Subscription — Codebase flow
Subscription spans both frontend (Tuke/Topi) and backend (Tux). This page lists the main paths; API/spec names are anchors for lookup.
Booking flow (customer submit)
Schedule-clash guard (overlap validation)
On submit/edit/confirm, the system compares submitted schedule rows with:
- Enrollment in
Submitted/Confirmed(compareEnrollmentPattern). - Normal TermBookingOrder in
Submitted/Quote/Submitted_Change. - Normal TermBooking in
Approved/Attendance_Approved.
Any clash → whole request fails (atomic, no partial state). Edit excludes the current EnrollmentId so it does not self-conflict. Direct-confirm and future-confirm use the same guard.
Direct-confirm (admin)
- Only admin/staff may use direct-confirm; customer/non-admin → rejected.
- Uses Subscription as template, but runtime mutation happens only through existing confirmation services (UI setup does not directly mutate Enrollment/Invoice/Booking).
- Response does not say "confirmed success" unless runtime confirmation semantics are complete.
Billing Details: Schedule / Approve / Skip
| Action | Backend does |
|---|---|
| Schedule | Creates one InvoiceScheduler / invoice; ScheduledOn = Invoice.Date (UTC). |
| Approve | Updates invoice → Approved; creates InvoiceScheduler with ScheduledOn = DateTime.UtcNow. |
| Skip | Deactivates active scheduler (if any); updates invoice → Initialised (0). |
Page derives button intent from invoice status, not from
EnrollmentInvoiceLog.
Manage Add-ons / Discounts
Constraint: only mutate add-on selection belonging to the enrollment; billing side effects go through backend service (popup does not directly approve/skip/schedule/regenerate invoice).
Setup: conventions to keep when coding
| Convention | Note |
|---|---|
| Archive only when unpublished | Published package → server rejects archive. |
CutOffMinute stores minutes, UI days | Decimal rejected; 0/null = no cut-off. |
Billing Type locked to Flat Rate | Dynamic request rejected/normalized. |
BillingOnly editable before create | After it exists → read-only. |
| New Add Price = blank | Do not prefill from viewed/saved price. |
| Rollover alert muted | Notification-only: does not change booking/enrollment/billing/term planner state. |
Frontend (Subscription Manager)
- Subscription filter:
GET /api/Subscription(admin). Site filter limits options by site. - Changing tab → auto-reload by current filter (no Apply needed). Old tab response does not overwrite new tab data (prevents race on fast switch).
- Expanded row: shows add-ons then discounts; Update button opens Manage Add-ons.
Where to find code
Frontend is in Tuke/ (Next.js) and partly Topi/ (old admin). Backend + API are in Tux/ (ConsumerEnrollment, Subscription, Invoice services).
Next: Common cases.