Accrue.Billing.Customer (accrue v0.3.0)

Copy Markdown View Source

Ecto schema for the accrue_customers table.

The Customer is the fully-realized polymorphic schema linking a host app's billable record (User, Organization, Team, etc.) to a processor customer (e.g. Stripe cus_xxx).

Polymorphic ownership

owner_type and owner_id are explicit string columns (D2-01, D2-02), lossless across UUID, bigint, ULID, or any future PK format. The composite unique index (owner_type, owner_id, processor) enforces one customer per billable per processor.

Metadata

The metadata field follows the exact Stripe metadata contract (D2-07): flat %{String.t() => String.t()}, max 50 keys, keys max 40 chars, values max 500 chars, no nested maps. See Accrue.Billing.Metadata.

Optimistic locking

All writes use Ecto.Changeset.optimistic_lock/2 on lock_version to prevent torn writes when a user update and webhook reconcile race on the same customer (D2-09).

Phase 3 additions

  • default_payment_method_id — FK to accrue_payment_methods with ON DELETE SET NULL. Set via set_default_payment_method/2 (Plan 06), which asserts attachment before updating.
  • last_stripe_event_ts / last_stripe_event_id — webhook watermark

Summary

Functions

Builds a changeset for creating or updating a Customer.

Types

t()

@type t() :: %Accrue.Billing.Customer{
  __meta__: term(),
  charges: term(),
  data: term(),
  default_payment_method: term(),
  default_payment_method_id: term(),
  email: term(),
  id: term(),
  inserted_at: term(),
  invoices: term(),
  last_stripe_event_id: term(),
  last_stripe_event_ts: term(),
  lock_version: term(),
  metadata: term(),
  name: term(),
  owner_id: term(),
  owner_type: term(),
  payment_methods: term(),
  preferred_locale: term(),
  preferred_timezone: term(),
  processor: term(),
  processor_id: term(),
  subscriptions: term(),
  updated_at: term()
}

Functions

changeset(customer_or_changeset, attrs \\ %{})

@spec changeset(
  %Accrue.Billing.Customer{
    __meta__: term(),
    charges: term(),
    data: term(),
    default_payment_method: term(),
    default_payment_method_id: term(),
    email: term(),
    id: term(),
    inserted_at: term(),
    invoices: term(),
    last_stripe_event_id: term(),
    last_stripe_event_ts: term(),
    lock_version: term(),
    metadata: term(),
    name: term(),
    owner_id: term(),
    owner_type: term(),
    payment_methods: term(),
    preferred_locale: term(),
    preferred_timezone: term(),
    processor: term(),
    processor_id: term(),
    subscriptions: term(),
    updated_at: term()
  }
  | Ecto.Changeset.t(),
  map()
) :: Ecto.Changeset.t()

Builds a changeset for creating or updating a Customer.

Validates required fields, enforces Stripe-compatible metadata constraints, and applies optimistic locking.