Documentation
¶
Overview ¶
Package allotment grants a plan's recurring monthly included-usage credit to a tenant's prepaid balance.
Design (decomplected from the rest of billing):
The included monthly allotment is granted as an ordinary, tag-scoped, expiring Deposit transaction — the SAME mechanism as billing/credit's welcome credit. It therefore flows through TallyTransactions → balance → available with NO new balance-computation path, and the Hanzo gateway's prepaid balance gate (available > 0) honors it transparently. Usage withdrawals burn the deposit down; overage draws down purchased balance / is billed via the payment processor.
Non-accumulating: each grant expires at the end of its UTC month, so an unused remainder does not roll over. TallyTransactions already excludes expired deposits, so expiry needs no extra gate logic.
Idempotent per (user, period): the deposit is tagged with a period-scoped tag ("included-credit:YYYY-MM"). Re-running the grant for the same user in the same month is a safe no-op, which makes the monthly scheduler and any manual re-trigger naturally exactly-once.
The dollar amount per plan is catalog-derived (see billing.IncludedMonthlyCents, sourced from @hanzo/plans limits.includedCreditUsd). This package never hardcodes plan economics — callers pass the resolved cents in.
Index ¶
Constants ¶
const Kind = "iam-user"
Kind is the destination kind for IAM-bound balance transactions.
const TagPrefix = "included-credit"
TagPrefix is the stable prefix for monthly-allotment deposit tags. The full tag is TagPrefix + ":" + period (e.g. "included-credit:2026-06").
Variables ¶
This section is empty.
Functions ¶
func GrantedCents ¶
GrantedCents returns the total included-allotment credit currently granted to `user` for the UTC month containing `at` (sum of non-voided period-tagged deposits). Zero when none granted. Used by the rollup to report the included amount actually on the balance, independent of the catalog.
Types ¶
type Result ¶
type Result struct {
Granted bool `json:"granted"`
Reason string `json:"reason,omitempty"`
TransactionId string `json:"transactionId,omitempty"`
AmountCents int64 `json:"amountCents"`
Period string `json:"period"`
Tag string `json:"tag"`
}
Result describes the outcome of a grant attempt.
func Grant ¶
func Grant(db *datastore.Datastore, user, plan string, cents int64, at time.Time, test bool) (Result, error)
Grant idempotently grants `cents` of included monthly usage credit to `user` for the UTC month containing `at`. It is a no-op (Granted=false) when:
- cents <= 0 (plan has no included allotment), or
- a grant for the same (user, period) already exists.
The check-and-create runs inside a datastore transaction so concurrent schedulers cannot double-grant. `test` marks the deposit test-only (mirrors the org.Live convention used elsewhere in billing).