Stop billing the customer entirely. Drops the key rather than writing a json null, because every read tests key presence.
Returns the config it removed: that amount survives nowhere else, and the caller needs it for the audit entry it records.
The customer's fee configuration, or null when they are not billed one.
This customer's recorded fee changes, newest first.
Reads the shared admin activity feed rather than a table of the feature's
own, filtered by objectId and the customer.recurringFee.* types. Joins
the actor so the surface can name a person instead of a user id.
Recurring-fee charges, most recent first.
Reads fee_transfer directly rather than any table of the feature's own.
Selection and the period both come from data.recurringFee, which the
sweep stamps on every charge it makes, so the set is enumerable as a whole
rather than one customer at a time.
customerId is optional: omit it to enumerate every recurring fee taken,
and pair it with periodKey to pull a single month across the platform.
A period with no row here was never charged — the customer could not pay,
or is not yet due. That absence is the same signal listDue reads.
NOTE: the cross-customer form has no index behind it. fee_transfer is
indexed by account and by idempotency key, neither of which this predicate
uses, so an unscoped call scans. Fine for an operator report; add a jsonb
expression index on (data -> 'recurringFee' ->> 'periodKey') before
putting it on a hot path.
Customers to charge for periodKey: an ACTIVE fee on an ACTIVE customer
with no fee_transfer yet carrying this period's idempotency key.
The absent transfer is the claim, so the feature needs no cursor and no
table of its own. fee_transfer already has a partial unique index on
idempotency_key, and CustomerFeeTransferAdminService.create inserts
against it with ON CONFLICT DO NOTHING — so a customer who slips through
this query twice still cannot be billed twice.
A customer who could not pay leaves no transfer behind and so stays due: the nightly sweep re-attempts them and bills as soon as the account is funded, rather than writing off the month.
The period an instant falls in, in the billing timezone.
Set (or re-price) the fee. Validates the nominated source account exists and belongs to this customer — jsonb carries no check constraint, so the invariants are enforced here, on the one path that writes the key.
Preserves the current status, so re-pricing a paused fee does not silently resume billing.
Pause or resume billing without discarding the configured amount.
Charge one customer for one period.
Idempotent without a pre-check:
createis keyed on${customerId}:${periodKey}and returns the existing transfer rather than making a second one, so a Temporal retry, a concurrent sweep and a manual re-run all converge on the same charge.