Subscription — Luồng xử lý trong code
Subscription trải trên cả frontend (Tuke/Topi) và backend (Tux). Trang này nêu các đường chính; tên API/spec là điểm neo để tra cứu.
Luồng booking (khách hàng submit)
Guard trùng lịch (overlap validation)
Khi submit/edit/confirm, hệ thống so các schedule rows submit với:
- Enrollment đang
Submitted/Confirmed(soEnrollmentPattern). - TermBookingOrder normal đang
Submitted/Quote/Submitted_Change. - TermBooking normal đang
Approved/Attendance_Approved.
Trùng bất kỳ → toàn request fail (atomic, không tạo state một phần). Edit thì loại trừ EnrollmentId hiện tại để không tự xung đột. Direct-confirm và future-confirm dùng cùng guard.
Direct-confirm (admin)
- Chỉ admin/staff được dùng direct-confirm; khách/non-admin → từ chối.
- Dùng Subscription làm template, nhưng mutate runtime chỉ qua service confirmation hiện có (không sửa trực tiếp Enrollment/Invoice/Booking từ UI setup).
- Response không báo "confirmed success" trừ khi runtime đã hoàn tất confirmation semantics.
Billing Details: Schedule / Approve / Skip
| Hành động | Backend làm |
|---|---|
| Schedule | Tạo một InvoiceScheduler / invoice; ScheduledOn = Invoice.Date (UTC). |
| Approve | Update invoice → Approved; tạo InvoiceScheduler với ScheduledOn = DateTime.UtcNow. |
| Skip | Deactivate scheduler đang active (nếu có); update invoice → Initialised (0). |
Trang derive intent nút từ trạng thái invoice, không từ
EnrollmentInvoiceLog.
Manage Add-ons / Discounts
Ràng buộc: chỉ mutate state add-on selection thuộc enrollment; billing side effect đi qua service backend (popup không trực tiếp approve/skip/schedule/regenerate invoice).
Setup: các quy ước cần giữ khi code
| Quy ước | Ghi chú |
|---|---|
| Archive chỉ khi unpublished | Gói đã publish → server từ chối archive. |
CutOffMinute lưu phút, UI ngày | Decimal bị reject; 0/null = không có cut-off. |
Billing Type khóa Flat Rate | Request Dynamic bị reject/normalize. |
BillingOnly editable trước khi tạo | Sau khi tồn tại → read-only. |
| Add Price mới = blank | Không prefill từ price đã xem/lưu. |
| Rollover alert bị mute | Notification-only: không đổi state booking/enrollment/billing/term planner. |
Frontend (Subscription Manager)
- Filter subscription:
GET /api/Subscription(admin). Site filter giới hạn options theo site. - Đổi tab → tự reload theo filter hiện tại (không cần Apply). Response tab cũ không ghi đè data tab mới (chống race khi switch nhanh).
- Expanded row: hiện add-ons rồi discounts; có nút Update mở Manage Add-ons.
Nơi tìm code
Frontend ở Tuke/ (Next.js) và một phần Topi/ (admin cũ). Backend + API ở Tux/ (ConsumerEnrollment, Subscription, Invoice services).
Tiếp theo: Case thường gặp.