Research โ€” when do starting credits actually get written?

The ยฝ-day trace that de-risks Feature #30016 (auto-book the clicked class) ยท researched 2026-08-02 on the live code + dev DB
โœ… VERDICT: Starting credits are written SYNCHRONOUSLY at checkout โ€” auto-book can fire immediately after purchase. No daily-batch lag (that only applies to the cosmetic group flip). A buyer whose plan carries StartingCreditsAmount > 0 has Available credit rows in billing.SessionCreditCustomer the moment the purchase response returns.

The traced path (all in-process, same request)

  1. FunnelService.Checkout loads the plan's credit config (PlanCreditConfiguration / PlanCreditTrialConfiguration) and attaches it to the subscription DTO. Fpt.Standard/Services/FunnelService.cs:383-461
  2. BillingService.ZiftSubscriptionCreate / SinglePaymentSubscriptionCreate โ†’ calls SessionCreditService.CreateSubscriptionCreditConfiguration inline (wrapped non-fatal โ€” a credit failure never fails the payment). Fpt.PlatformBilling/Services/BillingService.cs:2074, 2278
  3. SessionCreditService.CreateSubscriptionCreditConfiguration does three things immediately:
    a. inserts the SubscriptionCreditConfiguration row (NextCreditProcessDate = FirstBillingDate)
    b. BuildStartingCredits() โ†’ inserts one SessionCreditCustomer row per starting credit, Status=Available, expiry = now + ExpiredDays โ€” THIS IS THE ANSWER
    c. if FirstBillingDate โ‰ค today, also issues the first recurring grant (BuildCredits()) and advances the process date. Fpt.Services/Services/SessionCreditService.cs:143-169
  4. Future recurring grants come from the scheduled credit processor (AllSubscriptionCredit where NextCreditProcessDate <= today) โ€” that's the only batch in this system, and it never gates the first booking.

โš  Two landmines auto-book must design around

1. The GrantCreditAmount > 0 gate skips starting-credits-only plans. Both create paths guard the entire credit block with CreditConfiguration != null && GrantCreditAmount > 0. A plan configured with starting credits but NO recurring grant (exactly the shape of a widget intro pack: "5 sessions, no renewal") gets zero credits written โ€” silent, non-fatal, invisible until the buyer can't book. Dev has 2 such configs today (1 in each config table, of 87+29); rare, but it's precisely the plan type the Booking Widget sells. Fix candidate (1-line, when #30016 starts): widen the gate to GrantCreditAmount > 0 || StartingCreditsAmount > 0 at BillingService.cs:2074 and :2278.
2. Most plans have no credit config at all โ€” and that can be fine. The booking gate (KioskService) only demands credits when the class has IsSessionRulesActive = 1. Widget plan 205 (Trial 25) has no credit config; whether its buyer can book depends entirely on the selected classes' session-rules flag. Design implication for the builder: the SELL step should warn when a selected class enforces session rules but a selected plan grants no day-1 credits (this is the ClassStructureMembership coherence-warning gap we already parked, now with a concrete rule).

What this means for Feature #30016

ScenarioAuto-book outcome
Class WITHOUT session rulesBook immediately โ€” no credit needed
Class WITH rules + plan has StartingCredits > 0 AND GrantCreditAmount > 0Book immediately โ€” credits written in the same request
Class WITH rules + plan has StartingCredits > 0 but GrantCreditAmount = 0FAILS today (landmine 1) โ€” 1-line gate fix required
Class WITH rules + plan has no credit configFails by design โ€” builder coherence warning should prevent this configuration
Future start date (challenge)Starting credits still issue at purchase (BuildStartingCredits is unconditional inside the block); only the recurring grant waits for FirstBillingDate

Bottom line: auto-book = purchase โ†’ immediately call the existing booking path with the class instance the user tapped. No queues, no retries, no "we'll confirm your spot" fallback needed. Ship it with the gate fix + the builder warning.

Evidence