Master Data — Kiến trúc & dữ liệu
Dòng phụ thuộc
Master Data được đọc rộng, nhưng mutation phải đi qua owner đúng. Ví dụ: update avatar account holder = update Contact, không thêm field avatar vào Account.
Boundary rules
| Rule | Ý nghĩa |
|---|---|
| BU là security/config boundary | Query token/payment/customer/account phải scope theo BU khi nghiệp vụ yêu cầu. |
| Account Holder là Contact | “Account holder avatar” thuộc Contact.ProfileImage, không thuộc Account. |
| Program setup khác booking runtime | Sửa TPS/TermProduct không tự sửa booking đã confirm khi chưa có flow migration/adjustment rõ. |
| Image crop policy theo field | Avatar 1:1; wide course/activity image 16:9; generic file upload được exempt. |
| Site/program link ảnh hưởng availability | Booking/payment/subscription đọc config này để expose option, không tự sở hữu config. |
| Subscription Config chỉ sys-admin SuperAdmin BU | Tab Subscription Config + API giới hạn sys-admin ở BU TypeId = 99; gate dùng context đã load, không query BU thêm. |
_Enabled gate nhưng không xóa | Requirement customization ẩn dimension trên mọi surface nhưng giữ giá trị attendee/Product đã lưu; _Required chỉ áp dụng khi _Enabled. |
Site-category selection = StatusId | OrgProgramCategory.StatusId Approved (500) = selected, Initialised (0) = unselected; IsActive giữ true cho row canonical. |
| Staff create tự link site | Tạo staff RoleId = Staff tự tạo OrgEmployee active cho mọi Org active cùng BU (idempotent); Admin role và edit không auto-link. |
| Archived staff bị loại khỏi surface | Employee StatusId = Archived không xuất hiện ở link list, Weekly Planner hay shift selector dù IsActive = true. |
| TermProduct kế thừa Product | Sign In/Out Method và requirement copy từ Product sang TermProduct khi tạo course; không cho chọn thủ công ở New Course drawer. |
| ProgramCapacity đọc từ TPS capacity | Capacity program-level lấy từ TermProgramSetCapacity theo TermProgram.Date; không có record → unlimited (ProgramRemainingCount = 999). |
Dữ liệu chính
| Nhóm | Dữ liệu |
|---|---|
| Organization | Enterprise, BusinessUnit, Org, site relationship, custom URL. |
| Customer | Account, BusinessUnitAccount, Contact, account holder relationship. |
| Attendee | Attendee, measurements (Height/Weight), requirement values (SchoolYear/Level/SwimmingCompetency), profile/system image. |
| Subscription Config | Attendee_Subscription, Attendee_ProductSet, SubscriptionExtra/ProductSet scope. |
| Customization | Reference_Enabled/_Text/_Required/_Options cấp BU; CustomConsent1..3, measurement customization, Enterprise Setting units. |
| Program | Term, ProgramCategory, Program, TermProgramSet, TermProduct, TermProgramSetCapacity. |
| Links/settings | OrgProgramCategory, site-program category link, booking rule options, category payment option. |
| Staff links | Employee, OrgEmployee, EmployeePermissionTemplate, TrackingCode (colorCode). |
Program structure — hierarchy và capacity
- Hierarchy runtime:
ProgramCategory(TypeId)→Program→TermProgramSet→TermProduct; booking resolve session payload quaTermProductId. Programlà template;Program.Capacityđã bị xóa. Capacity program-level đọc từTermProgramSetCapacity(TermProgramSetId+Date); không có record cho ngày → unlimited (ProgramRemainingCount = 999), không block booking.- Capacity slot-level enforce ở
TermProduct; counters ởTermProductBookingCount(BookingCount/ReservedCount). TermProgramSetkhởi tạoStatus=Approved,PublishStatus=Unbookable. Delete bị chặn khi còn booking/order active; shrink date-range bị chặn nếu booking line nằm ngoài.
Ví dụ thực tế: Admin đặt capacity 20 cho
TermProgramSetTerm 2 nhưng bỏ trống ngày2026-06-15. → Không chặn oan booking ngày thiếu setup. → Ngày đóProgramCapacity= null →ProgramRemainingCount = 999, booking vẫn qua.
Requirement summary và special type
- Course requirement summary hiển thị row chỉ cho dimension có giá trị. Format:
{min} - {max}/{min} and above/Up to {max}; age suffixyears old; height/weight append unit label từ Enterprise Setting. - Summary chỉ hiển thị dimension có
<Reference>_Enabled = true, label từ_Text; ẩn dimension không tạo row trống. - Term Planner cho phép edit requirement/price metadata (manual override được giữ; chỉ ghi đè khi user overwrite/reset); Customer-facing summary read-only.
Product.SwimmingCompetencylà single value (nullablenvarchar(50)), copy sangTermProduct. Null = dimension chưa config; value đã xóa khỏi options vẫn giữ và vẫn match attendee.- Term Care
SpecialTypeId(1 = Special, 0 = Default) round-trip qua Program setup, propagate sangTermProgramSetactive cùng BU. Customer Portal tách special Term Care khỏi regular.
Ví dụ thực tế: Admin đặt
Product "Swim Level 2"requirementMinAge 5,MaxAge 7, Swimming CompetencyCompetent, labelWater Confidence. → Booking card hiển thị đúng nhu cầu. → Summary hiện5 - 7 years oldvàWater Confidence: Competent;TermProductmangCompetent; class card (Class/Subscription) có weekday tag, Holiday/Term Care thì không.
Event side effects
Nhiều master data change có thể publish EntityEvent để Platform sinh history/notification hoặc để projections refresh. Event không chuyển ownership; owner vẫn là aggregate gốc.