Accrue.Billing.SubscriptionActions (accrue v0.2.0)

Copy Markdown View Source

Phase 3 Plan 04 subscription write surface (BILL-03/04/06/07/08/09/10).

Every function here is exposed on Accrue.Billing via defdelegate (wired in Plan 01 Task 4). All public functions follow the dual-API foo/n + foo!/n pattern and emit an accrue_events row inside the same Repo.transact/2 as the DB mutation (EVT-04 invariant).

The intent_result tagged return (D3-06..12) is used for ops that can surface a requires_action PaymentIntent (subscribe, swap_plan, cancel when invoice_now: true). Non-intent ops return plain {:ok, %Subscription{}}.

Summary

Functions

cancel(sub, opts \\ [])

@spec cancel(
  Accrue.Billing.Subscription.t(),
  keyword()
) ::
  {:ok, Accrue.Billing.Subscription.t()}
  | {:ok, :requires_action, map()}
  | {:error, term()}

cancel!(sub, opts \\ [])

cancel_at_period_end(sub, opts \\ [])

@spec cancel_at_period_end(
  Accrue.Billing.Subscription.t(),
  keyword()
) :: {:ok, Accrue.Billing.Subscription.t()} | {:error, term()}

cancel_at_period_end!(sub, opts \\ [])

@spec cancel_at_period_end!(
  Accrue.Billing.Subscription.t(),
  keyword()
) :: Accrue.Billing.Subscription.t()

comp_subscription(billable, price_spec, opts \\ [])

@spec comp_subscription(term(), term(), keyword()) ::
  {:ok, Accrue.Billing.Subscription.t()} | {:error, term()}

Creates a free-tier ("comped") subscription with a 100%-off coupon applied. Skips the payment_method guard since there is nothing to charge.

The coupon referenced by coupon_id must exist in the processor's dashboard. Defaults to "accrue_comp_100_forever"; host apps create this once via Accrue.Billing.create_coupon/2 (landed in 04-05) or the Stripe Dashboard.

comp_subscription!(billable, price_spec, opts \\ [])

@spec comp_subscription!(term(), term(), keyword()) :: Accrue.Billing.Subscription.t()

Raising variant of comp_subscription/3.

get_subscription(id, opts \\ [])

@spec get_subscription(
  String.t(),
  keyword()
) :: {:ok, Accrue.Billing.Subscription.t()} | {:error, :not_found}

get_subscription!(id, opts \\ [])

@spec get_subscription!(
  String.t(),
  keyword()
) :: Accrue.Billing.Subscription.t()

pause(sub, opts \\ [])

@spec pause(
  Accrue.Billing.Subscription.t(),
  keyword()
) :: {:ok, Accrue.Billing.Subscription.t()} | {:error, term()}

pause!(sub, opts \\ [])

preview_upcoming_invoice(sub_or_customer, opts \\ [])

@spec preview_upcoming_invoice(
  Accrue.Billing.Subscription.t() | Accrue.Billing.Customer.t(),
  keyword()
) :: {:ok, Accrue.Billing.UpcomingInvoice.t()} | {:error, term()}

preview_upcoming_invoice!(sub_or_customer, opts \\ [])

resume(sub, opts \\ [])

@spec resume(
  Accrue.Billing.Subscription.t(),
  keyword()
) :: {:ok, Accrue.Billing.Subscription.t()} | {:error, term()}

resume!(sub, opts \\ [])

subscribe(billable, price_spec, opts \\ [])

@spec subscribe(term(), term(), keyword()) ::
  {:ok, Accrue.Billing.Subscription.t()}
  | {:ok, :requires_action, map()}
  | {:error, term()}

Creates a subscription for the given billable (or %Customer{}) against the configured processor. Returns intent_result(Subscription.t()).

subscribe!(billable, price_spec, opts \\ [])

@spec subscribe!(term(), term(), keyword()) :: Accrue.Billing.Subscription.t()

Raising variant of subscribe/3.

swap_plan(sub, new_price_id, opts)

@spec swap_plan(Accrue.Billing.Subscription.t(), String.t(), keyword()) ::
  {:ok, Accrue.Billing.Subscription.t()}
  | {:ok, :requires_action, map()}
  | {:error, term()}

swap_plan!(sub, price, opts)

unpause(sub, opts \\ [])

@spec unpause(
  Accrue.Billing.Subscription.t(),
  keyword()
) :: {:ok, Accrue.Billing.Subscription.t()} | {:error, term()}

unpause!(sub, opts \\ [])

update_quantity(sub, new_quantity, opts \\ [])

@spec update_quantity(Accrue.Billing.Subscription.t(), pos_integer(), keyword()) ::
  {:ok, Accrue.Billing.Subscription.t()} | {:error, term()}

update_quantity!(sub, new_quantity, opts \\ [])