defmodule Plausible.Billing.Subscription.Status do @moduledoc """ The subscription statuses are stored in Paddle. They can only be changed through Paddle webhooks, which always send the current subscription status via the payload. * `active` - All good with the payments. Can access stats. * `past_due` - The payment has failed, but we're trying to charge the customer again. Access to stats is still granted. There will be three retries - after 3, 5, and 7 days have passed from the first failure. After a failure on the final retry, the subscription status will change to `paused`. As soon as the customer updates their billing details, Paddle will charge them again, and after a successful payment, the subscription will become `active` again. * `paused` - we've tried to charge the customer but all the retries have failed. Stats access restricted. As soon as the customer updates their billing details, Paddle will charge them again, and after a successful payment, the subscription will become `active` again. * `deleted` - The customer has triggered the cancel subscription action. Access to stats should be granted for the time the customer has already paid for. If they want to upgrade again, new billing details have to be provided. Paddle documentation links for reference: * Subscription statuses - https://developer.paddle.com/classic/reference/zg9joji1mzu0mdi2-subscription-status-reference * Payment failures - https://developer.paddle.com/classic/guides/zg9joji1mzu0mduy-payment-failures """ @statuses [:active, :past_due, :paused, :deleted] @type status() :: unquote(Enum.reduce(@statuses, &{:|, [], [&1, &2]})) for status <- @statuses do defmacro unquote(status)(), do: unquote(status) def unquote(:"#{status}?")(nil), do: false def unquote(:"#{status}?")(subscription), do: subscription.status == unquote(status) end defmacro in?(subscription, expected) do expected_expanded = Enum.map(expected, &Macro.expand(&1, __CALLER__)) if expected_expanded -- Plausible.Billing.Subscription.Status.valid_statuses() != [] do raise ArgumentError, "Invalid subscription statuses provided: #{inspect(expected_expanded)}" end quote bind_quoted: [subscription: subscription, expected: expected] do if is_nil(subscription), do: false, else: Map.get(subscription, :status) in expected end end def valid_statuses() do @statuses end end