101 lines
3 KiB
Elixir
101 lines
3 KiB
Elixir
defmodule Towerops.Billing.BillingNotifier do
|
|
@moduledoc """
|
|
Email notification service for billing events.
|
|
|
|
Sends emails for payment failures, subscription updates, and billing alerts.
|
|
"""
|
|
|
|
use Gettext, backend: ToweropsWeb.Gettext
|
|
|
|
import Swoosh.Email
|
|
import ToweropsWeb.GettextHelpers
|
|
|
|
alias Towerops.Mailer
|
|
alias Towerops.Organizations
|
|
|
|
require Logger
|
|
|
|
defp deliver(recipient, subject, body) do
|
|
from_address = Application.get_env(:towerops, :mailer_from, {"Towerops", "hi@towerops.net"})
|
|
|
|
email =
|
|
new()
|
|
|> to(recipient)
|
|
|> from(from_address)
|
|
|> subject(subject)
|
|
|> text_body(body)
|
|
|
|
case Mailer.deliver(email) do
|
|
{:ok, _metadata} ->
|
|
Logger.info("Billing email sent to #{recipient}: #{subject}")
|
|
{:ok, email}
|
|
|
|
{:error, reason} = error ->
|
|
Logger.error("Failed to send billing email to #{recipient}: #{inspect(reason)}")
|
|
error
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Deliver payment failure notification to organization owners and admins.
|
|
|
|
Sends an email to all organization owners and admins informing them of a payment
|
|
failure and providing a link to update their payment method.
|
|
"""
|
|
def deliver_payment_failed_notification(organization) do
|
|
# Get all owners and admins (people who can manage billing)
|
|
recipients =
|
|
organization.id
|
|
|> Organizations.list_organization_members()
|
|
|> Enum.filter(fn membership -> membership.role in [:owner, :admin] end)
|
|
|> Enum.map(fn membership -> membership.user end)
|
|
|
|
if Enum.empty?(recipients) do
|
|
Logger.warning("No owners or admins found for organization #{organization.slug} to notify about payment failure")
|
|
|
|
{:ok, []}
|
|
else
|
|
subject = t_email("Payment failed for %{org_name}", org_name: organization.name)
|
|
|
|
body =
|
|
t_email(
|
|
"""
|
|
Hi,
|
|
|
|
We were unable to process the payment for your %{org_name} subscription on Towerops.
|
|
|
|
Your subscription is still active, but we'll retry the payment in a few days. To avoid service interruption, please update your payment method as soon as possible.
|
|
|
|
You can update your payment method here:
|
|
%{billing_url}
|
|
|
|
If you have any questions or need assistance, please don't hesitate to reply to this email.
|
|
|
|
Thank you,
|
|
Towerops Team
|
|
""",
|
|
org_name: organization.name,
|
|
billing_url: billing_portal_url(organization)
|
|
)
|
|
|
|
results =
|
|
Enum.map(recipients, fn user ->
|
|
deliver(user.email, subject, body)
|
|
end)
|
|
|
|
# Return success if at least one email was sent
|
|
if Enum.any?(results, &match?({:ok, _}, &1)) do
|
|
{:ok, results}
|
|
else
|
|
{:error, :all_emails_failed}
|
|
end
|
|
end
|
|
end
|
|
|
|
defp billing_portal_url(organization) do
|
|
# Generate URL to billing settings page
|
|
# In production, this should use the configured app URL
|
|
base_url = Application.get_env(:towerops, :app_url, "https://towerops.net")
|
|
"#{base_url}/o/#{organization.slug}/settings#billing"
|
|
end
|
|
end
|