Giao diện
SAPP-26297 Chuyển nhượng học viên (tool sapp.011) - FS Overview ​
File tổng quan + index của FS. Mỗi User Story là 1 file riêng trong cùng thư mục (
US-S<nn>-<slug>.md). Các phần dùng chung (tổng quan, flow tổng, related features, NFR, Open Questions, References) đặt tập trung tại đây — file US chỉ tham chiếu ID, không lặp lại.FS as-built: mô tả hành vi đúng tại commit
e77c47a, dựng từ feature inventory 26297 (đã qua Gate R1). Tool chỉ gọi và chấm nghiệp vụ chuyển nhượng của SAPP — logic chuyển nhượng thật nằm ở hệ thống SAPP (Ops API, LMS API, hubspot-service), không do mind_keep cài. Mọi "kỳ vọng" của case là văn bản tool hiển thị (lấy từ guide QA của SAPP-26297), không phải rule của mind_keep.
| Field | Value |
|---|---|
| Doc ID | FS-SAPP-26297 |
| Mode | B – As-built |
| As-built tại commit | e77c47a |
| Last Updated | 2026-09-30 |
| Author | AI (lane ba/) |
| Reviewers | BA |
| Status | DRAFT |
| Figma Project | N/A — as-built, không có Figma |
| Related BRD | ../../brd/brd-as-built-v0.1-20260930.md |
| Related Impact Matrix | N/A — Mode B (as-built), không có Impact Analysis |
1. Tổng quan dự án ​
Sub-tool sapp.011 "SAPP 26297: Chuyển nhượng học viên" (màn /works/sapp/tools/sapp-26297) là bộ test có hướng dẫn cho tính năng chuyển nhượng suất học của SAPP (ticket SAPP-26297, nhánh sapp-sprint-49). Tester nhập một bộ id dùng chung (fixture), chọn môi trường dev / staging, rồi đi qua 9 tab luồng / 78 case; mỗi case gồm các bước gọi API tự chấm, chạy câu SQL đã lập danh mục trên DB Ops, hoặc hướng dẫn tay. Tool gọi thật SAPP Ops API, SAPP LMS API và HubSpot qua backend của mind_keep. Ops / LMS / SQL không có đường production; riêng HubSpot, lựa chọn staging dùng portal HubSpot production (cấu hình nền tảng) — ⚠️ Ghi PROD ở luồng 5–6, xem NFR-S-02 và OQ-S-19.
1.1 Bối cảnh ​
- Guide QA của SAPP-26297 có 6 luồng (chuyển nhượng, hủy, các trạng thái bị chặn, LMS, đồng bộ lại ticket HubSpot, mail). Chạy tay đòi hỏi dựng dữ liệu bằng SQL, gọi API Ops và so từng mã lỗi — tool gom các thao tác đó thành case bấm chạy và tự chấm (Fact:
fe/src/ui/components/works/sapp/sapp-26297-tool.tsx:214-219). - Sổ cái trao đổi với SAPP mô tả phạm vi: "dựng test cho tool
sapp-26297— chuyển nhượng học viên, hiển thị khóa học trên LMS, đồng bộ lại ticket HubSpot, mail thông báo" (nguồn:shared/external/sapp/sapp-26297/README.md). - Luồng 4–6 phụ thuộc 11 câu hỏi MIND gửi SAPP ngày 2026-09-25, đang
⏳ Wait SAPP(nguồn:shared/external/sapp/sapp-26297/2026-09-25-mind-sapp-26297-cau-hoi.md) → xem OQ-S-10.
1.2 Mục tiêu ​
- Trích nguồn (
shared/external/sapp/sapp-26297/2026-09-25-mind-sapp-26297-cau-hoi.md, mục "Bối cảnh" và lời mở đầu): tool "gọi Ops qua backend của tool, chạy SQL trên DB Ops dev/staging và tự chấmerror.code"; mục tiêu là "biết cái đang có hoạt động thế nào, để tool gọi đúng và chấm đúng". [Assumption]KPI / kết quả kỳ vọng ở cấp nghiệp vụ (vd giảm thời gian QA một vòng regression, ai ký nhận kết quả) — chưa có trả lời G-05 → OQ-S-18.
1.3 In Scope ​
- Màn
/works/sapp/tools/sapp-26297: chọn môi trường, banner cảnh báo GHI, fixture, 9 tab luồng (Chuẩn bị · Dọn, 1, 2, 3A, 3B, 3C, 4, 5, 6), 78 case, 3 loại bước (US-S01). - 14 thao tác BE × 2 môi trường = 28 route
/api/v1/sapp/{dev|staging}/sapp-26297/*(6 Ops, 1 LMS, 7 HubSpot). - Catalogue SQL
s26297.*— 39 entry: 20 chỉ-đọc, 19 ghi (US-S01, US-S02; cơ chế runner ở US-P09). - Seed tool
sapp.011(migration1786300000000-seed-tool-sapp-26297.ts).
1.4 Out Of Scope ​
- Cơ chế nền tảng dùng chung (chỉ link, không mô tả lại): khoá / trạng thái tool (US-P02), cấu hình
env_systems(US-P04), auto-login + transport Ops (US-P08), SQL runner (US-P09) — xem §3. - Nghiệp vụ phía SAPP: máy trạng thái chuyển nhượng, bảng mã lỗi Ops, logic ẩn lớp trên LMS, đồng bộ hubspot-service, gửi mail — tool chỉ gọi và chấm theo guide QA.
- Môi trường production của Ops / LMS / DB Ops (không có route, không có khoá URL, không có lựa chọn trên màn — NFR-S-02). Lưu ý: HubSpot
staging= portal prod (OQ-S-19). - Test Scenarios / User Guide (quyết định R0 trong
project-decisions.md).
1.5 Roles And Permissions ​
| Role ID | Role Name | Description | Permission Summary |
|---|---|---|---|
| R1 | Người dùng tool | Người mở màn sapp-26297 để chạy case test. Assumption (OQ về G-01) — code không có role: route @Public(), màn chỉ qua ToolGate | Thấy màn khi tool sapp.011 được mở cho viewer (US-P02); gọi được mọi route 26297 không cần đăng nhập (NFR-P-01) |
2. Luồng tổng quan của dự án ​
text
[Mở /works/sapp/tools/sapp-26297] (ToolGate sapp.011 → US-P02)
↓
[Chọn môi trường dev | staging · nhập fixture] US-S01
↓
[Tab "Chuẩn bị · Dọn" — case 0.1 kiểm tiền điều kiện] US-S02
↓
[Luồng 1 Chuyển nhượng] US-S03 ──→ [Luồng 2 Hủy] US-S04
↓ ↓
[3A Chặn chuyển nhượng] US-S05 [3C Chặn hủy] US-S07
[3B Chặn xóa học viên] US-S06
↓
[Luồng 4 LMS] US-S08 (⏸ lỗi 13058 tới khi có URL LMS)
[Luồng 5 HubSpot đồng bộ lại] US-S09 (⏸ guard SAPP chặn)
[Luồng 6 Mail] US-S10 (kiểm tay; 6.5–6.7 phụ thuộc luồng 5)
↓
[Tab "Chuẩn bị · Dọn" — case 0.2 dọn dữ liệu] US-S02Mỗi case = danh sách bước; mỗi bước là một trong 3 loại (US-S01):
text
call → điền field từ fixture → preview → [xác nhận nếu GHI] → gọi route 26297 → tự chấm ✓/✗ → (ghi ngược fixture)
sql → panel SQL catalogue s26297.<prefix> → chạy theo id trên DB Ops env → (ghi ngược fixture) → US-P09
guide → chỉ hiển thị các dòng hướng dẫn tay3. Các tính năng liên quan ​
| Mã | Tính năng liên quan | Link tài liệu | Loại liên quan | Mục bị ảnh hưởng ở feature kia | Mục ảnh hưởng ở feature hiện tại | Mô tả ảnh hưởng |
|---|---|---|---|---|---|---|
| REL-01 | Khoá / trạng thái tool (ToolGate) | US-P02 | Affects | - | US-S01.M1 - mở màn | Màn chỉ hiện khi tool sapp.011 có trong DB mind_keep và đang mở cho viewer |
| REL-02 | Cấu hình env_systems | US-P04 | Affects | - | US-S08.M1 - mọi bước gọi LMS; US-S01 - credentials Ops | Thiếu SAPP_LMS_API_URL_DEV / _STAGING ⇒ luồng 4 trả lỗi 13058; credentials Ops dùng cho auto-login |
| REL-03 | Ops passthrough (auto-login, transport) | US-P08 | Affects | - | US-S01.M2 - bước gọi API Ops/LMS | 6 thao tác Ops dùng token staff auto-login; thao tác LMS dùng chung transport nhưng với token học viên |
| REL-04 | Ops SQL runner | US-P09 | Affects | - | US-S01.M3, US-S02 - bước SQL | Bước SQL chạy câu s26297.* theo id qua runner dùng chung; không nhận SQL thô, không có key prod |
| REL-05 | SAPP-26878 — loại bước dùng chung | US-D03 | Affects / Be Affected | US-D03 - bước sql; catalogue SQL 26878 | US-S01.M3 - panel SQL, điền token {key} | 26297 dùng lại panel SQL và bộ điền token của 26878. Hai catalogue dùng chung không gian id — trùng id thì API không khởi động (NFR-S-05) |
| REL-06 | Dịch vụ HubSpot dùng chung + bảng môi trường HubSpot | FS nền tảng — overview | Affects | - | US-S09, US-S10 - tạo contact / ticket / kéo stage | Môi trường HubSpot staging dùng lại credentials portal prod (be/libs/constants/src/lib/hubspot/hubspot.constants.ts:19-26) ⇒ tab staging ghi HubSpot production; tạo contact trùng email ⇒ dùng lại và ghi đè property (DR-S-04) |
| REL-07 | Hệ thống SAPP (Ops API, LMS API, hubspot-service) — ngoài repo | shared/external/sapp/sapp-26297/README.md | Affects | - | Mọi US luồng | Kết quả chấm phụ thuộc hành vi và cấu hình SAPP; luồng 4–6 chờ 11 câu trả lời (OQ-S-10) |
4. User Story Index ​
| US ID | Tên User Story | File | Role | Priority | Status |
|---|---|---|---|---|---|
| US-S01 | Nhập fixture và chạy một case (gọi API · SQL · hướng dẫn, tự chấm, ghi ngược fixture) | US-S01-chay-case.md | R1 | N/A — as-built | Draft |
| US-S02 | Chuẩn bị điều kiện và dọn dữ liệu sau test | US-S02-chuan-bi-don-du-lieu.md | R1 | N/A — as-built | Draft |
| US-S03 | Chuyển nhượng suất học cho học viên khác (luồng 1) | US-S03-chuyen-nhuong.md | R1 | N/A — as-built | Draft |
| US-S04 | Hủy chuyển nhượng (luồng 2) | US-S04-huy-chuyen-nhuong.md | R1 | N/A — as-built | Draft |
| US-S05 | Kiểm tra các trạng thái chặn chuyển nhượng (luồng 3A) | US-S05-chan-chuyen-nhuong.md | R1 | N/A — as-built | Draft |
| US-S06 | Kiểm tra các trạng thái chặn xóa học viên (luồng 3B) | US-S06-chan-xoa-hoc-vien.md | R1 | N/A — as-built | Draft |
| US-S07 | Kiểm tra các trạng thái chặn hủy chuyển nhượng (luồng 3C) | US-S07-chan-huy-chuyen-nhuong.md | R1 | N/A — as-built | Draft |
| US-S08 | Kiểm tra khoá học của học viên trên LMS (luồng 4) | US-S08-lms-khoa-hoc.md | R1 | N/A — as-built | Draft (Đã triển khai — chưa chạy được end-to-end) |
| US-S09 | Đồng bộ lại qua ticket HubSpot (luồng 5) | US-S09-hubspot-dong-bo-lai.md | R1 | N/A — as-built | Draft (Đã triển khai — chưa chạy được end-to-end) |
| US-S10 | Kiểm tra mail thông báo (luồng 6) | US-S10-mail.md | R1 | N/A — as-built | Draft |
Status =
Draftcho mọi US — as-built chờ Gate R2.
5. Non-functional Requirements ​
| ID | Requirement | Applies To (US/màn/API) | Acceptance Criteria |
|---|---|---|---|
| NFR-S-01 | Quyền truy cập: cả 28 route /api/v1/sapp/{dev|staging}/sapp-26297/* là @Public() — thuộc hiện trạng chung, xem NFR-P-01 của FS nền tảng. Màn chỉ chặn bằng ToolGate (US-P02); 26297 không dùng khoá bí mật cứng | Mọi US | Gọi route không kèm JWT vẫn nhận kết quả (be/apps/api/src/sapp/sapp-26297.controller.ts:79,104,129,…,618). Cố ý hay nợ → OQ-S-06 |
| NFR-S-02 | Không có route production: controller chỉ khai báo route dev/… và staging/…; khoá URL LMS chỉ có dev/staging; màn chỉ cho chọn dev/staging; SQL runner không có key prod. ⚠️ Ngoại lệ HubSpot: route staging/…/hubspot/* gọi môi trường HubSpot "staging", mà nền tảng cố ý trỏ về credentials portal prod ⇒ 4 thao tác GHI HubSpot (tạo contact, tạo ticket, sửa ticket / kéo stage) ở tab staging ghi vào HubSpot production — trái với banner "Không có route production" (OQ-S-19) | Mọi US; ngoại lệ US-S09, US-S10 | Không tồn tại route prod/sapp-26297/* (sapp-26297.controller.ts:39-40 · be/libs/constants/src/lib/sapp/sapp-26297.constants.ts:8-16 · fe/src/data/services/sapp/sapp-26297.service.ts:16 · sapp-26297-tool.tsx:223). Ngoại lệ: sapp-26297.controller.ts:431,498,540 · hubspot.constants.ts:19-26 |
| NFR-S-03 | Bảo mật token LMS học viên: token không ghi xuống trình duyệt (chỉ sống tới khi đóng tab), ô kiểu password; gửi qua header X-Lms-Token (không phải Authorization), chỉ dùng cho một lần gọi, không lưu; transport ghi log tham số, không ghi header | US-S01, US-S08 | sapp-26297-tool.tsx:39-56 · fe/src/data/services/sapp/sapp-26297.service.ts:100-115 · be/libs/modules/src/lib/sapp/sapp-26297.common.service.ts:188-194 |
| NFR-S-04 | Log lỗi: mỗi route ghi log lỗi theo tên handler khi thất bại | Mọi route | sapp-26297.controller.ts:55-76 |
| NFR-S-05 | Nhất quán catalogue SQL: bản FE và BE của catalogue s26297.* phải giống nhau (39 entry; so tự động tại e77c47a — khớp); id mà case tham chiếu thiếu trong bản FE ⇒ màn lỗi khi tải; id trùng với catalogue 26878 ⇒ API không khởi động | US-S01, US-S02 | fe/src/ui/components/works/sapp/sapp-26297-flows.ts:321-349 · be/libs/constants/src/lib/sapp/sapp-ops-sql.constants.ts:10-27 |
6. Open Questions ​
| ID | Question | Owner | Due Date | Status | Blocks (US) |
|---|---|---|---|---|---|
| OQ-S-01 | Ai là người dùng tool (QA SAPP, dev MIND, BA…)? Code không có role (G-01; inventory Q-01) | BA | Gate R2 | Open | Mọi US (Role) |
| OQ-S-02 | ⚠️ Observed O-01 — cố ý hay bug? Ô để trống bị bỏ khỏi payload ⇒ không xoá được property HubSpot qua tool (API mind_keep coi chuỗi rỗng là "xoá property"). Case 5.1, 5.7 không dựng được như mô tả; 6.3 khi contact bị dùng lại thì tên cũ vẫn còn (G-06; inventory Q-02, R-30) | BA → FE | Gate R2 | Open | US-S09, US-S10 |
| OQ-S-03 | ⚠️ Observed O-02 — cố ý hay bug? Case 3.1 / 3.2: ô transfer_to_class_id mặc định rỗng, nút Chạy không khoá; quên điền ⇒ Ops trả 422 thay vì mã 100331 (inventory Q-04) | BA → FE | Gate R2 | Open | US-S05 |
| OQ-S-04 | ⚠️ Observed O-03 — cố ý hay bug? user_y trống thì tự lấy user_x; case 3.10 khi đó gửi user_x,user_x và luôn có 1 check fail, dễ hiểu nhầm là Ops lỗi (inventory Q-05) | BA → FE | Gate R2 | Open | US-S06 |
| OQ-S-05 | ⚠️ Observed O-04 — cố ý hay bug? Check "lớp biến mất" trên LMS (so chuỗi id lớp ở bất kỳ đâu trong body) đạt giả nếu LMS chỉ trả mã lớp hoặc trả body lỗi; chờ SAPP câu 3 (shape /courses) (inventory Q-09) | BA → FE / SAPP | Chờ SAPP | Open | US-S08 |
| OQ-S-06 | ⚠️ Observed O-05: route GHI Ops/HubSpot dev/staging @Public() — cố ý (chấp nhận vì chỉ dev/staging) hay tạm thời? (G-02; inventory Q-03) — xem NFR-P-01 | BA → BE | Gate R2 | Open | Mọi US |
| OQ-S-07 | ⚠️ Observed O-06: hộp xác nhận GHI ("GHI dữ liệu trên Ops …") và hộp lỗi ("Không gọi được Ops qua API") dùng nhãn "Ops" cho cả thao tác HubSpot / LMS — chấp nhận hay sửa? (inventory Q-15) | BA → FE | Không chặn | Open | US-S01 |
| OQ-S-08 | ⚠️ Observed O-07 / O-08: route đọc contact HubSpot tồn tại nhưng không bước nào dùng; bước pipeline/owner không chấm, không tự ghi fixture — dự định bổ sung hay bỏ? (inventory Q-06) | BA | Không chặn | Open | US-S09 |
| OQ-S-09 | ⚠️ Observed O-09: dọn dữ liệu xoá cứng mọi bản ghi lịch sử A→B, C→B (không lọc ngày) và ép A, B, C về NORMAL ở cả 3 lớp bất kể trạng thái gốc — cố ý? (inventory Q-05) | BA | Không chặn | Open | US-S02 |
| OQ-S-10 | Luồng 4, 5, 6 phụ thuộc 11 câu đang chờ SAPP (URL LMS, token học viên, shape /courses, pipeline/stage, guard "Ticket đã được xử lý", cột user_hubspot_enrollments, bảng log mail…). FS ghi US-S08 / US-S09 là "Đã triển khai — chưa chạy được end-to-end" — BA xác nhận cách ghi này? (G-08; inventory Q-09) | BA / SAPP | Chờ SAPP | Open | US-S08, US-S09, US-S10 |
| OQ-S-11 | Migration seed sapp.011 đã chạy ở môi trường nào? Thiếu row thì màn bị khoá (G-09; inventory Q-10) | BA → BE | Gate R2 | Open | US-S01 |
| OQ-S-12 | Các route GHI (chuyển nhượng, hủy, xoá học viên, ghi HubSpot) đã chạy thật lần nào chưa? (handover 0045/0046: chưa, tính đến 2026-09-25) (inventory Q-11) | BA / QA | Không chặn | Open | US-S03 → US-S07, US-S09, US-S10 |
| OQ-S-13 | Mã lỗi thật của case 1.10 và 3.20 — hiện tool chỉ chấm success=false (inventory Q-12) | SAPP | Không chặn | Open | US-S03, US-S07 |
| OQ-S-14 | Guide QA của SAPP-26297 (nguồn mọi case / kỳ vọng) nằm ở đâu? Không có trong repo (G-10; inventory Q-13) | BA | Không chặn | Open | Mọi US luồng |
| OQ-S-15 | Staging chạy nhánh Ops nào? Màn ghi "Test trên nhánh sapp-sprint-49" cho cả hai môi trường (inventory Q-14) | SAPP | Không chặn | Open | US-S01 |
| OQ-S-16 | Case 1.A: sự kiện Kafka HubSpot chỉ bắn cho A, không cho B — BA SAPP muốn thế nào? (tool chỉ ghi chú) (inventory Q-07) | BA SAPP | Không chặn | Open | US-S03 |
| OQ-S-17 | Case 4.8: WITHDRAWN vẫn hiện trên LMS — đúng ý nghiệp vụ SAPP-28419? (inventory Q-08) | BA SAPP | Không chặn | Open | US-S08 |
| OQ-S-19 | ⚠️ Ghi PROD — cố ý hay bug? Tab staging của 26297 ghi HubSpot production (tạo / dùng lại + ghi đè contact thật trùng email, tạo ticket, kéo stage ⇒ kích hoạt đồng bộ + mail thật phía SAPP) vì môi trường HubSpot "staging" = portal prod; banner và comment controller lại nói "không có route production". Inventory 26297 ghi "HubSpot (portal dev/staging)" — chưa gắn cờ điểm này (phát hiện khi viết FS, đọc tại hubspot.constants.ts:19-26 mà Gate R1 X-3 đã trích). Liên quan G-03 / G-04 | BA → BE | Gate R2 | Open | US-S09, US-S10 |
| OQ-S-18 | Mục đích nghiệp vụ / KPI của tool ngoài câu trích từ sổ cái SAPP (G-05) — dùng cho "So that" và §1.2 | BA | Gate R2 | Open | Mọi US |
6b. Drift: tài liệu ↔ code ​
| ID | Tài liệu nói | Code đang làm (bằng chứng file:dòng) | Ảnh hưởng | Owner quyết |
|---|---|---|---|---|
| DR-S-01 (inventory DR-01) | shared/api-docs/sapp.md:2756-2758: tool "covers transferring a seat, reverting the transfer, and removing learners — flows 1–3" | Tool có 9 tab / 6 luồng (+ LMS, HubSpot, mail), 28 route (sapp-26297-flows.ts:1964-1974 · sapp-26297.controller.ts:360-629) | Người đọc doc hiểu sai phạm vi tool | BE (chủ shared/api-docs/) |
| DR-S-02 (inventory DR-02) | shared/api-docs/sapp.md:2748-2750: "every read-only s26297.* statement (16 entries, 17 statements) ran" | Catalogue có 20 entry chỉ-đọc (thêm lms.1, hs5.1-3), tổng 39 (be/libs/constants/src/lib/sapp/sapp-26297-sql.constants.ts:251-294) | Con số kiểm chứng trong doc lỗi thời | BE |
| DR-S-03 (inventory DR-03) | shared/api-docs/sapp.md:2787-2789: "Every field and query value is … forwarded as given" | Giá trị query rỗng / null bị bỏ trước khi gửi Ops / LMS; chỉ body được chuyển nguyên (sapp-26297.common.service.ts:96-103,115,163,215) | Case dựng "query rỗng" sẽ thành "không có query" | BE |
| DR-S-04 (inventory DR-04) | shared/api-docs/sapp.md:2839: POST /hubspot/contacts "Creates the contact, or adopts the one that already holds that email" | Khi dùng lại còn ghi đè property của contact cũ bằng property gửi lên (be/libs/modules/src/lib/hubspot/common.service.ts:617-621,654-660) | Contact test dùng lại bị sửa dữ liệu; doc không cảnh báo | BE |
| DR-S-05 (inventory DR-05) | be/.agents/maps/modules/tool.md:34: "Tool test chuyển lớp học viên" | Tool là chuyển nhượng học viên (sapp-26297-tool.tsx:211 · be/libs/database/migrations/1786300000000-seed-tool-sapp-26297.ts:18) | Sai tên nghiệp vụ trong map module | BE |
| DR-S-06 (inventory DR-06) | shared/api-docs/sapp.md:2787-2789 ngầm hiểu chuỗi rỗng là một cách "gửi sai" | Màn không bao giờ gửi chuỗi rỗng (bỏ field); với HubSpot, DTO nói rỗng = xoá property nhưng màn không gửi được rỗng (fe/src/ui/components/works/sapp/sapp-26297-step-call.tsx:110-116 · be/libs/interface/src/lib/dto/sapp/sapp-26297.dto.ts:112) — liên quan OQ-S-02 | Doc và màn lệch về cách dựng case "để trống" | BE + FE |
7. References ​
- BRD: brd-as-built-v0.1-20260930.md
- Impact Matrix: N/A — Mode B
- Solution Decision: project-decisions.md
- Figma: N/A — as-built
- API Spec:
shared/api-docs/sapp.md:2674-2871(SQL runner + tool 26297) — có drift, xem §6b - Code đã đọc (Mode B):
fe/src/ui/components/works/sapp/sapp-26297-tool.tsx·sapp-26297-flows.ts·sapp-26297-step-call.tsx·sapp-26297-sql.ts·fe/src/data/services/sapp/sapp-26297.service.ts·be/apps/api/src/sapp/sapp-26297.controller.ts·be/libs/modules/src/lib/sapp/sapp-26297.common.service.ts·be/libs/interface/src/lib/dto/sapp/sapp-26297.dto.ts·be/libs/constants/src/lib/sapp/sapp-26297.constants.ts·sapp-26297-sql.constants.ts— chi tiết ở feature inventory 26297 §9 - Meeting Notes / Q&A:
shared/external/sapp/sapp-26297/README.md·2026-09-25-mind-sapp-26297-cau-hoi.md(11 câu gửi SAPP) ·shared/integration/0045-be-sapp-26297-transfer-tool.md·0046-be-sapp-26297-flows-4-5-6.md· gate-r1-summary (G-01…G-10)
Template Conformance Check ​
Quét từng file US, so khớp mục lục với ba/_workflow/templates/fs/User-Story.md: Metadata (US ID · Role · Phase · Priority · Status · NFR · OQ) · 1. US Statement · 2. Dependencies & DoR · 3. Business Rules (cột "Đã cover bởi (AC)" + "Nguồn code") · 4. Design (a. flow · b. mỗi màn: UI States · Fields · Actions · Acceptance Criteria · Negative AC / Edge Cases; không có màn List nên không có Filter/Search/Sort) · 5. Cross-feature AC. Đồng thời kiểm: mọi BR có ≥ 1 AC Maps to; mọi OQ được tham chiếu có trong §6; không có thẻ HTML thô.
| US file | Số màn | Section thiếu | Trạng thái |
|---|---|---|---|
| US-S01-chay-case.md | 4 (M1 màn tool, M2 bước gọi API, M3 bước SQL, M4 bước hướng dẫn — M4 ghi N/A có lý do ở Fields / Actions / vài UI State) | (đủ) | ✅ |
| US-S02-chuan-bi-don-du-lieu.md | 1 | (đủ) | ✅ |
| US-S03-chuyen-nhuong.md | 1 | (đủ) | ✅ |
| US-S04-huy-chuyen-nhuong.md | 1 | (đủ) | ✅ |
| US-S05-chan-chuyen-nhuong.md | 1 | (đủ) | ✅ |
| US-S06-chan-xoa-hoc-vien.md | 1 | (đủ) | ✅ |
| US-S07-chan-huy-chuyen-nhuong.md | 1 | (đủ) | ✅ |
| US-S08-lms-khoa-hoc.md | 1 | (đủ) | ✅ |
| US-S09-hubspot-dong-bo-lai.md | 1 | (đủ) | ✅ |
| US-S10-mail.md | 1 | (đủ) | ✅ |
Ghi chú: US-S05, US-S06, US-S07 ghi "Không có" ở Cross-feature AC (đúng quy ước template). Dependencies & DoR ghi N/A — đã triển khai + dependency runtime. Tổng: 81 BR · 69 AC (60 AC màn + 9 AC cross-feature) · 78 case trong bảng case (0.1–0.2 ở US-S02; 76 case ở US-S03 → US-S10).