Tài liệu nội bộ · Đã chốt với client (Option A) · Dùng cho FE / BE / QA handoff
Internal · Knowledge transfer · v2 chi tiết
Deploy & Fork — Sync to LMS
Tổng hợp đầy đủ 2 flow: Save → Deploy (sync roster) và
Set Up for New Trimester (Fork), kèm timeline LMS, thuật toán lookup,
nhánh Perpetual, rule duplicate/lineage, ví dụ end-to-end và checklist QA.
Client confirmedModule code = LMS type 101Roster = Offering type 3Cập nhật: 2026-07-21
Lỗi hiểu phổ biến — tránh
Đừng map CB “Module code” = Offering code (type 3). Offering code thường khác Module code,
và mỗi Offering chỉ gắn 1 semester — không thể giữ nguyên code khi fork sang kỳ mới.
2. Mô hình Option A (đã chốt)
Client chọn: Module code = LMS Module 101, khóa trên mọi fork; mỗi fork Deploy tìm
coursesite mới qua Module code + trimester; roster theo Offering / CB version.
CB v1code INF1001 T = AY 26/27 T1
→
LMS 101INF1001
→
Offering2610 → roster A
Fork (Set Up for New Trimester) — cùng Module code
CB v2code INF1001 T = AY 26/27 T2
→
cùng LMS 101INF1001
→
Offering mới2620 → roster B
v1 và v2 độc lập về roster. Student enrolled v1 không tự thấy v2.
CB sở hữu
Nội dung / version module
Catalog trimester + ngày
Binding: version ↔ Offering (sau Deploy)
Quyền truy cập theo roster đã sync
LMS sở hữu
Module 101 (tạo sớm)
Offering 3 (thường ~2 tuần trước kỳ)
Enrollment thật trên Offering
Semester / Ongoing
3. Timeline thực tế (LMS vs CB)
Đây là lý do bắt buộc tách Save và Deploy.
Thời gian ──────────────────────────────────────────────►
[Sớm — trước kỳ lâu]
LMS: Module 101 đã có (IT/admin)
CB: Instructor Save Sync LMS
✓ verify 101
✗ chưa cần Offering
✗ chưa sync roster
[~2 tuần trước start trimester]
LMS: Course Offering (3) được tạo + gắn semester 4-digit
CB: Cửa sổ Deploy mở (rule 2 weeks)
Deploy: tìm Offering + sync roster
✗ không thấy Offering → block + error
[Trong kỳ]
CB module deployed; roster tiếp tục sync theo cơ chế sync hiện có
Instructor có thể Fork chuẩn bị kỳ sau (tạo undeployed fork)
Perpetual
Không có “start trimester” → không áp cửa sổ 2 tuần theo cùng cách.
Deploy vẫn cần tìm được ≥1 Offering non-4-digit dưới Module 101.
4. Field Deployment + Admin trimester
4.1 Form Module Details → Deployment (Sync LMS)
Field
Bắt buộc
UI control
Lưu / dùng khi nào
Enrolment type
Có
Select
Doc này = Sync to LMS
Module code
Có
Text input
Save: verify 101. Deploy: P1 key.
Micro-credential
Không
Select từ list Admin
Save: fallback verify 101. Deploy: P2.
Trimester
Không
Dropdown label thân thiện
Có giá trị = theo kỳ. Trống = Perpetual. Deploy dùng mã 4 số.
4.2 Admin tạo trimester
UI Admin luôn hiện / nhập label thân thiện (vd AY 26/27 T1).
Backend convert & store 4-digit LMS run code: format YY + T + 0.
Vẫn cho đổi settings (ngoài scope chi tiết doc này).
5. Flow Save — chi tiết từng bước
Mục tiêu Save
Lưu cấu hình enrolment + xác nhận Module identity trên LMS.
Không bind Offering. Không sync student list.
User điền form & bấm Save
Enrolment = Sync LMS; Module code bắt buộc; MC optional; Trimester optional (dropdown).
Validate CB — duplicate code
Tìm module khác trong CB có cùng Module code / MC code.
Cùng version lineage (gốc + các fork) → không coi là duplicate.
Khác lineage → lỗi: “A module with this Module Code already exists.”
Verify LMS Module (101)
Search LMS orgstructure / API cho Module type 101 có code =
Module code (ưu tiên) hoặc MC code nếu dùng fallback verify.
Không tìm thấy → lỗi: “Module Code not found. Please verify the code in the LMS and try again.”
Tìm thấy → cho phép Save (có thể trả về title LMS để hiển thị / rename theo feedback UI cũ).
Persist trên CB
Lưu enrolment type, moduleCode, mcId/code, trimesterId (nullable), trạng thái “saved / ready to deploy”.
Chưa có binding Offering id.
Implication implement
Save path phải gọi lookup Module (101), không gọi
findCourseOfferingByCode(moduleCode) như model cũ (Offering-as-code).
Decision tree Save
Save Sync LMS
├─ duplicate code ngoài lineage? ──YES──► ERROR duplicate
└─ NO
├─ LMS Module 101 (moduleCode)? ──YES──► SAVE OK
└─ NO
├─ có MC code & LMS 101 (mcCode)? ──YES──► SAVE OK
└─ NO ──► ERROR module not found
(Không search Offering. Không check trimester trên LMS.)
6. Flow Deploy — lookup & roster
Mục tiêu Deploy
Resolve đúng Course Offering(s) trên LMS, bind vào CB version, sync enrollment theo role matrix.
Nếu 0 Offering → block.
6.1 Điều kiện trước Deploy (có trimester)
Module đã Save Sync LMS thành công.
Trong cửa sổ ~2 tuần trướctrimester.startDate.
LMS đã có Offering cho kỳ đó (IT tạo — CB không tạo).
6.2 Thuật toán lookup (có trimester)
Chuẩn hóa trimester key
Từ dropdown selection → lấy mã 4 số đã store (vd 2610).
Priority 1 — Module code + trimester
Tìm Module 101 theo Module code → liệt kê Offering con → giữ Offering có semester code = 2610
(hoặc tương đương mapping đã thống nhất).
Priority 2 — MC code + trimester (fallback)
Nếu P1 = 0 Offering: lặp lại với MC code (cũng là Module 101) + cùng trimester.
Xử lý kết quả
0 → block Deploy + error (Offering chưa có / sai code / sai kỳ).
1 → bind Offering đó; sync roster.
N → merge roster tất cả Offering khớp; grant theo LMS–CB role mapping matrix.
Deploycó trimester
→
P1Module code + 4-digit
→
P2MC code + 4-digit
→
Roster1 hoặc merge N
Lookup uniqueness không guarantee → luôn implement nhánh N = merge.
Map role LMS → role CB theo matrix (Learner, Instructor, …).
User chỉ thấy CB version họ được grant — không nhảy sang fork khác.
Merge N Offerings
Client xác nhận: gộp roster mọi Offering khớp.
Edge còn mở: cùng user khác role trên 2 Offering → cần rule resolve (priority / union) khi code.
7. Nhánh Perpetual (trimester trống)
Định nghĩa
Dropdown trimester không chọn → CB coi module là Perpetual.
Vẫn Sync LMS được. Không hiện / không cho Set Up for New Trimester.
7.1 Save
Giống module có trimester: chỉ cần Module 101 tồn tại.
7.2 Deploy — rule chọn Offering
Tìm Module 101
Theo Module code (rồi MC nếu fallback).
Lọc Offering
Giữ Offering có semester code KHÔNG thuộc format 4-digit YY+T+0.
Ví dụ ứng viên: Semester_Ongoing, empty, text khác không phải run code kỳ.
0 / 1 / N
Giống Deploy thường: 0 block; 1 sync; N merge roster.
7.3 Ví dụ trực quan
LMS Module 101 · INF1001
├── Offering A · semester 2610 → BỎ (là run code kỳ)
├── Offering B · semester 2620 → BỎ
├── Offering C · semester Ongoing → LẤY
└── Offering D · semester Open → LẤY (cũng ≠ 4-digit)
CB: Sync LMS · Module code INF1001 · Trimester = (trống)
Deploy → merge roster C + D → grant vào CB perpetual module
(User không được UI “chọn enrollment” — hệ thống tự lọc)
OK 1 non-term
Sync đúng 1 Offering Ongoing.
OK N non-term
Merge roster; không picker.
Fail 0 non-term
Block Deploy + error.
Khác biệt với “có trimester”
Key không còn là Module + 2610 mà là
Module + (semester ∉ 4-digit set).
Instructor chỉ để trống dropdown — không nhập free-text semester LMS.
8. MC code & Priority 2
Cách MC hoạt động
Admin tạo MC “rỗng”: MC code + title (chưa gắn module).
Editor gắn module vào MC từ list.
Deploy P1 fail → P2: search LMS Module 101 bằng MC code + trimester (hoặc rule perpetual).
Đổi so với note cũ
Trước đây từng hiểu MC = exact-match Offering (3).
Client reply mới: MC = Module (101), cùng kiểu Priority 1.
Hệ quả
Nhiều CB module cùng một MC code có thể Deploy P2 vào cùng Offering(s) → share roster (đã từng được product chấp nhận trong discussion cũ).
P2 không phải “nhảy thẳng tới 1 Offering code” nữa — vẫn phải + trimester / perpetual filter.
9. Flow Fork — Set Up for New Trimester
9.1 Ai được fork?
Điều kiện
Được fork?
Có trimester (không Perpetual)
Có
Perpetual (trimester trống)
Không
Enrolment = Sync LMS vs non-LMS
Không liên quan — cả hai đều fork được nếu có trimester
Module thuộc / không thuộc MC
Không liên quan — fork theo từng module
9.2 Gate: một undeployed fork / lineage
User bấm Set Up for New Trimester
Kiểm tra lineage
Đã tồn tại fork cùng lineage ở trạng thái undeployed?
Có → block action; dẫn user tới fork hiện có (không tạo thêm).
Không → tiếp tục tạo.
Tạo version mới
Clone nội dung theo rule fork product; giữ Module code;
gắn trimester mới (user chọn); enrolment/LMS settings kế thừa theo product;
trạng thái undeployed cho đến khi Deploy thành công.
Fork không tạo Offering LMS
CB chỉ chuẩn bị version nội dung. Offering kỳ mới do IT LMS tạo.
Deploy version mới mới đi tìm Offering + sync roster kỳ mới.
9.3 Sau fork — Deploy version mới
Lineage INF1001
├── v1 T=AY25/26 T1 (2610) DEPLOYED → Offering A · roster cũ
└── v2 T=AY26/27 T1 (2610*) UNDEPLOYED (fork mới)
Save: OK — cùng Module code, cùng lineage ≠ duplicate
Deploy khi tới cửa sổ 2 tuần:
P1 INF1001 + trimester mới → Offering B
sync roster B vào v2
v1 vẫn giữ roster A
9.4 Những gì fork thay đổi / không đổi
Giữ nguyên
Module code (101)
Lineage identity
(Thường) Sync LMS flag / MC gắn — confirm khi impl nếu product có ngoại lệ
Đổi / tách
Trimester mới
CB version mới (nội dung clone)
Offering + roster riêng sau Deploy
Enrollment học viên không mang từ version cũ
Chi tiết “fork clone gì” (collaborator, history, staff copy) theo SRS/discussion cũ —
gate undeployed + who-can-fork lấy từ client reply mới nhất.
10. Duplicate & lineage
Tình huống
Cùng Module code?
Save OK?
Lý do
Hai module độc lập (khác lineage)
Có
Không
Duplicate thật
v1 deployed + v2 fork cùng lineage
Có (bắt buộc)
Có
Cùng lineage ≠ duplicate
v2 undeployed đã tồn tại, tạo fork nữa
—
Fork blocked
Max 1 undeployed / lineage
Module khác dùng lại code sau khi lineage cũ archived?
Chưa chốt trong reply — cần Product nếu gặp case
11. Kịch bản end-to-end
S1 Happy path — có trimester
1. Admin tạo trimester “AY 26/27 T1” → BE store 2610 + start/end
2. LMS đã có Module 101 code INF1001 (Offering chưa có)
3. Editor Save: Module code INF1001, T=AY 26/27 T1 → verify 101 OK → saved
4. ~2 tuần trước start: IT tạo Offering semester 2610 dưới INF1001
5. Editor Deploy → P1 khớp 1 Offering → sync roster → deployed
6. Cuối kỳ: Set Up for New Trimester → v2 (undeployed), cùng INF1001, chọn T2
7. Tới cửa sổ T2: Deploy v2 → Offering 2620 → roster mới
S2 Happy path — Perpetual
1. Editor Save: INF1001, trimester trống → verify 101 OK
2. LMS có Offering dưới Ongoing (semester ≠ 4-digit)
3. Deploy → lọc non-4-digit → sync roster Ongoing
4. UI không hiện “Set Up for New Trimester”
S3 Save sớm nhưng Deploy sớm quá / Offering chưa có
1. Save OK (101 có)
2. Deploy trước khi IT tạo Offering HOẶC ngoài cửa sổ 2 tuần
3. → block Deploy (0 Offering hoặc window rule)
4. User đợi Offering / đúng cửa sổ rồi Deploy lại
S4 Module code sai trên LMS
Save → không tìm thấy 101
→ “Module Code not found. Please verify the code in the LMS and try again.”
→ không lưu Sync LMS thành công
S5 Hai Offering cùng Module + trimester
Deploy P1 trả về Offering X và Y (cùng 2610)
→ merge roster X∪Y
→ mọi user (sau map role) được access CB module version đó
→ không hiện UI chọn X hay Y
S6 Fork khi đã có undeployed
v1 deployed, v2 undeployed đã tồn tại
User bấm Set Up for New Trimester lần nữa
→ block + deep-link / chỉ đường tới v2
→ phải Deploy (hoặc hủy theo rule product) trước khi fork tiếp
S7 Priority 2 — Module code không ra Offering, MC có
P1: Module code + 2610 → 0 Offering
P2: MC code (101) + 2610 → 1 Offering
→ Deploy OK bằng P2
(Lưu ý: nhiều CB module cùng MC có thể share roster Offering đó)
12. Gợi ý UI / state
Trước Deploy (Sync LMS)
Form Module code / MC / Trimester editable
Save riêng với Deploy
Trimester = dropdown + option trống (Perpetual)
CTA Deploy disabled nếu ngoài window / chưa Save
Sau Deploy (Sync LMS)
LMS mapping locked (Change Settings không mở lại Sync fields)
Hiện trạng thái linked / last sync nếu có
Fork CTA chỉ khi có trimester
Copy / UX đã từng request
Đổi “Edit” → “Change Settings”; success Save có thể show Module code + LMS module name
(và rename CB title theo LMS) — thuộc feedback UI riêng, không contradict model này.
13. Bảng lỗi & message
Bước
Điều kiện
Message / hành vi (client)
Save
Duplicate code ngoài lineage
“A module with this Module Code already exists.”
Save
Không có LMS Module 101
“Module Code not found. Please verify the code in the LMS and try again.”
Fork
Đã có undeployed fork
Block + điều hướng tới fork hiện có
Deploy
0 Offering (term hoặc perpetual)
Block + error (Offering missing / mismatch)
Deploy
Ngoài cửa sổ 2 tuần (có trimester)
Block theo deploy-window rule
14. FE / BE / QA — ai làm gì
Frontend
Dropdown trimester + empty = perpetual
Ẩn fork khi perpetual
Message lỗi Save/Deploy/Fork
Deep-link undeployed fork
Lock fields sau Deploy Sync LMS
Backend
Trimester: label ↔ 4-digit
Save: lookup Module 101
Deploy: P1/P2 + perpetual filter
Merge roster N
Lineage duplicate + undeployed gate
Bind Offering id(s) per version
QA
Chạy S1–S7
Staging: 101 vs Offering code
Ongoing / 4-digit filter
Fork gate + same code Save
Deploy window 2 weeks
15. Checklist QA (copy nhanh)
☐ Admin tạo trimester hiện label; DB/API có mã 2610 (không 2601)
☐ Save với Module code = 101 thật → success; = Offering code → fail “not found” (nếu code khác)
☐ Save trùng code khác lineage → duplicate error
☐ Save trùng code cùng lineage (fork) → OK
☐ Deploy có T trước cửa sổ 2 tuần → blocked
☐ Deploy đúng cửa sổ, Offering có → roster đúng Offering đó
☐ Deploy 0 Offering → error, không partial grant
☐ Deploy N Offering cùng kỳ → user từ cả hai Offering vào được
☐ Perpetual: bỏ Offering 4-digit, lấy Ongoing
☐ Perpetual: không có CTA fork
☐ Fork lần 1 → tạo undeployed; Fork lần 2 → block + link v2
☐ Sau Deploy v2: v1 roster không đổi; v2 roster kỳ mới
☐ P2 MC = 101 + trimester khi P1 miss
☐ Sau Deploy Sync LMS: không edit lại Module code / trimester
16. Edge còn mở (không chặn bắt đầu impl)
Edge
Câu hỏi
Workaround tạm
Perpetual semester shape
Field nào? Exact value Ongoing / Semester_Ongoing / empty?
Implement “không match regex 4-digit YY+T+0”; refine sau khi probe LMS
Merge role conflict
Cùng user 2 role trên 2 Offering?
Follow role matrix; nếu conflict → chọn role “cao hơn” (cần Product confirm)
Duplicate wording
Check Module code, MC code, hay cả hai? Message chỉ nói Module Code
Validate cả hai; message theo field đang conflict
Archived lineage reuse code
Module mới được dùng lại code cũ?
Hỏi Product khi gặp
Kết luận cho team
Model Save / Deploy / Fork / Perpetual đã đủ để bắt đầu design kỹ thuật & ticket.
Các edge trên tinh chỉnh lúc implement + probe LMS, không đảo Option A.