Subscription — Architecture & data
This page sketches the main data "objects" and their relationships — conceptual view, not exact schema.
Relationship diagram (conceptual)
Two BillingSchedule levels
Core rule: Manage Add-ons/Discounts only uses
EnrollmentBillingSchedule(booked periods). This is invariantINV-SUB-ADDON-SCHEDULE-001andINV-SUB-DISCOUNT-SCHEDULE-001.
Ownership boundary
Important to avoid breaking consistency:
| Block | Who may change it |
|---|---|
| Subscription (template, price, product, content) | UI Setup |
| Enrollment / TermBookingOrder / TermBooking / Billing / Invoice / CreditNote (runtime) | Only existing booking/enrollment/confirmation services |
UI Setup / add-on popup does NOT directly approve/skip/schedule/regenerate invoice. Every billing recalculation goes through the backend service that owns that behavior.
Main APIs (read/write paths)
| Purpose | API |
|---|---|
| Billing schedule for booking | GET /api/ConsumerEnrollment/Subscriptions/{id}/BillingSchedules |
| Subscription metadata (price, product, linked term) | GET /api/ConsumerEnrollment/Subscriptions/{id} |
| Submit enrollment | POST .../ConsumerEnrollment/Submit |
| Options for Subscription Manager filter | GET /api/Subscription (admin, includes unpublished) |
| Booking options (customer) | GET /api/ConsumerEnrollment/Subscriptions |
Manager filter uses
GET /api/Subscription(admin, sees unpublished packages too); customer booking still usesConsumerEnrollment(only bookable packages). The two paths do not mix.
Units & data conventions to remember
| Field | Convention |
|---|---|
Subscription.CutOffMinute | Stored in minutes; UI displays whole days (1 day = 1440). Decimal is rejected. |
Subscription.TypeId | null/0 = BookingAndBilling; 1 = BillingOnly. |
| Booking Start/End Selection | 0 = Staff Only (default); otherwise Staff & Customer. |
| Billing Type | Hard-locked to Flat Rate (Dynamic not ready). |
Term & related booking
- Term = academic period. Subscription links to term through
SubscriptionTerm(fieldLinked). - "Normal" booking (
TermBookingOrder/TermBooking) is a different flow from subscription but intersects for schedule-clash validation — see Booking and Common cases.
Public-safe vs private
Customer-facing APIs (Course List, Step 1) only expose public-safe data: title, price info, weekday availability, description, site map metadata, closure-day. They do not expose private booking/enrollment/account/attendee/invoice/payment data. Every display path is read-only (does not mutate state).
Next: Codebase flow.