Giao diện
US-D09: Flow P2 — DTTH theo buổi (story SAPP US-01) ​
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-100 → A-117). Khung stepper → US-D01 · lịch sử run / log SAP → US-D02 · hành vi từng loại bước → US-D03. File này không mô tả lại ba phần đó.⭐ US này là xương sống của phase 2. 16 bước đầu (bước 1–16) được 8 luồng phase 2 còn lại (US-D10 → US-D17) dùng lại nguyên vẹn; các file đó ghi
U01:x= bước x trong bảng §4a của file này.
| Field | Value |
|---|---|
| US ID | US-D09 |
| 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 ("Doanh thu thực hiện" – DTTH) · chip US-01 · DTTH theo buổi (id us01) |
| 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-05, OQ-D-06, OQ-D-11, OQ-D-13, OQ-D-14, OQ-D-15, OQ-D-02 — xem 00-overview §6 · DR-D-11, DR-D-06 — xem 00-overview §6b |
1. US Statement ​
text
As a Người dùng tool (Assumption — OQ về G-01)
I want dựng trọn một lượt dữ liệu test "doanh thu thực hiện theo buổi" trên dev/staging bằng 18 bước
có sẵn: tạo lớp mới trên Ops, sinh buổi học, tạo Deal HubSpot nối với lớp qua mã lớp, tạo đơn
hàng + giao dịch trên Ops, kéo Deal qua hai mốc Won, chạy lượt quét rồi đọc sổ cái SAP
So that kiểm được rằng mỗi buổi đã diễn ra sinh một bút toán sang SAP và số dư tài khoản 3387 của học
viên giảm dần qua từng buổi- Nguồn "So that": mục đích nghiệp vụ của DTTH lấy từ
shared/runbooks/sapp/sapp-26878/README.md:3-4("Ghi nhận doanh thu theo buổi học … mỗi buổi đã diễn ra sinh một bút toán sang SAP, và số dư tài khoản 3387 của học viên giảm dần cho tới khi lớp kết thúc"). Việc tool phục vụ ai / nghiệm thu thế nào là[Assumption](inventory Q-05, Q-13 — BA chưa cung cấp FS gốc của story US-01).
2. Dependencies & Definition Of Ready ​
N/A — đã triển khai (Mode B).
Dependency runtime (để luồng chạy được, Fact từ code):
| # | Cần sẵn sàng | Ở đâu | Tham chiếu |
|---|---|---|---|
| D1 | Credential Ops của môi trường (dev/staging) trong env_systems | DB mind_keep | US-P04, hint bước 1 sapp-26878-flows.ts:2830 |
| D2 | Danh mục phase 2 theo môi trường (môn, khóa, cơ sở, nhân sự, sản phẩm + giá, phòng học) — chỉ dev + staging; thiếu → 501 | BE constant | inventory R-32, be/apps/api/src/sapp/sapp.controller.ts:640-657 |
| D3 | Ops passthrough + auto-login | BE → Ops API | US-P08 |
| D4 | SQL runner theo statement id | BE → Ops DB | US-P09 |
| D5 | Thêm option property HubSpot (chỉ dev) | BE → HubSpot dev | US-P07 |
| D6 | Manual scan + trace log SAP | BE → SAP service | US-P05 |
3. Business Rules ​
| ID | Rule | Áp dụng ở | Đã cover bởi (AC) | Nguồn code (Mode B/C) |
|---|---|---|---|---|
| BR-01 | Luồng chỉ chạy trên portal Dev và Staging; không mở trên Prod | M1 - chọn portal | AC-M1.1 | fe/src/ui/components/works/sapp/sapp-26878-tool.tsx:91-119 |
| BR-02 | Luồng có đúng 18 bước theo thứ tự cố định ở §4a; một bước chỉ mở khi mọi bước trước đã xong (xong / bỏ qua) | M1 - toàn chuỗi | AC-M1.2 | fe/src/ui/components/works/sapp/sapp-26878-flows.ts:2796-3351; sapp-26878-tool.tsx:888-894 |
| BR-03 | Số thứ tự lớp mới = số lớp loại STANDARD hiện có của môn đã chọn + 1, đếm tại thời điểm bấm bước 2 | M1 - A2 Đếm lớp | AC-M1.3 | sapp-26878-flows.ts:2840-2860,2598 |
| BR-04 | Trên Dev: mã lớp sinh theo mẫu {mã môn}03.{số thứ tự}, tên lớp theo mẫu [SAPP-26878] {mã môn} - {số thứ tự} | M1 - A3 Tạo lớp | AC-M1.3 | sapp-26878-flows.ts:2604-2605,2876-2891 |
| BR-05 | Trên Staging: mã lớp chọn từ danh sách gồm những mã đã có option trên cả ba property mã lớp (Deal ×2, Contact ×1), đúng tiền tố môn, và chưa có lớp nào giữ (kể cả lớp đã xóa mềm). Danh sách rỗng → bước Tạo lớp bị chặn kèm lý do | M1 - A3 Tạo lớp | AC-M1.4, EC-M1.2 | be/apps/api/src/sapp/sapp.controller.ts:659-771; fe/src/ui/components/works/sapp/sapp-26878-step-ops.tsx:445-456,597-600,825-850 |
| BR-06 | Lớp tạo với giá trị mặc định: trạng thái DRAFT, loại LESSON, hình thức BLENDED, thời lượng FIXED, khai giảng 00:00 hôm nay giờ VN, lịch tuần cố định = thứ của hôm nay 13:00–16:00 (UTC) | M1 - A3 Tạo lớp | AC-M1.3 | sapp-26878-flows.ts:2920-2971 |
| BR-07 | Buổi học được sinh bằng bộ sinh lịch từ lịch tuần (không tạo tay từng buổi), mốc bắt đầu mặc định = hôm qua 15:00Z | M1 - A4 Tạo buổi học | AC-M1.5 | sapp-26878-flows.ts:2994-3019 |
| BR-08 | Gán phòng học gửi link_meeting rỗng (vẫn gửi khóa, không bỏ) | M1 - A5 Gán phòng | AC-M1.5 | sapp-26878-flows.ts:3039-3046; inventory R-24 |
| BR-09 | Mở lớp chuyển trạng thái lớp sang PUBLIC (giá trị cố định, không sửa được) | M1 - A6 Mở lớp | AC-M1.5 | sapp-26878-flows.ts:3056-3066 |
| BR-10 | Bước "Thêm option mã lớp" chỉ thực hiện được trên Dev; trên Staging người dùng phải bỏ qua bước | M1 - A7 | AC-M1.6 | fe/src/ui/components/works/sapp/sapp-26878-step-option.tsx:69-72,117; inventory R-19 |
| BR-11 | Deal của mọi luồng phase 2 mang toàn bộ bộ property của Deal học phí thường phase 1 (US-03), cộng bắt buộc hai property mã lớp của Deal; hai ô mã lớp và mã lớp của Contact được điền sẵn từ bước Tạo lớp | M1 - A8 Tạo Deal | AC-M1.7 | sapp-26878-flows.ts:2639-2651,2682-2686 |
| BR-12 | Thiếu CCCD/Hộ chiếu, Họ tên học viên hoặc một property thuộc nhóm Business Partner (theo đối tượng mua hàng cá nhân / doanh nghiệp) → cảnh báo mềm, không chặn tạo Deal | M1 - A8 Tạo Deal | AC-M1.7 | sapp-26878-flows.ts:2662-2680,2687-2705; inventory R-06 |
| BR-13 | Đơn hàng Ops tạo ra có số tiền 0 → báo lỗi, bước không được đánh dấu xong | M1 - A10 Tạo đơn hàng | EC-M1.4 | sapp-26878-step-ops.tsx:636-646; inventory R-22 |
| BR-14 | Giao dịch lấy số tiền đúng bằng số tiền thật của đơn (không có mặc định); loại TUITION_PAYMENT, phương thức CASH, trạng thái AWAITING_CONFIRMATION, kiểu ONETIME, văn phòng NEU cố định; ngày thanh toán mặc định hôm nay | M1 - A12 Tạo giao dịch | AC-M1.8 | sapp-26878-flows.ts:3246-3292; inventory R-23 |
| BR-15 | Deal đi qua hai mốc Won nối tiếp: Won - Hoàn tất thủ tục rồi Won - Hoàn thiện hồ sơ (stage gợi ý theo nhãn) | M1 - A14, A15 | AC-M1.9 | sapp-26878-flows.ts:2748-2752,3308-3321 |
| BR-16 | Bước Đọc kết quả lọc log SAP theo deal_id của lượt và tự chạy 2 kiểm chứng (§M2); bước này luôn coi là xong | M2 | AC-M2.1, AC-M2.2, AC-M2.3 | sapp-26878-tool.tsx:883-884,1465-1501; sapp-26878-flows.ts:2715-2733,3331-3342 |
| BR-17 | Kiểm chứng không đọc được trường cần kiểm → trạng thái "unknown", không phải "fail" | M2 | AC-M2.3 | sapp-26878-flows.ts:382-384; fe/src/ui/components/works/sapp/sap-log-summary.tsx:401-409 |
| BR-18 | "Trả lại mã lớp": câu đọc lớp tự chạy; câu ghi đổi mã lớp thành removed_{thời điểm}_{mã cũ} và đặt thời điểm xóa mềm trong cùng một lệnh, chỉ tác động lớp chưa bị xóa mềm; câu ghi phải qua hộp xác nhận | M1 - A18 | AC-M1.10 | sapp-26878-flows.ts:2519-2537,2767-2787; fe/src/ui/components/works/sapp/sapp-26878-step-sql.tsx:200-213; inventory R-26 |
| BR-19 | Các luồng phase 2 khác dùng lại nguyên bước của luồng này theo tên bước; một bước bị đổi tên làm tool báo lỗi ngay thay vì lặng lẽ thiếu bước | Toàn phase 2 | AC-X.1 | sapp-26878-flows.ts:3375-3418 |
Không phải BR (⚠️ Observed, xem EC): trùng mã lớp khi có người tạo lớp xen giữa bước 2 và 3 (inventory Q-11 / R-21); "Dùng deal có sẵn" tự đánh dấu xong mọi bước còn lại (inventory Q-06 / R-04); BE có route prod cho thao tác ghi Ops (inventory Q-02 / R-33).
4. Design ​
a. Mối liên hệ giữa các màn & User Flow ​
Toàn bộ luồng chạy trong một màn stepper (khung ở US-D01): M1 = 17 bước dựng dữ liệu + bước trả mã, M2 = bước 17 "Đọc kết quả".
text
[Chip "US-01 · DTTH theo buổi", portal Dev | Staging]
↓
[M1] 1 Ping Ops → 2 Đếm lớp → 3 Tạo lớp → 4 Tạo buổi → 5 Gán phòng → 6 Mở lớp PUBLIC
→ 7 Thêm option (dev) / bỏ qua (staging) → 8 Tạo Deal → 9 Gán mã lớp → 10 Tạo đơn
→ 11 Soạn thảo hợp đồng → 12 Tạo giao dịch → 13 Xác nhận giao dịch → 14 Won - Hoàn tất thủ tục
→ 15 Won - Hoàn thiện hồ sơ → 16 Chạy lượt quét
↓
[M2] 17 Đọc kết quả (luôn "xong")
↓
[M1] 18 Trả lại mã lớp (staging) / bỏ qua (dev)Bảng bước (Fact: sapp-26878-flows.ts:2796-3351; loại bước → US-D03). Cột "Tái dùng" ở file này luôn là "gốc" — các US-D10…D17 dẫn ngược về đây.
| # | 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 | gốc (A-100) | Không ghi. Đọc Ops API; SQL p2.ping.1/2 đọc Ops DB (bảng có thật, có cột xóa mềm, schema) | Gọi ping thành công |
| 2 | Đếm lớp của môn | ops | gốc (A-101) | Không ghi. Đọc danh sách lớp Ops (môn, STANDARD) → bag subject_code, class_total, class_seq | Gọi thành công |
| 3 | Tạo lớp | ops + sql | gốc (A-102) | Ops (dev/staging): lớp mới DRAFT. SQL p2.takencodes chỉ đọc → bag course_id, class_id, class_code | Gọi thành công |
| 4 | Tạo buổi học | ops | gốc (A-103) | Ops: sinh buổi từ lịch tuần | Gọi thành công |
| 5 | Gán phòng học | ops | gốc (A-104) | Ops: phòng của lớp | Gọi thành công |
| 6 | Mở lớp (PUBLIC) | ops | gốc (A-105) | Ops: DRAFT → PUBLIC | Gọi thành công |
| 7 | Thêm option mã lớp | option | gốc (A-106) | HubSpot dev: định nghĩa 3 property enumeration | Đủ 3 property (dev) · staging: bỏ qua |
| 8 | Tạo Deal | deal | gốc (A-107) | HubSpot deal + contact — dev portal, hoặc portal prod khi Staging. Redis run history | Có deal trong lượt |
| 9 | Gán mã lớp | classcode | gốc (A-108) | HubSpot deal (2 property) + contact (1 property) | Gọi thành công |
| 10 | Tạo đơn hàng | ops | gốc (A-109) | Ops: đơn hàng gắn deal_id → bag order_id, order_amount | Gọi thành công và số tiền ≠ 0 |
| 11 | Soạn thảo hợp đồng | stage | gốc (A-110) | HubSpot dealstage | Chuyển stage thành công |
| 12 | Tạo giao dịch | ops | gốc (A-111) | Ops: giao dịch chờ xác nhận → bag transaction_id | Gọi thành công |
| 13 | Xác nhận giao dịch | ops | gốc (A-112) | Ops → SAP (theo hint: sinh số dư 3387) | Gọi thành công |
| 14 | Kéo sang Won | stage | gốc (A-113) | HubSpot dealstage = Won - Hoàn tất thủ tục (theo hint: bắn event hóa đơn) | Chuyển stage thành công |
| 15 | Hoàn thiện hồ sơ | stage | gốc (A-114) | HubSpot dealstage = Won - Hoàn thiện hồ sơ (theo hint: action tự thêm học viên vào lớp) | Chuyển stage thành công |
| 16 | Chạy lượt quét | scan | gốc (A-115) | SAP service (dev/staging): bắn một lượt quét thủ công | Gọi thành công |
| 17 | Đọc kết quả | trace | riêng của US-01 (A-116) | Không ghi (chỉ đọc log SAP theo deal_id) | Luôn xong |
| 18 | Trả lại mã lớp (staging) | guide + sql | riêng của US-01 (A-117) | Ops DB (staging): đổi mã lớp + đặt xóa mềm | Bấm "Đã trả lại mã lớp" (ack) · dev: bỏ qua |
⚠️ Ghi PROD — trên portal Staging, các bước 8, 9, 11, 14, 15 ghi vào HubSpot portal production (pipeline
[UAT-TEST]), vì Staging dùng credential portal prod (inventory §6 "Tích hợp ngoài — HubSpot";sapp-26878-tool.tsx:85-90). Các bước Ops/SQL/scan ghi Ops/SAP staging, không phải prod.
Tình trạng nghiệm thu gần nhất (nguồn ngoài code, chưa kiểm chứng lại ở R3): runbook ghi US-01 dựng data ✅ và khẳng định nghiệp vụ ✅ 2/2 trên dev 2026-09-18 (shared/runbooks/sapp/sapp-26878/phase-2/README.md bảng "Trạng thái lần đo cuối"); một lượt trọn vẹn trên staging 2026-09-21 (shared/runbooks/sapp/sapp-26878/phase-2/staging/README.md §6c).
b. Chi tiết từng màn ​
Màn M1 - Chuỗi bước dựng dữ liệu (bước 1–16, 18) ​
| Field | Value |
|---|---|
| Figma frame | N/A — as-built, không có Figma |
| Trigger vào màn | Chọn chip US-01 · DTTH theo buổi ở nhóm "Phase 2 · doanh thu thực hiện" (inventory E-07) |
| Mô tả ngắn | Stepper 18 bước; mỗi bước hiển thị hint, form (điền sẵn từ "bag" id của lượt), panel SQL nếu có, nút chạy / bỏ qua. |
UI States ​
| State | Khi nào | Hiển thị | Figma frame |
|---|---|---|---|
| Default | Vừa mở chip (sitting mới) | Bước 1 mở, bước 2–18 khóa (khung → US-D01) | N/A |
| Loading | Đang gọi Ops / HubSpot / SAP của một bước | Nút chạy của bước ở trạng thái đang xử lý | N/A |
| Has data | Bước chạy xong | Response + các id vừa thu vào bag; sau 1,2 s tự sang bước kế (US-D01) | N/A |
| Empty | Staging, danh sách mã lớp còn trống rỗng | Ô code không có lựa chọn, thông báo đỏ "⛔ Không còn mã lớp nào dùng được…" | N/A |
| Error | Hệ ngoài trả lỗi / đơn 0đ | Thông báo lỗi của bước; bước không được đánh dấu xong | N/A |
| Disabled | Bước bị khóa; bước 7 trên Staging; nút chạy bước 3 khi pool rỗng | Bước khóa hiện lý do khi bấm; bước 7 không chạy được ở Staging | N/A |
Fields ​
Chỉ liệt kê field riêng của luồng ở các bước ops (field của bước deal → US-D03 / US-D04). Nguồn: sapp-26878-flows.ts:2842-3292.
| Field | Required | Type | Default | Format | Validation | Error Message | Visibility | Depends On |
|---|---|---|---|---|---|---|---|---|
B2 · subject_id | Yes | Dropdown (danh mục môn) | — | id Ops | — | Lỗi của Ops | Always | Danh mục môi trường (D2) |
B2 · category | Yes | Text | STANDARD | — | — | — | Readonly | — |
B3 · name | Yes | Text | mẫu [SAPP-26878] {subject_code} - {class_seq} | — | BR-04 | Lỗi của Ops | Always | B2 |
B3 · code | Yes | Text (dev) / Dropdown (staging) | Dev: mẫu {subject_code}03.{class_seq}; Staging: mục đầu của pool | — | BR-04, BR-05; Ops ràng buộc duy nhất | Pool rỗng: thông báo chặn (EC-M1.2); trùng: lỗi 422 của Ops | Always | B2, môi trường |
B3 · course_id, facility_id, class_owner_id, cx_admin_id | Yes | Dropdown (danh mục) | — | id Ops | — | Lỗi của Ops | Always | D2 |
B3 · status / type / instruction_mode / duration_type | No | Text | DRAFT / LESSON / BLENDED / FIXED | — | BR-06 | — | Always | — |
B3 · started_at, opening_at | Yes | Datetime ISO | 00:00 hôm nay giờ VN | ISO | Hint: ≥ go-live (dev 2026-09-14, staging 2026-09-17) | — | Always | — |
B3 · capacity | No | Dropdown 20/30/40/50 | 20 | số | — | — | Always | — |
B3 · class_standard_schedules | — | JSON | thứ hôm nay, 13:00–16:00 | JSON | BR-06 | — | Hidden | — |
B4 · class_id | Yes | Text | từ bag | — | — | — | Always | B3 |
B4 · started_at | Yes | Datetime ISO | hôm qua 15:00Z | ISO | BR-07 | Lỗi của Ops | Always | — |
B5 · room_id | Yes | Dropdown (phòng học) | — | id | — | Lỗi của Ops | Always | D2 |
B5 · link_meeting | — | Text | rỗng | — | BR-08 | — | Readonly | — |
B6 · id / status | Yes | Text | bag class_id / PUBLIC | — | BR-09 | — | status Readonly | B3 |
B10 · deal_id, thông tin học viên, sản phẩm, giá | Yes (deal_id) | Text / Dropdown | từ bag / danh mục sản phẩm (giá theo sản phẩm) | — | BR-13 | "Đơn hàng tạo ra có số tiền bằng 0" | Always | B8 |
B12 · amount | Yes | Number | bag order_amount | — | BR-14 | Lỗi của Ops | Always | B10 |
B12 · type / payment_method / status / payment_type / payment_office | — | Text | TUITION_PAYMENT / CASH / AWAITING_CONFIRMATION / ONETIME / NEU | — | BR-14 | — | Readonly | — |
B12 · pay_date | Yes | Date | hôm nay | YYYY-MM-DD | — | — | Always | — |
Actions ​
Hành vi chung của từng loại bước (gọi API nào, bag, bỏ qua) → US-D03. Dưới đây chỉ ghi phần riêng của luồng.
A1 - Kiểm tra kết nối Ops (bước 1) ​
| Item | Description |
|---|---|
| Trigger | Mở bước 1 (SQL tự chạy) và bấm chạy ping |
| Behavior | Gọi thao tác ping Ops qua passthrough (US-P08); SQL p2.ping.1 tự chạy, p2.ping.2 chạy tay (US-P09). Không ghi. |
| Success Result | Ping thành công → bước xong |
Error cases:
| Case | Expected Handling |
|---|---|
| Credential Ops chưa cấu hình | Lỗi của bước; hint chỉ ra env_systems (sapp-26878-flows.ts:2830) |
A2 / A3 - Đếm lớp · Tạo lớp (bước 2–3) ​
| Item | Description |
|---|---|
| Trigger | Chọn môn, bấm chạy bước 2; sang bước 3 kiểm/chọn mã lớp, bấm chạy |
| Behavior | Bước 2 đọc tổng số lớp STANDARD của môn → số thứ tự (BR-03). Bước 3 tạo lớp trên Ops dev/staging (BR-04/05/06); panel SQL p2.takencodes (chỉ đọc, tự chạy) liệt kê mã đã dùng để giải thích danh sách chọn. |
| Success Result | Bag có class_id, class_code, course_id |
Error cases:
| Case | Expected Handling |
|---|---|
| Pool mã staging rỗng | Chặn chạy, thông báo đỏ (EC-M1.2) |
| Mã trùng (có người tạo lớp xen giữa) | Ops trả 422; hint khuyên bấm lại bước 2 (EC-M1.1) |
A4–A6 - Tạo buổi học · Gán phòng · Mở lớp (bước 4–6) ​
| Item | Description |
|---|---|
| Trigger | Bấm chạy từng bước |
| Behavior | Ghi Ops dev/staging: sinh buổi từ lịch tuần (BR-07), gán phòng (BR-08), chuyển lớp PUBLIC (BR-09). class_id lấy từ bag. |
| Success Result | Từng bước xong |
Error cases:
| Case | Expected Handling |
|---|---|
| Ops từ chối (vd lịch không khớp thứ, phòng trùng) | Lỗi của Ops hiện ở bước; bước không xong |
A7 - Thêm option mã lớp (bước 7) ​
| Item | Description |
|---|---|
| Trigger | Bấm chạy (Dev) · "Bỏ qua bước này" (Staging) |
| Behavior | Dev: thêm class_code vào option của 3 property (US-P07). Staging: không chạy được (BR-10) — mã đã có option sẵn vì được chọn từ pool. |
| Success Result | Đủ 3 property / bước đánh dấu bỏ qua |
Error cases:
| Case | Expected Handling |
|---|---|
| Staging bấm chạy | Không thực hiện được (BR-10); dùng "Bỏ qua bước này" |
A8–A9 - Tạo Deal · Gán mã lớp (bước 8–9) ​
| Item | Description |
|---|---|
| Trigger | Điền form Deal, bấm tạo; bấm chạy bước 9 |
| Behavior | Tạo Deal + Contact trên HubSpot theo spec Deal phase 2 (BR-11, BR-12) — chi tiết form → US-D03 / US-D04. Bước 9 ghi mã lớp lên 2 property Deal + 1 property Contact, không ghi nếu đã đúng (inventory R-16). Tạo Deal ghi một run vào lịch sử → US-D02. ⚠️ Ghi PROD khi Staging (HubSpot portal prod). |
| Success Result | Bag có deal_id, contact_* |
Error cases:
| Case | Expected Handling |
|---|---|
| Property ngoài whitelist / thiếu bắt buộc | Chặn ở form hoặc BE trả 400 13027 (→ US-D03) |
A10–A13 - Tạo đơn · Soạn thảo hợp đồng · Tạo giao dịch · Xác nhận giao dịch (bước 10–13) ​
| Item | Description |
|---|---|
| Trigger | Bấm chạy từng bước |
| Behavior | Bước 10 tạo đơn trên Ops với deal_id + thông tin học viên từ bag, sản phẩm từ danh mục (giá theo sản phẩm) (BR-13). Bước 11 chuyển stage HubSpot. Bước 12 tạo giao dịch trong đơn, số tiền = số tiền đơn (BR-14). Bước 13 xác nhận giao dịch trên Ops — theo hint, đây là bước gọi SAP và sinh số dư 3387 (sapp-26878-flows.ts:3303). |
| Success Result | Bag có order_id, order_amount, transaction_id |
Error cases:
| Case | Expected Handling |
|---|---|
| Đơn 0đ | EC-M1.4 |
| Số tiền giao dịch lệch đơn | Ops từ chối (hint sapp-26878-flows.ts:3259) |
A14–A16 - Kéo Won · Hoàn thiện hồ sơ · Chạy lượt quét (bước 14–16) ​
| Item | Description |
|---|---|
| Trigger | Bấm chuyển stage (bước 14, 15); bấm chạy lượt quét (bước 16) |
| Behavior | Hai mốc Won nối tiếp (BR-15). Lượt quét thủ công → US-P05; chỉ dev/staging (inventory R-25). ⚠️ Ghi PROD (HubSpot) khi Staging cho bước 14, 15. |
| Success Result | Lượt quét được đưa vào hàng đợi (xử lý bất đồng bộ) |
Error cases:
| Case | Expected Handling |
|---|---|
| Bấm quét dồn | Hint ghi SAP service chặn nhịp 1000 ms (429) — nêu ở US-D12/D13 |
A18 - Trả lại mã lớp (bước 18, staging) ​
| Item | Description |
|---|---|
| Trigger | Mở bước (câu ① tự chạy), bấm "Chạy" câu ②, xác nhận, rồi "Đã trả lại mã lớp" |
| Behavior | Câu ② ghi Ops DB staging qua SQL runner (BR-18). Dev: bỏ qua bước. Guide ghi rõ: không hoàn tác được bằng tool; bút toán đã ghi không mất (sổ cái khóa theo class_id). |
| Success Result | rowCount = 1; mã quay lại danh sách chọn ở bước 3 của lượt sau |
Error cases:
| Case | Expected Handling |
|---|---|
| Lớp đã trả trước đó | rowCount = 0 — guide ghi "không phải lỗi" |
Acceptance Criteria của màn M1 ​
AC-M1.1 - Chỉ Dev / Staging ​
gherkin
Given người dùng đang ở portal Prod
When chọn chip "US-01 · DTTH theo buổi"
Then tool tự chuyển sang portal được phép và hiện thông báo; luồng không chạy trên ProdMaps to:
- Business Rule: BR-01
AC-M1.2 - Thứ tự 18 bước ​
gherkin
Given một sitting mới của luồng US-01
When người dùng xem stepper
Then thấy đúng 18 bước theo thứ tự §4a, chỉ bước 1 mở
And bấm vào bước N (N > bước chưa xong đầu tiên) thì hiện lý do bị khóaMaps to:
- Business Rule: BR-02
AC-M1.3 - Sinh mã lớp trên Dev ​
gherkin
Given portal Dev, môn có 215 lớp STANDARD, mã môn "F1"
When chạy bước 2 rồi mở bước 3
Then ô code điền sẵn "F103.216", ô name điền sẵn "[SAPP-26878] F1 - 216"
And lớp được tạo với DRAFT, LESSON, BLENDED, FIXED, khai giảng 00:00 hôm nay giờ VNMaps to:
- Business Rule: BR-03, BR-04, BR-06
AC-M1.4 - Chọn mã lớp từ pool trên Staging ​
gherkin
Given portal Staging và pool có ít nhất một mã hợp lệ
When mở bước 3
Then ô code là danh sách chọn chỉ gồm mã có option trên cả 3 property, đúng tiền tố môn, chưa có lớp nào giữMaps to:
- Business Rule: BR-05
AC-M1.5 - Chuẩn bị lớp trước khi tạo Deal ​
gherkin
Given bước 3 đã tạo lớp
When chạy lần lượt bước 4, 5, 6
Then Ops có buổi học sinh từ lịch tuần, lớp có phòng, và lớp ở trạng thái PUBLICMaps to:
- Business Rule: BR-07, BR-08, BR-09
AC-M1.6 - Option mã lớp chỉ Dev ​
gherkin
Given portal Staging
When tới bước 7 "Thêm option mã lớp"
Then bước không chạy được; người dùng dùng "Bỏ qua bước này" để đi tiếpMaps to:
- Business Rule: BR-10
AC-M1.7 - Deal mang mã lớp ​
gherkin
Given bag có class_code từ bước 3
When mở bước 8 "Tạo Deal"
Then hai property mã lớp của Deal và mã lớp của Contact đã điền sẵn class_code, và hai property Deal là bắt buộc
And nếu để trống CCCD/Họ tên hoặc nhóm Business Partner thì chỉ hiện cảnh báo, vẫn tạo được DealMaps to:
- Business Rule: BR-11, BR-12
AC-M1.8 - Giao dịch theo số tiền đơn ​
gherkin
Given bước 10 trả về đơn có số tiền X > 0
When mở bước 12
Then ô amount = X, các ô type/payment_method/status/payment_type/payment_office chỉ đọc với giá trị cố địnhMaps to:
- Business Rule: BR-14
AC-M1.9 - Hai mốc Won ​
gherkin
Given Deal ở stage "Soạn thảo hợp đồng" và giao dịch đã xác nhận
When mở bước 14 rồi bước 15
Then stage gợi ý lần lượt là "Won - Hoàn tất thủ tục" và "Won - Hoàn thiện hồ sơ"Maps to:
- Business Rule: BR-15
AC-M1.10 - Trả lại mã lớp ​
gherkin
Given portal Staging, đã xong bước 17, lớp chưa bị xóa mềm
When chạy câu ② của bước 18 và xác nhận hộp thoại
Then mã lớp đổi thành "removed_<thời điểm>_<mã cũ>" và lớp bị xóa mềm; rowCount = 1
And ở lượt sau, mã cũ xuất hiện lại trong danh sách chọn của bước 3Maps to:
- Business Rule: BR-18
Negative AC / Edge Cases của màn M1 ​
| ID | Tình huống | Hành vi mong đợi |
|---|---|---|
| EC-M1.1 | ⚠️ Observed — có người tạo lớp của cùng môn xen giữa bước 2 và bước 3 | Hành vi hiện tại: mã lớp dựng từ số đếm cũ bị trùng, Ops trả 422; hint khuyên bấm lại bước 2. Không có cơ chế chống trùng — OQ-D-11 — xem 00-overview §6 |
| EC-M1.2 | Staging, pool mã lớp rỗng | Chặn chạy bước 3. Nếu không có mã nào có option trên đủ 3 property → báo "vấn đề cấu hình"; nếu mọi mã đã có lớp → hướng dẫn chạy bước "Trả lại mã lớp" của một luồng đã nghiệm thu (sapp-26878-step-ops.tsx:825-850) |
| EC-M1.3 | ⚠️ Observed — bước 8 chọn "Dùng deal có sẵn" (nhập deal id) | Hành vi hiện tại: không kiểm deal tồn tại / do tool tạo; mọi bước không phải deal của luồng (vì luồng chỉ có 1 deal: gồm cả tạo lớp, đơn, giao dịch, quét) bị đánh dấu "xong · bỏ qua" — OQ-D-06 — xem 00-overview §6 |
| EC-M1.4 | Đơn hàng Ops ra số tiền 0 | Báo "Đơn hàng tạo ra có số tiền bằng 0", bước không xong (BR-13) |
| EC-M1.5 | Bỏ qua bước 13 (xác nhận giao dịch) | Luồng vẫn đi tiếp; theo hint, mọi bút toán sẽ ra 0đ (AC-X.1 của story) — không có chặn trong tool |
| EC-M1.6 | Bỏ qua bước 15 (Hoàn thiện hồ sơ) | Luồng vẫn đi tiếp; theo hint, lớp không có học viên và lượt quét không sinh bút toán — không có chặn trong tool |
| EC-M1.7 | ⚠️ Observed — hint bước 3 và bước 10 nói Deal ở "bước 5" | Deal thật ở bước 8 — DR-D-11 — xem 00-overview §6b |
| EC-M1.8 | Chạy câu ghi SQL (bước 18) | Luôn qua hộp xác nhận, không tự chạy (BR-18). Id câu SQL FE ↔ BE không được kiểm đối chiếu tự động — OQ-D-14 |
| EC-M1.9 | ⚠️ Observed — route ghi Ops có bản prod ở BE | Tool không mở luồng trên Prod (BR-01) nhưng chặn chỉ nằm ở giao diện — OQ-D-02 — xem 00-overview §6 |
Màn M2 - Bước 17 "Đọc kết quả" ​
| Field | Value |
|---|---|
| Figma frame | N/A — as-built, không có Figma |
| Trigger vào màn | Bước 16 xong (hoặc bỏ qua) → mở bước 17 |
| Mô tả ngắn | Tra trail log SAP theo deal_id của lượt (→ US-P05), hiện mã lớp để copy, và tự chạy các kiểm chứng của story. |
UI States ​
| State | Khi nào | Hiển thị | Figma frame |
|---|---|---|---|
| Default | Mở bước | Hint + mã lớp (copy được) + khung trace tự chạy với bộ lọc deal_id | N/A |
| Loading | Đang tra log | Trace đang tải | N/A |
| Has data | Có trail | Log SAP + kết quả từng kiểm chứng (pass / fail / unknown); fail kèm câu giải thích | N/A |
| Empty | Chưa có log (quét bất đồng bộ) | Trace rỗng; hint khuyên đọc counters của lượt quét và đọc lại sau một nhịp | N/A |
| Error | API trace lỗi | Lỗi của trace (→ US-P05) | N/A |
| Disabled | N/A — bước không có trạng thái khóa riêng | N/A | N/A |
Fields ​
N/A — bước chỉ đọc; bộ lọc deal_id lấy tự động từ bag.
Actions ​
A17 - Đọc kết quả ​
| Item | Description |
|---|---|
| Trigger | Mở bước 17 (tự chạy) |
| Behavior | Tra log SAP theo deal_id, chạy 2 kiểm chứng (BR-16, BR-17). Không ghi. |
| Success Result | Bước luôn "xong" dù kiểm chứng pass hay fail |
Error cases:
| Case | Expected Handling |
|---|---|
| Không đọc được trường cần kiểm | Kiểm chứng = unknown (BR-17) |
Acceptance Criteria của màn M2 ​
AC = các kiểm chứng tự chấm của bước (sapp-26878-flows.ts:2715-2733).
AC-M2.1 - Số dư giảm dần qua từng buổi ​
gherkin
Given lượt quét đã gửi các buổi của lớp sang SAP
When bước "Đọc kết quả" chạy kiểm chứng "Số dư giảm dần qua từng buổi"
Then pass khi trường standard_hours_remaining trong các payload gửi SAP giảm dần theo thứ tự (vd 15.00 → 12.00 → 9.00)
And fail kèm giải thích "một buổi bị ghi lại hoặc thứ tự thời gian sai" khi không giảmMaps to:
- Business Rule: BR-16
AC-M2.2 - Mẫu số tính theo cả môn ​
gherkin
Given các payload gửi SAP của lượt
When chạy kiểm chứng "Mẫu số tính theo cả môn, không theo từng buổi"
Then pass khi standard_hours_remaining KHÔNG luôn bằng lesson_hours ở mọi buổi
And fail kèm "⛔ … mẫu số đang tính sai phạm vi … Báo dev" khi bằng nhau ở mọi buổiMaps to:
- Business Rule: BR-16
AC-M2.3 - Bước đọc không chặn ​
gherkin
Given một hoặc cả hai kiểm chứng fail hoặc unknown
When người dùng xem stepper
Then bước 17 vẫn được coi là xong và bước 18 mởMaps to:
- Business Rule: BR-16, BR-17
Negative AC / Edge Cases của màn M2 ​
| ID | Tình huống | Hành vi mong đợi |
|---|---|---|
| EC-M2.1 | Kiểm chứng fail nhưng người dùng vẫn đi tiếp | Hành vi hiện tại: không có gate "phải xanh"; nghiệm thu dựa vào người đọc — OQ-D-15 — xem 00-overview §6 |
| EC-M2.2 | Dòng sổ cái SUCCESS không có số chứng từ | Theo hint: bút toán giá trị 0, đúng thiết kế (EC-M2.7 của story) — tool không phân biệt riêng |
| EC-M2.3 | Chạy bước 18 trước khi đọc kết quả | Theo guide: sau khi trả mã không tra lớp theo mã được nữa; đọc theo deal_id vẫn được. Tool không chặn thứ tự ngoài gate chung (BR-02) |
5. Cross-feature AC ​
AC-X.1 - Các luồng phase 2 dùng lại bước của US-01 ​
gherkin
Given một thay đổi ở bước 1–16 của US-01 (hint, field, mặc định)
When mở bất kỳ luồng phase 2 nào dùng lại bước đó (US-D10 … US-D17)
Then luồng đó chạy đúng bước đã đổi (cùng một định nghĩa), trừ các field được ghi đè riêng ở luồng đó
And nếu một bước của US-01 bị đổi tên, tool báo lỗi thay vì lặng lẽ thiếu bướcMaps to:
- Business Rule: BR-19
- Liên quan nội bộ FS 26878 (không có mã REL) (liên quan nội bộ FS: US-D10 → US-D17; khung US-D01/US-D03)
AC-X.2 - Lịch sử run của phase 2 ​
gherkin
Given bước 8 tạo Deal thành công
When tool ghi run history
Then run được ghi vào bucket "us01" của môi trường (→ US-D02)Maps to:
- Liên quan nội bộ FS 26878 (không có mã REL) (US-D02). ⚠️ Observed: bucket phase 2 không có trong enum BE / API doc — OQ-D-03, DR-D-02; nút "Lịch sử" ở luồng phase 2 nghi crash — OQ-D-04 — xem US-D02