Accrue.Billing.Query (accrue v0.3.1)

Copy Markdown View Source

Composable Ecto.Query fragments mirroring the Accrue.Billing.Subscription predicates (D3-04).

Every predicate in Subscription has a matching query fragment here. Use these in where clauses instead of accessing raw .status — BILL-05 forbids raw status access outside this module and Subscription itself (enforced by Accrue.Credo.NoRawStatusAccess).

All functions accept an optional queryable (default Accrue.Billing.Subscription) and compose via |>:

import Ecto.Query

from(s in Subscription, where: s.customer_id == ^id)
|> Accrue.Billing.Query.active()
|> Repo.all()

Summary

Functions

Subscriptions counted as active (includes :trialing).

Subscriptions that are terminated (:canceled, :incomplete_expired, or any ended_at).

Subscriptions that are :active with cancel_at_period_end set and a period end still in the future — i.e. the cancel hasn't landed yet.

Subscriptions eligible for a BILL-15 dunning sweep tick: strictly :past_due, with past_due_since older than the grace window, and with no prior dunning_sweep_attempted_at stamp (D4-02).

Subscriptions that are past due or unpaid (dunning territory).

Subscriptions that are paused (legacy :paused status or non-nil pause_collection).

Subscriptions currently in trial.

Functions

active(query \\ Subscription)

@spec active(Ecto.Queryable.t()) :: Ecto.Query.t()

Subscriptions counted as active (includes :trialing).

canceled(query \\ Subscription)

@spec canceled(Ecto.Queryable.t()) :: Ecto.Query.t()

Subscriptions that are terminated (:canceled, :incomplete_expired, or any ended_at).

canceling(query \\ Subscription)

@spec canceling(Ecto.Queryable.t()) :: Ecto.Query.t()

Subscriptions that are :active with cancel_at_period_end set and a period end still in the future — i.e. the cancel hasn't landed yet.

dunning_sweep_candidates(grace_days, query \\ Subscription)

@spec dunning_sweep_candidates(pos_integer(), Ecto.Queryable.t()) :: Ecto.Query.t()

Subscriptions eligible for a BILL-15 dunning sweep tick: strictly :past_due, with past_due_since older than the grace window, and with no prior dunning_sweep_attempted_at stamp (D4-02).

past_due(query \\ Subscription)

@spec past_due(Ecto.Queryable.t()) :: Ecto.Query.t()

Subscriptions that are past due or unpaid (dunning territory).

paused(query \\ Subscription)

@spec paused(Ecto.Queryable.t()) :: Ecto.Query.t()

Subscriptions that are paused (legacy :paused status or non-nil pause_collection).

trialing(query \\ Subscription)

@spec trialing(Ecto.Queryable.t()) :: Ecto.Query.t()

Subscriptions currently in trial.