Skip to content

US-D14: Flow P2 — DTTH đảo buổi (story SAPP US-06 phase 2) ​

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-124). Khung stepper → 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.

⚠ "US-06" ở đây là story phase 2 (chip id us06-p2), khác "US-06 · CBE / Cert / Becker" phase 1 (US-D06).

FieldValue
US IDUS-D14
Role thực hiệnNgười dùng tool — Assumption (OQ về G-01 · inventory Q-05 — xem 00-overview §6)
PhasePhase 2 của SAPP-26878 (DTTH) · chip US-06 · DTTH đảo buổi (id us06-p2)
PriorityN/A — as-built, đã triển khai (backlog R2: không xếp Priority)
StatusDraft
NFR liên quanNFR-P-01 (quyền, FS nền tảng) · NFR của 26878 — xem 00-overview §5
OQ liên quanOQ-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 hôm nay đã được ghi nhận doanh thu, rồi dời (hoặc hủy) đúng buổi đó và đọc kết quả
So that kiểm được rằng một buổi đã ghi nhận doanh thu mà bị hủy hoặc dời lịch thì phần đã ghi cho buổi đó
        bị đảo ngay, ghi vào nhóm cột đảo của chính dòng sổ cái gốc, không chờ lượt quét
  • Nguồn "So that": shared/runbooks/sapp/sapp-26878/phase-2/us-06/README.md:6-7 ("Một buổi đã ghi nhận doanh thu mà bị hủy hoặc dời lịch thì phần đã ghi cho buổi đó bị đảo ngay, không chờ lượt quét"); hint luồng sapp-26878-flows.ts:5343. 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 (hint): chip chỉ chạy được trước 22:00 giờ VN (bộ sinh lịch đẩy buổi đầu sang tuần sau); thao tác dời đóng lúc 20:00, hủy đóng lúc 23:00 giờ VN (sapp-26878-flows.ts:5093,5189,5343).

3. Business Rules ​

IDRuleÁp dụng ởĐã cover bởi (AC)Nguồn code (Mode B/C)
BR-01Luồng có 22 bước theo thứ tự ở §4a (một Deal, một hàng); không có bước trả lại mã lớpM1AC-M1.1fe/src/ui/components/works/sapp/sapp-26878-flows.ts:5345-5379
BR-02"Kiểm buổi đã được ghi": câu SQL đọc tự chạy và điền sẵn id buổi (dòng đầu theo ngày) cho hai bước kích hoạt; kèm một kiểm chứng tự chấmM2 - A17AC-M2.1sapp-26878-flows.ts:4982-5017
BR-03"Tạo giáo viên" tạo một giáo viên dùng một lần; năm trường định danh bắt buộc, sinh từ mẫuM1 - A18AC-M1.2sapp-26878-flows.ts:4939-4980
BR-04"Kiểm buổi có học viên" là bước hướng dẫn chỉ đọc (đếm bản ghi buổi ↔ học viên), xong khi người dùng bấm xác nhậnM1 - A19AC-M1.3sapp-26878-flows.ts:5039-5072
BR-05"Dời buổi" bắt buộc: id buổi, ngày mới (mặc định ngày mai 15:00Z), khung giờ, phòng, giáo viên (điền từ bước Tạo giáo viên), lý do (mặc định "Test US-06"); hình thức OFFLINE cố định; nội dung buổi để trống = giữ nguyênM1 - A20AC-M1.4sapp-26878-flows.ts:5087-5167
BR-06"Hủy buổi (trigger thay thế)" gửi id buổi và lý do (mặc định "Test US-06 — hủy buổi", được phép rỗng)M1 - A21AC-M1.5sapp-26878-flows.ts:5183-5208
BR-07Đọc kết quả lọc log SAP theo deal_id, tự chạy 6 kiểm chứng (§M2), luôn coi là xong; panel SQL 3 câu đọc + 1 câu ghi (xóa vết đảo phía sổ cái để dựng lại ca)M2 - A22AC-M2.2 → AC-M2.8sapp-26878-flows.ts:5223-5329
BR-08Mọi câu SQL ghi không tự chạy và phải qua hộp xác nhậnM2AC-M2.8fe/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-06 · DTTH đảo buổi", portal Dev | Staging]
  ↓
[M1] U01:1 → U01:2 → U01:3 → U01:5 → U01:4 → U01:6 … U01:16 (dựng bút toán gốc)
  ↓
[M2] Kiểm buổi đã được ghi
  ↓
[M1] Tạo giáo viên → Kiểm buổi có học viên → Dời buổi  ─┐ (chỉ MỘT trong hai mỗi lượt,
                                         Hủy buổi ──────┘  bước còn lại "Bỏ qua")
  ↓
[M2] Đọc kết quả

Bảng bước (Fact: sapp-26878-flows.ts:5345-5379).

#Tên bướcLoạiTái dùngGhi gì (hệ thống · môi trường)Điều kiện chuyển (xong)
1Kiểm tra kết nối Opsops + sqlU01:1Không ghiPing thành công
2Đếm lớp của mônopsU01:2Không ghiGọi thành công
3Tạo lớpops + sqlU01:3Ops dev/stagingGọi thành công
4Gán phòng họcopsU01:5OpsGọi thành công
5Tạo buổi họcopsU01:4OpsGọi thành công
6Mở lớp (PUBLIC)opsU01:6OpsGọi thành công
7Thêm option mã lớpoptionU01:7HubSpot dev (staging: bỏ qua)Đủ 3 property / bỏ qua
8Tạo DealdealU01:8HubSpot (⚠️ portal prod khi Staging); Redis run historyCó deal
9Gán mã lớpclasscodeU01:9HubSpotGọi thành công
10Tạo đơn hàngopsU01:10OpsThành công, số tiền ≠ 0
11Soạn thảo hợp đồngstageU01:11HubSpotChuyển stage thành công
12Tạo giao dịchopsU01:12OpsGọi thành công
13Xác nhận giao dịchopsU01:13Ops → SAP (theo hint)Gọi thành công
14Kéo sang WonstageU01:14HubSpotChuyển stage thành công
15Hoàn thiện hồ sơstageU01:15HubSpotChuyển stage thành công
16Chạy lượt quétscanU01:16SAP service dev/stagingGọi thành công
17Kiểm buổi đã được ghitrace + sqlriêngKhông ghi → bag class_schedule_idLuôn xong
18Tạo giáo viênopsriêngOps: giáo viên test → bag teacher_idGọi thành công
19Kiểm buổi có học viênguide + sqlriêngKhông ghi (SQL us06.link chỉ đọc)Bấm "Đã có bản ghi buổi ↔ học viên"
20Dời buổiopsriêngOps: sửa lịch buổi (theo hint: bắn sự kiện đảo ngay)Gọi thành công, hoặc bỏ qua
21Hủy buổi (trigger thay thế)opsriêngOps: hủy buổi (theo hint: cùng sự kiện đảo)Gọi thành công, hoặc bỏ qua
22Đọc kết quảtrace + sqlriêngKhông ghi, trừ câu SQL ④ (Ops DB) nếu chạyLuôn xong

⚠️ Ghi PROD — trên Staging, bước 8, 9, 11, 14, 15 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 ✅ 6/6 trên dev 2026-09-18, lớp F103.215 (shared/runbooks/sapp/sapp-26878/phase-2/us-06/README.md:3-4) và một lượt trọn vẹn trên staging 2026-09-22 (.../phase-2/staging/README.md §6h).

b. Chi tiết từng màn ​

Màn M1 - Chuỗi bước dựng dữ liệu và kích hoạt (bước 1–16, 18–21) ​

FieldValue
Figma frameN/A — as-built, không có Figma
Trigger vào mànChọn chip US-06 · DTTH đảo buổi (inventory E-07)
Mô tả ngắnDựng như US-01 để có bút toán gốc, rồi dời hoặc hủy chính buổi đó.
UI States ​
StateKhi nàoHiển thịFigma frame
DefaultSitting mớiBước 1 mở (→ US-D01)N/A
LoadingĐang gọi OpsNút chạy ở trạng thái xử lýN/A
Has dataBước 18 xongteacher_id vào bag, điền sẵn vào bước 20N/A
EmptyStaging, pool mã lớp rỗngNhư US-D09 EC-M1.2N/A
ErrorOps từ chối dời / hủyLỗi Ops (vd theo hint: ngày đã có buổi, quá giờ, thiếu giáo viên)N/A
DisabledBước khóa; bước 7 trên StagingNhư US-D09N/A
Fields ​

Chỉ field riêng (Nguồn sapp-26878-flows.ts:4946-5207).

FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
B18 · full_name, email, username, phone, teacher_codeYesTextsinh từ mẫu (cùng một số điện thoại)—BR-03Lỗi Ops (trùng)Always—
B19 · class_schedule_id của buổi hôm nay—Text— (nhập tay)id——AlwaysBước 17
B20 · class_schedule_idYesTextbag (bước 17)idBR-05Lỗi OpsAlwaysBước 17
B20 · lesson_dateYesDatetime ISOngày mai 15:00ZISOHint: khác ngày cũ, không ở quá khứLỗi OpsAlways—
B20 · learning_mode—TextOFFLINE———Readonly—
B20 · class_durationYesJSON13:00–16:00JSON——Always—
B20 · classroom_idYesDropdown (phòng học)—id—Lỗi OpsAlwaysDanh mục
B20 · teacher_idYesTextbag teacher_ididBR-05Theo hint: thiếu → Ops 400/460404AlwaysBước 18
B20 · course_section_idsNoJSONrỗngmảng——Always—
B20 · reasonYesText"Test US-06"—BR-05Theo hint: rỗng → lỗi OpsAlways—
B21 · class_schedule_idYesTextbag (bước 17)idBR-06Lỗi OpsAlwaysBước 17
B21 · reasonNoText"Test US-06 — hủy buổi"—được phép rỗng—Always—
Actions ​
A18 - Tạo giáo viên (bước 18) ​
ItemDescription
TriggerBấm chạy
BehaviorTạo giáo viên test trên Ops dev/staging (BR-03). Hint: không bỏ qua được vì buổi do bộ sinh lịch tạo không có giáo viên.
Success ResultBag có teacher_id

Error cases:

CaseExpected Handling
Trùng định danhLỗi Ops
A19 - Kiểm buổi có học viên (bước 19) ​
ItemDescription
TriggerNhập id buổi, chạy câu đếm, bấm xác nhận
BehaviorChỉ đọc Ops DB (BR-04). Guide: bản ghi sinh bất đồng bộ, đếm lại vài lần; ra 0 thì lượt dời sau trả 200 mà không có gì xảy ra.
Success ResultNgười dùng bấm "Đã có bản ghi buổi ↔ học viên"

Error cases:

CaseExpected Handling
Đếm ra 0Tool không chặn; guide yêu cầu đợi, không đi tiếp
A20 / A21 - Dời buổi / Hủy buổi (bước 20, 21) ​
ItemDescription
TriggerBấm chạy một trong hai; bấm "Bỏ qua bước này" ở bước còn lại
BehaviorGhi Ops dev/staging (BR-05, BR-06). Hint: một buổi chỉ nhận một trigger; muốn kiểm cả hai phải chạy chip hai lần.
Success ResultGọi thành công; không cần lượt quét

Error cases:

CaseExpected Handling
Ngày mới đã có buổi của lớpOps từ chối (ClasScheduleExisted); chọn ngày trống
Hủy sau khi đã dờiTheo hint: Ops trả 200 nhưng không bắn sự kiện
Quá hạn giờ (dời sau 20:00 / hủy sau 23:00 giờ VN)Ops từ chối
Acceptance Criteria của màn M1 ​
AC-M1.1 - Chuỗi 22 bước ​
gherkin
Given một sitting mới của luồng US-06 phase 2
When người dùng xem stepper
Then thấy 22 bước theo §4a trong một hàng; không có bước "Trả lại mã lớp"

Maps to:

  • Business Rule: BR-01
AC-M1.2 - Giáo viên test ​
gherkin
When mở bước 18
Then năm ô định danh đã điền sẵn từ mẫu; chạy thành công thì teacher_id vào bag và điền sẵn vào bước 20

Maps to:

  • Business Rule: BR-03
AC-M1.3 - Kiểm bản ghi buổi ↔ học viên ​
gherkin
When mở bước 19
Then chỉ có câu SQL đọc và nút xác nhận; bước xong khi bấm "Đã có bản ghi buổi ↔ học viên"

Maps to:

  • Business Rule: BR-04
AC-M1.4 - Dời buổi ​
gherkin
Given bag có class_schedule_id và teacher_id
When mở bước 20
Then các ô bắt buộc đã điền sẵn (ngày mới = ngày mai 15:00Z, lý do "Test US-06"), learning_mode = OFFLINE chỉ đọc

Maps to:

  • Business Rule: BR-05
AC-M1.5 - Hủy buổi thay thế ​
gherkin
Given bước 20 đã được bỏ qua
When chạy bước 21
Then yêu cầu hủy gửi id buổi và lý do (được phép rỗng)

Maps to:

  • Business Rule: BR-06
Negative AC / Edge Cases của màn M1 ​
IDTình huốngHành vi mong đợi
EC-M1.1⚠️ Observed — chạy luồng trên StagingLuồ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 §6h 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 "US-06 24 bước"Code hiện có 22 bước (có thể do thay đổi sau ngày ghi) — DR-D-07 — xem 00-overview §6b
EC-M1.3Chạy cả bước 20 và 21 trong một lượtTool không chặn; theo hint, trigger thứ hai không bắn gì
EC-M1.4Staging — phòng học trùng lịchTheo runbook staging §6h: Ops trả room_schedule_conflicted; chọn phòng khác
EC-M1.5⚠️ Observed — "Dùng deal có sẵn" ở bước 8Như US-D09 EC-M1.3 — OQ-D-06

Màn M2 - Bước 17 "Kiểm buổi đã được ghi" và bước 22 "Đọc kết quả" ​

FieldValue
Figma frameN/A — as-built, không có Figma
Trigger vào mànMở bước 17 / 22
Mô tả ngắnHai bước đọc lọc theo deal_id (→ US-P05); bước 17 có 1 kiểm chứng, bước 22 có 6.
UI States ​
StateKhi nàoHiển thịFigma frame
DefaultMở bướcHint + mã lớp + trace tự chạy + panel SQLN/A
LoadingĐang traTrace đang tảiN/A
Has dataCó trailKết quả kiểm chứngN/A
EmptyKhông có lượt EVENT_RESCHEDULEHint: bị loại ở cổng (go-live / sửa ngày khai giảng), không phải sự kiện chưa tớiN/A
ErrorTrace / SQL lỗi→ US-P05 / US-P09N/A
DisabledN/AN/AN/A
Fields ​
FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
B22 · class_schedule_id của buổi đã đảo—Text—idHint: cùng id đã dùng ở bước 20/21—AlwaysBước 17
Actions ​
A17 - Kiểm buổi đã được ghi (bước 17) ​
ItemDescription
TriggerMở bước (trace + SQL tự chạy)
BehaviorĐọc Ops DB + trace, điền class_schedule_id (BR-02). Không ghi.
Success ResultBước luôn xong

Error cases:

CaseExpected Handling
Không có dòng PER_LESSONKiểm chứng fail kèm giải thích (buổi hôm nay bị chốt sổ, hoặc chưa quét / chưa PUBLIC / chưa có học viên)
A22 - Đọc kết quả (bước 22) ​
ItemDescription
TriggerMở bước (tự chạy); chạy tay SQL
BehaviorTrace + 6 kiểm chứng (BR-07). SQL ①–③ đọc (sổ cái lớp, nhóm cột đảo của buổi, lượt EVENT_RESCHEDULE); ④ ghi Ops DB xóa vết đảo để dựng lại ca (BR-08). Ghi chú ④: bút toán đảo đã tạo phía SAP vẫn còn.
Success ResultBước luôn xong

Error cases:

CaseExpected Handling
Không đọc được trườngKiểm chứng = unknown
Acceptance Criteria của màn M2 ​

AC = kiểm chứng tự chấm (sapp-26878-flows.ts:5006-5015,5223-5282).

AC-M2.1 - Buổi hôm nay được ghi như buổi thường (bước 17) ​
gherkin
When bước 17 chạy kiểm chứng "Buổi hôm nay được ghi như buổi thường"
Then pass khi có ít nhất một dòng sổ cái entry_type = PER_LESSON

Maps to:

  • Business Rule: BR-02
AC-M2.2 - Payload mang recognition_type = LESSON_REVERSAL ​
gherkin
When bước 22 chạy kiểm chứng tương ứng
Then pass khi phần tử cuối của payload có recognition_type = LESSON_REVERSAL

Maps to:

  • Business Rule: BR-07
AC-M2.3 - Đảo trỏ thẳng vào bút toán gốc ​
gherkin
Then pass khi phần tử cuối của payload CÓ original_external_reference

Maps to:

  • Business Rule: BR-07
AC-M2.4 - Đảo mang định danh buổi gốc ​
gherkin
Then pass khi phần tử cuối của payload CÓ lesson_id

Maps to:

  • Business Rule: BR-07
AC-M2.5 - document_date = u_lesson_date = ngày buổi bị hủy ​
gherkin
Then pass khi ở phần tử cuối, document_date bằng u_lesson_date

Maps to:

  • Business Rule: BR-07
AC-M2.6 - Có khối batch ​
gherkin
Then pass khi phong bì (cấp ngang payloads) của lời gọi cuối CÓ khối batch

Maps to:

  • Business Rule: BR-07
AC-M2.7 - Có khối scope_evidence ​
gherkin
Then pass khi phong bì của lời gọi cuối CÓ khối scope_evidence

Maps to:

  • Business Rule: BR-07
AC-M2.8 - Bước đọc không chặn · dựng lại ca ​
gherkin
Given một kiểm chứng fail hoặc unknown
Then bước 22 vẫn "xong"
When chạy câu SQL ④ và xác nhận
Then nhóm cột đảo của buổi đã chọn về rỗng và các lượt EVENT_RESCHEDULE bị xóa

Maps to:

  • Business Rule: BR-07, BR-08
Negative AC / Edge Cases của màn M2 ​
IDTình huốngHành vi mong đợi
EC-M2.1Không có kiểm chứng nào về số tiềnTheo code: đúng thiết kế — payload đảo không mang trường tiền, SAP tự tra (sapp-26878-flows.ts:5210-5222)
EC-M2.2⚠️ Observed (OQ-D-19) — câu ④ xóa mọi lượt EVENT_RESCHEDULE của môi trườngKhông lọc theo lớp (sapp-26878-flows.ts:5324) — đề xuất OQ "cố ý hay bug?" (cùng dạng US-D13 EC-M2.3)
EC-M2.3Kiểm chứng fail nhưng đi tiếpKhông có gate — OQ-D-15

5. Cross-feature AC ​

AC-X.1 - Dùng lại bước US-01 ​

gherkin
Given bước U01:1–16 thay đổi ở US-01
When mở luồng US-06 phase 2
Then luồng dùng đúng định nghĩa mới

Maps to:

  • Liên quan nội bộ FS 26878 (không có mã REL) (US-D09)

AC-X.2 - Xóa buổi ở US-03 / US-04 cũng bắn sự kiện đảo ​

gherkin
Given một buổi đã có học viên
When bước "Xóa buổi đuôi" của US-03 / US-04 xóa buổi đó
Then theo hint, cùng sự kiện đảo của US-06 được bắn (không có bút toán gốc → ERR-03 + mail kế toán)

Maps to:

  • Liên quan nội bộ FS 26878 (không có mã REL) (US-D11, US-D12)