Repository navigation
billing: a plan row states its reload bound and the reload it switches on - #6
Merged
Merged
Conversation
…s on
plan.Limits gains reloadsPerDay (the most automatic reloads a day for an
org the plan serves; absent is the sweep's ReloadsPerDay, 0 is unbounded)
and reload {thresholdCents, amountCents} (the auto-recharge rule buying the
plan with a card switches on). Both persist in the row's envelope, are
compared by the seed, and stay off the public catalog's Capacity.
The sweep reads the bound from the authority row the org's own account is
served from; an unbounded plan skips the daily check and keeps the count.
The rule's perDay reports that bound. A card sale to the org's own account
on a plan with a reload switches the rule on through the same write the
endpoint uses (card on file, amount bounds), leaving a rule the org
switched on as it stands; a rule that cannot be written is logged and the
sale stands.
Claude-Session: https://claude.ai/code/session_016DKtyuzxU43Gsc6Pm9vKTF
YearlyTotal answers AnnualTotal, else the legacy rung's stated year, and 0 for a row stating neither, so planAtInterval refuses a yearly purchase of such a row with "plan %q is not sold annually". PriceAnnual is a per-month price tag and is never multiplied into a charge. Claude-Session: https://claude.ai/code/session_016DKtyuzxU43Gsc6Pm9vKTF
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A plan row now states its own auto-reload behaviour, so a plan can switch auto-reload on when it is bought and can lift the daily reload bound. Both are data on the row, edited with the plan.
What changed
plan.Limits(models/plan), stored in the row's envelope, compared by the seed, and never served byGET /v1/billing/plans(Capacitystays capacities only):reloadsPerDay(*int): the most automatic reloads a day for an org the plan serves. Absent uses the package boundReloadsPerDay(3, unchanged for every plan that says nothing).0means unbounded.reload(*plan.Reload{thresholdCents, amountCents}): the auto-recharge rule that buying the plan with a card switches on.Sweep (
api/billing/autorecharge.go). The sweep reads the bound from the authority row the org's own account is served from (servedSubscription→servedAs→ plan row by slug). An unbounded plan skips the daily check; the day's count is still kept. A bounded plan's refusal names its own bound. The rule'sperDayreports the org's real bound.Card sale (
api/billing/subscribe_card.go). Once a card has paid the first period, a sale to the org's own account on a plan with areloadswitches the org's rule on. It goes through the same write asPUT /v1/billing/recharge, so the card-on-file check and amount bounds still apply. A rule the org already switched on is left as it stands; one switched off, or no rule at all, is set to the plan's figures. If the rule cannot be written, the failure is logged and the sale stands.Separate commit (
models/planYearlyTotal). Only a stated year is billed annually:AnnualTotal, else the legacy rung's stated year. A row stating neither answers 0, so a yearly purchase is refused withplan %q is not sold annually.PriceAnnualis a per-month price tag and is never multiplied into a charge.Data, not code
No row in the embed changes. An Ultra row would carry
"limits": {"reloadsPerDay": 0, "reload": {"thresholdCents": 1000, "amountCents": 5000}}, written through the admin plan op.Tests
api/billing/reload_test.goandmodels/plan/reload_test.go, covering an unbounded plan reloading past 3 a day, a plan's bound of 1 being kept and named, the default for no bound and for no plan, the public catalog carrying neither field, buying a plan with a reload switching the rule on, buying without one storing no rule, the org's own switched-on rule being kept and a switched-off one being set, and the envelope round-trip.api/billing/monthly_test.go.TestPlanAtIntervalnow passes in full. Already failing onorigin/mainand not touched here:TestSubscribeTrial_NoChargeCardVaultedTrialing.Rollout
Cloud picks this up with a commerce tag and a
go.modpin.https://claude.ai/code/session_016DKtyuzxU43Gsc6Pm9vKTF