Giao diện
US-D12: Flow P2 — DTTH ghi bù, học viên A/B (story SAPP US-04) ​
Thuộc FS: 00-overview.md — SAPP-26878 · Tạo dữ liệu test doanh thu (Ops → HubSpot → SAP) Phần chung (tổng quan, roles, flow tổng, related features, NFR, Open Questions, References) xem ở Overview. File này chỉ chứa nội dung riêng của US.
Mode B – As-built tại commit
e77c47a· nguồn Fact: inventory 26878 §3.3 (A-122). Khung stepper (kể cả hiển thị một hàng cho mỗi deal) → US-D01 · lịch sử / log SAP → US-D02 · loại bước → US-D03.U01:x= bước x của luồng US-01 ở US-D09 §4a.
| Field | Value |
|---|---|
| US ID | US-D12 |
| Role thực hiện | Người dùng tool — Assumption (OQ về G-01 · inventory Q-05 — xem 00-overview §6) |
| Phase | Phase 2 của SAPP-26878 (DTTH) · chip US-04 · DTTH ghi bù (id us04) |
| Priority | N/A — as-built, đã triển khai (backlog R2: không xếp Priority) |
| Status | Draft |
| NFR liên quan | NFR-P-01 (quyền, FS nền tảng) · NFR của 26878 — xem 00-overview §5 |
| OQ liên quan | OQ-D-07, OQ-D-06, OQ-D-13, OQ-D-15 — xem 00-overview §6 · DR-D-06, DR-D-07 — xem 00-overview §6b |
1. US Statement ​
text
As a Người dùng tool (Assumption — OQ về G-01)
I want dựng một lớp có buổi ở quá khứ, cho học viên A vào lớp và quét trước, dựng mốc "cửa sổ đã quét",
rồi cho học viên B vào lớp muộn và quét lần hai
So that kiểm được rằng những buổi đã qua trước khi học viên vào lớp vẫn được ghi nhận bù cho học viên
vào muộn (ghi bù / CATCH_UP), còn học viên có mặt từ đầu không bị ghi lại- Nguồn "So that":
shared/runbooks/sapp/sapp-26878/phase-2/us-04/README.md:5-6("Học viên vào lớp sau khi lớp đã học vài buổi thì những buổi đã qua phải được ghi bù, với ngày chứng từ dồn về ngày quét để phiếu vào được kỳ đang mở"); hint luồngsapp-26878-flows.ts:4457. Tiêu chí nghiệm thu của tool:[Assumption](OQ-D-13).
2. Dependencies & Definition Of Ready ​
N/A — đã triển khai (Mode B). Dependency runtime như US-D09 §2. Thêm: trên Staging, ngày khai giảng lớp phải nằm trong [2026-09-17, hôm qua] thì mới còn chỗ kéo buổi về quá khứ (hint sapp-26878-flows.ts:4251,4457).
3. Business Rules ​
| ID | Rule | Áp dụng ở | Đã cover bởi (AC) | Nguồn code (Mode B/C) |
|---|---|---|---|---|
| BR-01 | Luồng có 29 bước chia hai hàng theo học viên (A: bước 1–18, B: bước 19–29) theo thứ tự ở §4a; không có bước trả lại mã lớp | M1 | AC-M1.1 | fe/src/ui/components/works/sapp/sapp-26878-flows.ts:4459-4496 |
| BR-02 | Luồng có hai Deal (học viên A "có mặt từ đầu", học viên B "vào lớp muộn"), cả hai dùng bộ property Deal phase 2 của US-01 và mang vai contact khác nhau | M1 - A10, A20 | AC-M1.2 | sapp-26878-flows.ts:4109-4125; nhãn tên deal be/libs/constants/src/lib/sapp/sapp-26878.constants.ts:515-529 |
| BR-03 | Mỗi học viên đi qua cùng một khối 8 bước: Tạo Deal → Gán mã lớp → Tạo đơn → Soạn thảo hợp đồng → Tạo giao dịch → Xác nhận giao dịch → Kéo sang Won → Hoàn thiện hồ sơ, gắn với Deal của học viên đó | M1 - A10…A17, A20…A27 | AC-M1.2 | sapp-26878-flows.ts:4140-4176 |
| BR-04 | Bước Tạo lớp dùng lại bước của US-01; chỉ hint ô ngày khai giảng đổi (yêu cầu sửa về mốc go-live của môi trường), giá trị mặc định không đổi | M1 - A3 | AC-M1.3 | sapp-26878-flows.ts:4463-4468 |
| BR-05 | "Kéo buổi về quá khứ": người dùng tự nhập hai ngày (buổi 1–2 ≤ mốc S, buổi 3–4 > S) và bốn id lịch; câu ghi cập nhật ngày bắt đầu và ngày kết thúc của 4 buổi | M1 - A6 | AC-M1.4 | sapp-26878-flows.ts:4192-4259 |
| BR-06 | "Quét lần 1 (nền của A)" là một lượt quét thủ công nằm sau khối 8 bước của A và trước "Dựng mốc cửa sổ" | M1 - A18 | AC-M1.5 | sapp-26878-flows.ts:4271-4279,4482-4492 |
| BR-07 | "Dựng mốc cửa sổ": câu ghi chèn một lượt quét WEEKLY · SUCCESS có ngày cuối cửa sổ = S, đánh dấu seeded_by = test-us04; câu dọn chỉ xóa đúng các lượt mang dấu đó | M1 - A19 | AC-M1.6 | sapp-26878-flows.ts:4325-4377 |
| BR-08 | Đọc kết quả lọc log SAP theo mã lớp (không theo deal), tự chạy 4 kiểm chứng (§M2), luôn coi là xong | M2 | AC-M2.1 → AC-M2.5 | sapp-26878-flows.ts:4390-4440; fe/src/ui/components/works/sapp/sapp-26878-tool.tsx:1479-1498 |
| BR-09 | Mọi câu SQL ghi không tự chạy và phải qua hộp xác nhận | M1 - A6, A19 | AC-M1.4, AC-M1.6 | fe/src/ui/components/works/sapp/sapp-26878-step-sql.tsx:200-213 |
4. Design ​
a. Mối liên hệ giữa các màn & User Flow ​
text
[Chip "US-04 · DTTH ghi bù", portal Dev | Staging]
↓
[M1 · hàng Học viên A] U01:1 → U01:2 → U01:3 (sửa ngày khai giảng) → U01:5 → U01:4
→ Kéo buổi về quá khứ → Xóa buổi đuôi (tùy chọn) → U01:6 → U01:7
→ 8 bước học viên A → Quét lần 1 (nền của A)
↓
[M1 · hàng Học viên B] Dựng mốc cửa sổ → 8 bước học viên B → U01:16
↓
[M2] Đọc kết quả (lọc theo mã lớp, luôn "xong")Bảng bước (Fact: sapp-26878-flows.ts:4459-4496).
| # | Tên bước | Loại | Tái dùng | Ghi gì (hệ thống · môi trường) | Điều kiện chuyển (xong) |
|---|---|---|---|---|---|
| 1 | Kiểm tra kết nối Ops | ops + sql | U01:1 | Không ghi | Ping thành công |
| 2 | Đếm lớp của môn | ops | U01:2 | Không ghi | Gọi thành công |
| 3 | Tạo lớp | ops + sql | U01:3 (đổi hint started_at) | Ops dev/staging | Gọi thành công |
| 4 | Gán phòng học | ops | U01:5 | Ops | Gọi thành công |
| 5 | Tạo buổi học | ops | U01:4 | Ops | Gọi thành công |
| 6 | Kéo buổi về quá khứ | guide + sql | riêng | Ops DB: us04.backdate.2 cập nhật ngày 4 buổi | Bấm "Đã kéo ngày xong" |
| 7 | Xóa buổi đuôi (tùy chọn) | ops + sql | riêng (dùng chung với US-D11 bước 16) | Ops: xóa buổi (lặp được) | Xóa thành công hoặc bỏ qua |
| 8 | Mở lớp (PUBLIC) | ops | U01:6 | Ops | Gọi thành công |
| 9 | Thêm option mã lớp | option | U01:7 | HubSpot dev (staging: bỏ qua) | Đủ 3 property / bỏ qua |
| 10 | Tạo Deal (A) | deal | tương đương U01:8, Deal học viên A | HubSpot (⚠️ portal prod khi Staging); Redis run history | Có deal A |
| 11 | Gán mã lớp (A) | classcode | U01:9 | HubSpot | Gọi thành công |
| 12 | Tạo đơn hàng (A) | ops | U01:10 | Ops | Thành công, số tiền ≠ 0 |
| 13 | Soạn thảo hợp đồng (A) | stage | tương đương U01:11, trên deal A | HubSpot | Chuyển stage thành công |
| 14 | Tạo giao dịch (A) | ops | U01:12 | Ops | Gọi thành công |
| 15 | Xác nhận giao dịch (A) | ops | U01:13 | Ops → SAP (theo hint) | Gọi thành công |
| 16 | Kéo sang Won (A) | stage | tương đương U01:14, trên deal A | HubSpot | Chuyển stage thành công |
| 17 | Hoàn thiện hồ sơ (A) | stage | tương đương U01:15, trên deal A (thêm câu hint) | HubSpot | Chuyển stage thành công |
| 18 | Quét lần 1 (nền của A) | scan | riêng | SAP service dev/staging | Gọi thành công |
| 19 | Dựng mốc cửa sổ | guide + sql | riêng | Ops DB: us04.window.1 chèn lượt quét mẫu (câu ③ xóa khi chạy lại) | Bấm "Đã dựng mốc cửa sổ" |
| 20–27 | 8 bước học viên B (Tạo Deal … Hoàn thiện hồ sơ) | deal / classcode / ops / stage | như bước 10–17, trên deal B | Như bước 10–17 | Như bước 10–17 |
| 28 | Chạy lượt quét | scan | U01:16 | SAP service | Gọi thành công |
| 29 | Đọc kết quả | trace | riêng (lọc theo mã lớp) | Không ghi | Luôn xong |
⚠️ Ghi PROD — trên Staging, bước 10, 11, 13, 16, 17 và 20, 21, 23, 26, 27 ghi HubSpot portal production (như US-D09 §4a).
Tình trạng nghiệm thu gần nhất (nguồn ngoài code, chưa kiểm chứng ở R3): runbook ghi ✅ 4/4 trên dev 2026-09-18 (shared/runbooks/sapp/sapp-26878/phase-2/us-04/README.md:3) và một lượt trọn vẹn trên staging 2026-09-22 (.../phase-2/staging/README.md §6f).
b. Chi tiết từng màn ​
Màn M1 - Chuỗi bước dựng dữ liệu (bước 1–28, hai hàng) ​
| Field | Value |
|---|---|
| Figma frame | N/A — as-built, không có Figma |
| Trigger vào màn | Chọn chip US-04 · DTTH ghi bù (inventory E-07) |
| Mô tả ngắn | Stepper chia hai hàng "Học viên A · có mặt từ đầu" / "Học viên B · vào lớp muộn"; các bước dựng lớp đứng ở hàng A. |
UI States ​
| State | Khi nào | Hiển thị | Figma frame |
|---|---|---|---|
| Default | Sitting mới | Hai hàng bước; bước 1 mở, còn lại khóa (→ US-D01) | N/A |
| Loading | Đang gọi hệ ngoài / SQL | Nút chạy ở trạng thái xử lý | N/A |
| Has data | Bước xong | Response + id vào bag, tự sang bước kế | N/A |
| Empty | Staging, pool mã lớp rỗng | Như US-D09 EC-M1.2 | N/A |
| Error | Hệ ngoài trả lỗi (vd 429 khi quét dồn) | Lỗi của bước | N/A |
| Disabled | Bước khóa; bước 9 trên Staging | Như US-D09 | N/A |
Fields ​
Chỉ field riêng của luồng (Nguồn sapp-26878-flows.ts:4192-4356).
| Field | Required | Type | Default | Format | Validation | Error Message | Visibility | Depends On |
|---|---|---|---|---|---|---|---|---|
B3 · started_at | Yes | Datetime ISO | 00:00 hôm nay giờ VN (như U01:3) | ISO | Hint: sửa về go-live (dev 2026-09-14, staging 2026-09-17), không sớm hơn go-live | — | Always | — |
| B6 · Ngày cho buổi 1–2 (≤ S) | — | Date | — | YYYY-MM-DD | Hint: ≥ go-live và ≥ ngày khai giảng | — | Always | — |
| B6 · Ngày cho buổi 3–4 (> S) | — | Date | — | YYYY-MM-DD | Hint: > S, ≤ hôm nay | — | Always | — |
B6 · schedule_1 … schedule_4 | — | Text | — (nhập tay từ câu ①) | id lịch | Hint: cột schedule_id, không phải cột id | — | Always | Câu ① |
B7 · class_schedule_id | Yes | Text | id buổi cuối từ p2.deletetail.1 | id | Như US-D11 BR-03 | class_schedule_not_found | Always | class_id |
| B19 · Mốc S | — | Date | — | YYYY-MM-DD | Hint: cùng giá trị đã dùng ở bước 6 | — | Always | Bước 6 |
Actions ​
A6 - Kéo buổi về quá khứ (bước 6) ​
| Item | Description |
|---|---|
| Trigger | Chạy câu ① lấy id, nhập 2 ngày + 4 id, chạy câu ② (xác nhận), chạy câu ③, bấm "Đã kéo ngày xong" |
| Behavior | Ghi Ops DB dev/staging (BR-05, BR-09). Guide: phải chừa ít nhất một buổi ở tương lai, nếu không buổi ghi bù cuối cùng ra TRUE_UP thay vì CATCH_UP. |
| Success Result | 4 buổi nằm đúng hai phía S, còn ít nhất một buổi tương lai |
Error cases:
| Case | Expected Handling |
|---|---|
Nhập nhầm cột id thay cho schedule_id | Theo ghi chú: câu UPDATE không cập nhật dòng nào, không báo lỗi |
A18 - Quét lần 1 (bước 18) ​
| Item | Description |
|---|---|
| Trigger | Bấm chạy |
| Behavior | Lượt quét thủ công (→ US-P05) để học viên A có lịch sử ghi nhận (BR-06). |
| Success Result | Lượt quét vào hàng đợi |
Error cases:
| Case | Expected Handling |
|---|---|
| Bấm dồn hai lượt | Theo hint: SAP service trả 429 (nhịp chặn 1000 ms) — đợi rồi bấm lại |
A19 - Dựng mốc cửa sổ (bước 19) ​
| Item | Description |
|---|---|
| Trigger | Nhập S, chạy câu ① (xác nhận), chạy câu ② kiểm, bấm "Đã dựng mốc cửa sổ" |
| Behavior | Ghi Ops DB dev/staging: chèn lượt quét mẫu (BR-07). Guide: thứ tự cố định quét lần 1 → dựng mốc → thêm B → quét lần 2. |
| Success Result | Dòng mới nhất là WEEKLY · SUCCESS với ngày cuối cửa sổ = S |
Error cases:
| Case | Expected Handling |
|---|---|
| Chạy lại ca | Câu ③ xóa đúng các mốc seeded_by = test-us04 |
A10–A17, A20–A27 - Khối 8 bước học viên ​
| Item | Description |
|---|---|
| Trigger | Như U01:8 → U01:15 |
| Behavior | Như US-D09 A8–A15 nhưng trên Deal A / Deal B (BR-02, BR-03). Hint Deal B: B phải là người khác A (email, SĐT, CCCD khác). ⚠️ Ghi PROD (HubSpot) khi Staging. |
| Success Result | Hai Deal ở Won - Hoàn thiện hồ sơ |
Error cases:
| Case | Expected Handling |
|---|---|
| Contact của B trùng A | Theo hint Deal B: Ops coi là cùng một học viên, không có người vào muộn; tool chỉ cảnh báo contact trùng theo vai (→ US-D03) |
Acceptance Criteria của màn M1 ​
AC-M1.1 - Chuỗi 29 bước, hai hàng ​
gherkin
Given một sitting mới của luồng US-04
When người dùng xem stepper
Then thấy hai hàng "Học viên A · có mặt từ đầu" (bước 1–18) và "Học viên B · vào lớp muộn" (bước 19–29) theo §4a
And không có bước "Trả lại mã lớp"Maps to:
- Business Rule: BR-01
AC-M1.2 - Hai Deal, hai khối học viên ​
gherkin
Given luồng US-04
When đi hết bước 10–17 và 20–27
Then có hai Deal riêng (tên chứa "US-04 Ghi bù · Học viên A" và "… Học viên B"), mỗi khối 8 bước tác động đúng Deal của nóMaps to:
- Business Rule: BR-02, BR-03
AC-M1.3 - Hint ngày khai giảng ​
gherkin
When mở bước 3 "Tạo lớp" của US-04
Then ô started_at vẫn mặc định 00:00 hôm nay giờ VN, và hint yêu cầu sửa về mốc go-live của môi trườngMaps to:
- Business Rule: BR-04
AC-M1.4 - Kéo 4 buổi quanh mốc S ​
gherkin
Given đã nhập hai ngày và bốn schedule_id
When chạy câu ② và xác nhận hộp thoại
Then ngày bắt đầu và kết thúc của buổi 1–2 = ngày ≤ S, của buổi 3–4 = ngày > SMaps to:
- Business Rule: BR-05, BR-09
AC-M1.5 - Quét lần 1 trước khi dựng mốc ​
gherkin
Given khối 8 bước của A đã xong
When người dùng xem bước kế tiếp
Then đó là "Quét lần 1 (nền của A)", và "Dựng mốc cửa sổ" chỉ mở sau khi bước này xongMaps to:
- Business Rule: BR-06
AC-M1.6 - Dựng và dọn mốc cửa sổ ​
gherkin
Given đã nhập mốc S
When chạy câu ① và xác nhận
Then có thêm một lượt quét WEEKLY · SUCCESS với ngày cuối cửa sổ = S và counters.seeded_by = "test-us04"
When chạy câu ③ và xác nhận
Then chỉ các lượt mang seeded_by = "test-us04" bị xóaMaps to:
- Business Rule: BR-07, BR-09
Negative AC / Edge Cases của màn M1 ​
| ID | Tình huống | Hành vi mong đợi |
|---|---|---|
| EC-M1.1 | ⚠️ Observed — chạy luồng trên Staging | Luồng không có bước "Trả lại mã lớp" (chỉ US-01 có), trong khi runbook staging §0.1 và lượt §6f ghi mọi lượt đều trả mã. Mỗi lượt giữ vĩnh viễn một mã của pool staging; cạn pool → bước Tạo lớp của mọi luồng phase 2 bị chặn. OQ-D-07 · DR-D-06 — xem 00-overview §6 / §6b |
| EC-M1.2 | ⚠️ Observed — sổ cái trao đổi với SAPP ghi "chip US-04 (28 bước)" | Code hiện có 29 bước (có thể do thay đổi sau ngày ghi) — DR-D-07 — xem 00-overview §6b |
| EC-M1.3 | Đảo thứ tự (dựng mốc trước quét lần 1, hoặc thêm B trước khi dựng mốc) | Gate stepper giữ đúng thứ tự khi chạy tuần tự; nếu bỏ qua bước thì tool không chặn. Theo guide: A cũng nhận CATCH_UP hoặc B không còn là người vào muộn |
| EC-M1.4 | Kéo hết buổi về quá khứ | Tool không chặn; theo guide, buổi cuối ra TRUE_UP (thành ca EC-M2.5 của story) |
| EC-M1.5 | ⚠️ Observed (OQ-D-18) — guide bước 6 ghi "⚠ Chỉ làm trên dev" | Bước không bị khóa trên Staging, flow hint mô tả khung staging, và runbook §6f ghi đã chạy trên staging. Đề xuất OQ "hướng dẫn cũ hay giới hạn thật?" — điều phối viên cấp mã |
| EC-M1.6 | ⚠️ Observed — "Dùng deal có sẵn" cho Deal A hoặc B | Mọi bước còn lại thuộc deal đó bị đánh dấu xong — OQ-D-06 |
Màn M2 - Bước 29 "Đọc kết quả" ​
| Field | Value |
|---|---|
| Figma frame | N/A — as-built, không có Figma |
| Trigger vào màn | Mở bước 29 |
| Mô tả ngắn | Trace log SAP lọc theo mã lớp (cả hai học viên) + 4 kiểm chứng. |
UI States ​
| State | Khi nào | Hiển thị | Figma frame |
|---|---|---|---|
| Default | Mở bước | Hint + mã lớp + trace tự chạy (lọc class_code) | N/A |
| Loading | Đang tra | Trace đang tải | N/A |
| Has data | Có trail | Kết quả 4 kiểm chứng | N/A |
| Empty | Chưa có bút toán ghi bù | Kiểm chứng 1 fail kèm hai nghi can (chưa có mốc cửa sổ; B vào lớp trước mốc) | N/A |
| Error | Trace lỗi | → US-P05 | N/A |
| Disabled | N/A | N/A | N/A |
Fields ​
N/A — bộ lọc class_code lấy từ bag.
Actions ​
A29 - Đọc kết quả ​
| Item | Description |
|---|---|
| Trigger | Mở bước (tự chạy) |
| Behavior | Tra log theo mã lớp, chạy 4 kiểm chứng (BR-08). Không ghi. Theo code: hai khẳng định quan trọng nhất của story (A không bị ghi lại; ngày chứng từ của dòng ghi bù) cần so từng dòng giữa hai học viên, không được tự động hóa — chỉ nêu trong hint (sapp-26878-flows.ts:4379-4389). |
| Success Result | Bước luôn xong |
Error cases:
| Case | Expected Handling |
|---|---|
| Không đọc được trường | Kiểm chứng = unknown |
Acceptance Criteria của màn M2 ​
AC = kiểm chứng tự chấm (sapp-26878-flows.ts:4390-4426).
AC-M2.1 - Có bút toán ghi bù ​
gherkin
When chạy kiểm chứng "Có bút toán ghi bù"
Then pass khi có ít nhất một dòng sổ cái của lớp mang entry_type = CATCH_UPMaps to:
- Business Rule: BR-08
AC-M2.2 - Ghi bù dùng chung công thức buổi thường ​
gherkin
When chạy kiểm chứng "Ghi bù dùng chung công thức buổi thường"
Then pass khi recognition_type trong payload = PER_LESSONMaps to:
- Business Rule: BR-08
AC-M2.3 - Ghi bù mang ngày quét, giữ nguyên ngày buổi ​
gherkin
When chạy kiểm chứng "Ghi bù mang ngày quét, giữ nguyên ngày buổi"
Then pass khi có ít nhất một phần tử payload có document_date khác u_lesson_dateMaps to:
- Business Rule: BR-08
AC-M2.4 - Ghi bù và buổi thường là một chuỗi ​
gherkin
When chạy kiểm chứng "Ghi bù và buổi thường là MỘT chuỗi"
Then pass khi standard_hours_remaining giảm dần qua các phần tử payloadMaps to:
- Business Rule: BR-08
AC-M2.5 - Bước đọc không chặn ​
gherkin
Given một kiểm chứng fail hoặc unknown
Then bước 29 vẫn là "xong"Maps to:
- Business Rule: BR-08
Negative AC / Edge Cases của màn M2 ​
| ID | Tình huống | Hành vi mong đợi |
|---|---|---|
| EC-M2.1 | 4/4 kiểm chứng pass | Chưa đủ để kết luận story đạt: đếm "A đúng 4 dòng" và so ngày của dòng ghi bù phải đọc tay (A29) — OQ-D-15 |
| EC-M2.2 | Lượt quét tuần thật hỏng hoặc mốc dựng sai | Theo hint: buổi lẽ ra ghi bù ra PER_LESSON, tiền vẫn đúng, không lỗi — người dùng phải tự đọc window_from |
5. Cross-feature AC ​
AC-X.1 - Khối 8 bước học viên dùng chung với US-05 ​
gherkin
Given khối 8 bước học viên (bước 10–17 / 20–27) thay đổi
When mở luồng US-05 phase 2
Then luồng đó dùng cùng khối bước (US-D13 bước 9–16 / 18–25)Maps to:
- Liên quan nội bộ FS 26878 (không có mã REL) (US-D09, US-D11 bước "Xóa buổi đuôi", US-D13)