Master Data — Khái niệm cốt lõi
| Khái niệm | Nghĩa |
|---|---|
| Enterprise | Tổ chức cấp cao, có thể có custom URL và service-area policy. |
| BusinessUnit (BU) | Ranh giới dữ liệu/cấu hình chính: payment setting, billing setting, timezone, provider. |
| Org / Site | Cơ sở vật lý hoặc site thuộc BU, nơi chương trình/session diễn ra. |
| Account | Gia đình/customer account; thường là container cho account holder và attendee. |
| Account Holder / Contact | Contact đại diện account. Avatar/profile image thuộc Contact, không thuộc Account. |
| Attendee | Trẻ/người tham gia được booking/subscription/incident/finance tham chiếu. |
| Term | Kỳ học hoặc khoảng thời gian vận hành chương trình. |
| ProgramCategory | Loại chương trình (Term Care, Holiday, Class, Camp); giữ rule cấp category (TypeId quyết định hành vi card/session). |
| Program | Template chương trình trong category; giữ requirement metadata và SpecialTypeId (chỉ Term Care / Before-and-After-School-Care). |
| TermProgramSet (TPS) | Offering/course trong một term tại site/category; giữ lịch, requirement summary, publish state và capacity context. |
| TermProduct | Session/slot cụ thể mà booking chọn hoặc subscription schedule tham chiếu; kế thừa sign method và requirement từ Product. |
| TermProgramSetCapacity | Capacity cấp TPS theo ngày (TermProgram.Date); là nguồn ProgramCapacity khi check booking. |
| ProductSet | Bộ sản phẩm gán cho attendee qua Subscription Config; nguồn từ SubscriptionExtra.ProductSetId của Subscription được gán. |
| Attendee_Subscription | Gán đúng một Subscription active (cùng BU) cho attendee; gán Subscription khác sẽ replace row active. |
| Attendee_ProductSet | Association enable/disable ProductSet cho attendee; không có row active = ProductSet disabled. |
| Subscription Config | Tab trên Attendee Profile chỉ sys-admin trong BU TypeId = 99 (SuperAdmin) thấy; gán Subscription và cấu hình ProductSet. |
| Customization item | Code Reference_Enabled/_Text/_Required/_Options cấp BU điều khiển hiển thị/label/required của field attendee và requirement. |
| OrgProgramCategory | Link site–program category; StatusId Approved (500) = được chọn, Initialised (0) = chưa chọn; IsActive luôn true cho row canonical. |
| Employee / OrgEmployee | Staff + link staff–site; archived staff (StatusId = Archived) bị loại khỏi danh sách link, roster và shift selector. |
| TrackingCode | Mã phân loại ca/leave (TypeId Leave/Shift); có colorCode hiển thị swatch màu ở danh sách. |
| System image | Asset hệ thống hoặc uploaded image dùng cho avatar/course/activity, có crop policy. |
Entity hierarchy
Enterprise chứa BU; BU chứa site/org, account và config. Account giữ relationship tới account holder/contact và attendee. Program structure nối từ term/category/program tới TPS và term product.
Source entity vs runtime record
Master Data thường là source entity. Runtime record như TermBooking, Enrollment, Invoice, PaymentBatch chỉ tham chiếu master data để biết ai, ở đâu, thuộc chương trình nào.
Ownership ngắn gọn
| Owner | Sở hữu |
|---|---|
| Enterprise | Custom URL, service area policy cấp enterprise; HeightUnit/WeightUnit cho measurement display. |
| BusinessUnit | BU-scoped settings, customization items, data boundary. |
| Contact | Account holder profile image/avatar. |
| Attendee | Attendee profile/measurements/requirement values/product config/subscription config. |
| Program/Term structure | Category/program/TPS/product setup và availability. |
Subscription Config — gán Subscription và ProductSet cho attendee
- Tab
Subscription Configtrên Attendee Profile chỉ hiển thị cho sys-admin trong BUTypeId = 99(SuperAdmin). User khác hoặc sys-admin BU khác không thấy tab, bị chặn ở API. - Selector Subscription chỉ liệt kê Subscription cùng BU (
BusinessUnitId = CurrentBusinessUnitId),IsActive = true, không archived, sắp theoName. Chọn Subscription khác → replace gán hiện tại (tối đa một activeAttendee_Subscription). - Candidate ProductSet đi qua các add-on product active của Subscription và mapping active
ProductSetProducttới ProductSet active cùng BU;SubscriptionExtra.ProductSetIdđơn lẻ không đủ làm candidate. Attendee chưa gán Subscription → danh sách rỗng. - ProductSet không được Subscription tham chiếu → không hiện dù có row
Attendee_ProductSet. Row active cũ vẫn disable được để không orphan config sau khi đổi Subscription. - Enable/Edit dùng popup form. Enable tạo
Attendee_ProductSetactive (một active duy nhất cho cặp attendee/ProductSet); Disable soft-disable row, không đổiProductSet. - Cột hiển thị: Name, Effective Start (month picker, lưu ngày đầu tháng), Effective End (optional, ngày cuối tháng), Discount, Disc. Effective Date, Custom Price (NZD) optional. End không được trước start → block save + feedback.
Ví dụ thực tế: Gán
Subscription "Swim 2026"choAttendee "Lily"ở BU SuperAdmin. → Định phạm vi bộ sản phẩm hợp lệ. → Selector chỉ liệt kê cùng BU; chọnProductSet "Level 2 Kit"→ rowAttendee_ProductSetactive mới, không tạo row thứ hai.
Requirement customization — School Year / Level / Swimming Competency
- Mỗi reference
AttendeeSchoolYear,AttendeeLevel,AttendeeSwimmingCompetencycó customization_Enabled(defaultFalse),_Text(default tên field),_Required(defaultFalse). _Enabledlà gate hiển thị trên mọi surface: Attendee Profile, Product setup (Session/Class/Enrichment), Term Planner summary, Booking UI, Reports. Ẩn không xóa giá trị attendee/Product đã lưu._Textlà label dùng chung mọi surface;_Textrỗng → fallback default label._Requiredchỉ chặn submit khi reference đang_Enabled; chặn cảBasicProfileCompletedvà booking.AttendeeLevelpersistint NULL; thay đổi ghi entity event history nhưSchoolYear.AttendeeSwimmingCompetency_Optionslà JSON array (default["Non Swimmer","Learner","Competent"]) → dropdown single-select. Legacy value ngoài options vẫn hiển thị; save chỉ nhận giá trị trong options. Options hỏng → danh sách rỗng, form không vỡ.
Ví dụ thực tế: BU tắt
AttendeeLevel_Enabled, đổiAttendeeSchoolYear_TextthànhGrade, bậtAttendeeSwimmingCompetency_Required. → Bỏ dimension không dùng, đổi nhãn đồng bộ. → Surface nào cũng không render Level; labelGradexuất hiện ở mọi nơi; booking của attendee thiếu Swimming Competency bị từ chối.
Measurement customization — height/weight
Enterprise Setting.HeightUnit/WeightUnitlà unit metadata cho render height/weight. Để trống → UI bỏ label, không block field.AttendeeHeight_Enabled/_RequiredvàAttendeeWeight_Enabled/_Requiredđiều khiển field attendee (persistHeight/Weightnullable decimal).- Product
MinHeight/MaxHeight/MinWeight/MaxWeightlà requirement, chỉ hiển thị khi measurement tương ứng enabled. Chỉ là metadata hiển thị, không tự enforce eligibility booking.
Ví dụ thực tế: BU bật
AttendeeHeight_Enabled, tắtAttendeeWeight_Enabled. → Tránh hỏi thông tin không dùng. → Form attendee hiện Height, ẩn Weight; product form chỉ hiện cột Min/Max Height; booking không bị chặn bởi height range.
Business Unit và unified settings
- Business Unit là boundary của dữ liệu, permission và cấu hình. Luồng Add Business Unit chỉ tạo trong Enterprise hiện tại; client không thể mở rộng Enterprise/BU scope bằng ID tùy ý.
- Bootstrap settings dùng ba audience snapshot
Admin,Shared,Customer, gộp scope Enterprise → Business Unit → Org → Program Category → Org Program Category. Route GET cũ là compatibility adapter; settings edit vẫn dùng endpoint aggregate tương ứng. - Mọi write settings, kể cả logo/banner/square logo, invalidate cache theo hierarchy trước khi trả thành công; loader dedupe request đang bay và bỏ qua response stale.
Ví dụ thực tế: Admin đổi banner Enterprise rồi mở Customer Portal ngay. → Không chờ TTL một giờ. → Write invalidate Enterprise → BU → Org, lần đọc sau lấy snapshot mới.
Chuẩn hóa tên và nhãn đơn vị
- Backend normalize các field name/code đã định nghĩa ở mọi tracked save, import/bulk path; field edit không đổi thì không bị rewrite.
Account.Namecollapse nhiều khoảng trắng nội bộ, các field khác chỉ trim biên. - Giá trị measurement lưu giữ nguyên (
lbvẫn là stored value); lớp hiển thị maplbthànhlbsvà resolve unit theo từng field qua các mức setting, không dừng ở object setting thiếuweightUnit.
Ví dụ thực tế: Form gửi
" Kai Zhang ". → Dữ liệu hiển thị/search ổn định. →Account.Namelưu thành"Kai Zhang"; field nullable gửinullvẫn lànull.
Enrollment form customization — consent fields
CustomConsent1..3là consent field cấu hình cấp BU vớiEnabled,Required,Text,Description(shape nhưPhotoConsent).Text= label,Description= helper text (rỗng thì không render container rỗng);Requiredchỉ áp dụng khiEnabled.- Câu trả lời persist nullable boolean theo attendee; payload rỗng → giữ null, không chọn Yes/No.
MedicalDeclarationvàTreatmentConsenthỗ trợDescriptionmetadata nhưPhotoConsent.
Ví dụ thực tế: BU bật
CustomConsent1vớiText "Chấp thuận chụp ảnh",Required true, thêm Description. → Thu thập đồng ý rõ ràng. → Form enrollment render label + helper; submit không chọn → validation fail; sau saveCustomConsent1 = truecho attendee đó.