Accrue.Billing.CouponActions (accrue v0.3.0)

Copy Markdown View Source

Coupon and promotion-code write surface.

Thin wrappers around the processor's coupon + promotion-code endpoints. The local accrue_coupons + accrue_promotion_codes tables are a thin projection — the processor is canonical and Accrue mirrors only the fields the admin LiveView needs.

Functions

  • create_coupon/2 — creates a coupon via the processor, persists a local row, records a "coupon.created" event.
  • create_promotion_code/2 — creates a promotion code via the processor, persists a local row FK'd to the coupon, records a "promotion_code.created" event.
  • apply_promotion_code/3 — looks up a local promotion code by its customer-facing code, validates active / expires_at / max_redemptions, then calls Processor.update_subscription(sub_id, %{coupon: coupon_id}). Records a "coupon.applied" event on success.

All public functions follow the dual-API foo/n + foo!/n pattern. Processor calls run inside Repo.transact/2 here because coupon create is not SCA-capable — there's no asynchronous 3DS leg to keep outside the transaction.

Summary

Functions

Attaches a promotion code to a subscription by looking up the local %PromotionCode{} row by customer-facing code, validating applicability, then calling the processor's update_subscription with %{coupon: coupon_processor_id}.

Creates a coupon through the configured processor and persists a local %Coupon{} row plus a "coupon.created" event.

Creates a promotion code through the configured processor and persists a local %PromotionCode{} row FK'd to the underlying coupon. Records a "promotion_code.created" event.

Types

apply_error()

@type apply_error() ::
  :not_found
  | :inactive
  | :expired
  | :max_redemptions_reached
  | :coupon_missing
  | term()

Functions

apply_promotion_code(sub, code, opts \\ [])

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

Attaches a promotion code to a subscription by looking up the local %PromotionCode{} row by customer-facing code, validating applicability, then calling the processor's update_subscription with %{coupon: coupon_processor_id}.

Returns {:ok, %Subscription{}} on success. On validation failure returns {:error, :not_found | :inactive | :expired | :max_redemptions_reached} before making any processor call.

A "coupon.applied" event is recorded inside the same Repo.transact/2 as the processor call on success.

apply_promotion_code!(sub, code, opts \\ [])

Raising variant of apply_promotion_code/3.

create_coupon(params, opts \\ [])

@spec create_coupon(
  map(),
  keyword()
) :: {:ok, Accrue.Billing.Coupon.t()} | {:error, term()}

Creates a coupon through the configured processor and persists a local %Coupon{} row plus a "coupon.created" event.

params is a map of processor-shape attrs. Supply a caller-chosen :id to pin a deterministic coupon id (required for the comp flow's "accrue_comp_100_forever" seed coupon).

create_coupon!(params, opts \\ [])

@spec create_coupon!(
  map(),
  keyword()
) :: Accrue.Billing.Coupon.t()

Raising variant of create_coupon/2.

create_promotion_code(params, opts \\ [])

@spec create_promotion_code(
  map(),
  keyword()
) :: {:ok, Accrue.Billing.PromotionCode.t()} | {:error, term()}

Creates a promotion code through the configured processor and persists a local %PromotionCode{} row FK'd to the underlying coupon. Records a "promotion_code.created" event.

params[:coupon] MUST be the processor-side coupon id (e.g. "accrue_comp_100_forever" or "SUMMER25").

create_promotion_code!(params, opts \\ [])

@spec create_promotion_code!(
  map(),
  keyword()
) :: Accrue.Billing.PromotionCode.t()

Raising variant of create_promotion_code/2.