Skip to content

US-D16: Flow P2 — DTTH đồng bộ lại (story SAPP US-08 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-126). 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.

⚠ Không nhầm với "đồng bộ lại theo story" US-08/09/10/12/14 của phase 1 (US-D18) — chip này là story US-08 phase 2 (id us08-p2), gửi lại dòng sổ cái DTTH.

FieldValue
US IDUS-D16
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-08 · DTTH đồng bộ lại (id us08-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 — 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 dòng sổ cái ở trạng thái lỗi, bấm gửi lại theo dòng và theo lớp, rồi dựng lần lượt sáu
       trạng thái phải bị chặn
So that kiểm được rằng kế toán gửi lại được các dòng sổ cái bị lỗi mà tuyệt đối không sinh bút toán trùng
  • Nguồn "So that": shared/runbooks/sapp/sapp-26878/phase-2/us-08/README.md:6-8 ("Kế toán bấm tay gửi lại các dòng sổ cái bị lỗi, và tuyệt đối không sinh bút toán trùng … Trọng tâm là những ca KHÔNG gửi lại"); hint luồng sapp-26878-flows.ts:5909. 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; hai thao tác gửi lại đi qua Ops passthrough (US-P08, inventory E-27 "sap-revenue resync").

3. Business Rules ​

IDRuleÁp dụng ởĐã cover bởi (AC)Nguồn code (Mode B/C)
BR-01Luồng có 22 bước: U01:1 → U01:16 rồi 6 bước riêng theo thứ tự ở §4a; không có bước trả lại mã lớpM1AC-M1.1fe/src/ui/components/works/sapp/sapp-26878-flows.ts:5911-5947
BR-02"Đọc sổ cái" là bước đọc không có kiểm chứng tự động (lọc theo deal_id), kèm 2 câu SQL chỉ đọcM2 - A17AC-M2.1sapp-26878-flows.ts:5635-5662
BR-03"Dựng dòng lỗi": câu đọc tự chạy và điền sẵn entry_id (dòng sớm nhất theo ngày buổi); câu ghi đưa dòng đó về FAILED · ERR-04M1 - A18AC-M1.2sapp-26878-flows.ts:5678-5714
BR-04"Đồng bộ lại theo dòng" gửi lại đúng một dòng theo entry_id (không có thân request); bấm lặp đượcM1 - A19AC-M1.3sapp-26878-flows.ts:5723-5742
BR-05"Đồng bộ lại theo lớp" gửi lại mọi dòng chưa chốt của lớp theo class_id từ bag (không có thân request); bấm lặp đượcM1 - A21AC-M1.4sapp-26878-flows.ts:5750-5761
BR-06"Đọc kết quả gửi lại" lọc theo deal_id, tự chạy 3 kiểm chứng, luôn coi là xongM2 - A20AC-M2.2 → AC-M2.5sapp-26878-flows.ts:5772-5812
BR-07"Dựng sáu chốt chặn" là bước hướng dẫn, xong khi bấm xác nhận; panel SQL 6 câu đều ghi (5 câu dựng từng trạng thái chặn, 1 câu đưa dòng về trạng thái test được và xóa lượt chạy gửi lại)M1 - A22AC-M1.5sapp-26878-flows.ts:5829-5894
BR-08Câu SQL ghi không tự chạy và phải qua hộp xác nhậnM1 - A18, A22AC-M1.2, AC-M1.5fe/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-08 · DTTH đồng bộ lại", portal Dev | Staging]
  ↓
[M1] U01:1 → … → U01:16 (dựng dòng sổ cái)
  ↓
[M2] Đọc sổ cái → [M1] Dựng dòng lỗi → Đồng bộ lại theo dòng
  ↓
[M2] Đọc kết quả gửi lại → [M1] Đồng bộ lại theo lớp → Dựng sáu chốt chặn
                                   (mỗi chốt: chạy 1 câu SQL → bấm lại "Đồng bộ lại theo dòng" → đọc lại)

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

#Tên bướcLoạiTái dùngGhi gì (hệ thống · môi trường)Điều kiện chuyển (xong)
1–16Kiểm tra kết nối Ops … Chạy lượt quétnhư US-D09U01:1 → U01:16 (đúng thứ tự)Như US-D09 §4a bước 1–16 (⚠️ HubSpot portal prod khi Staging)Như US-D09
17Đọc sổ cáitrace + sqlriêngKhông ghiLuôn xong
18Dựng dòng lỗiguide + sqlriêngOps DB: us08.seed.2 sửa trạng thái một dòng sổ cái → bag entry_idBấm "Đã dựng dòng lỗi"
19Đồng bộ lại theo dòngopsriêngOps → gửi lại SAP một dòng (dev/staging)Gọi thành công
20Đọc kết quả gửi lạitraceriêngKhông ghiLuôn xong
21Đồng bộ lại theo lớpopsriêngOps → gửi lại SAP các dòng chưa chốt của lớpGọi thành công
22Dựng sáu chốt chặnguide + sqlriêngOps DB: us08.guards.1–6 (chỉ khi người dùng chạy)Bấm "Đã đọc sáu chốt chặn"

⚠️ 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 ✅ 3/3 + 5/5 chốt chặn trên dev 2026-09-18, hai ca chưa dựng được (shared/runbooks/sapp/sapp-26878/phase-2/us-08/README.md:3-4); staging ✅ 2026-09-22 (.../phase-2/staging/README.md §6i).

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

Màn M1 - Chuỗi bước dựng dữ liệu và gửi lại (bước 1–16, 18, 19, 21, 22) ​

FieldValue
Figma frameN/A — as-built, không có Figma
Trigger vào mànChọn chip US-08 · DTTH đồng bộ lại (inventory E-07)
Mô tả ngắnDựng như US-01 để có dòng sổ cái, ép dòng về lỗi, gửi lại hai chế độ, rồi dựng các ca bị chặn.
UI States ​
StateKhi nàoHiển thịFigma frame
DefaultSitting mớiBước 1 mở (→ US-D01)N/A
LoadingĐang gọi Ops / chạy SQLNút chạy ở trạng thái xử lýN/A
Has dataBước 19 / 21 xongResponse (bước 21 có entries_queued)N/A
EmptyStaging, pool mã lớp rỗngNhư US-D09 EC-M1.2N/A
ErrorAPI gửi lại từ chốiTheo hint: dòng không tồn tại / đã SUCCESS / đã đảo → lỗi ngay; lớp không còn dòng chưa chốt → "không tìm thấy dòng sổ cái"N/A
DisabledBước khóa; bước 7 trên StagingNhư US-D09N/A
Fields ​
FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
B19 · entry_idYesTextbag entry_id (bước 18)id dòng sổ cáiHint: không phải id buổi / dealLỗi OpsAlwaysBước 18

Bước 21 không có field (dùng class_id từ bag). Field bước 1–16 → US-D09.

Actions ​
A18 - Dựng dòng lỗi (bước 18) ​
ItemDescription
TriggerMở bước (câu ① tự chạy), chạy câu ② (xác nhận), bấm "Đã dựng dòng lỗi"
BehaviorGhi Ops DB dev/staging (BR-03, BR-08). Guide: chỉ FAILED và PENDING được gửi thẳng; không xóa mốc đã post của dòng SAP đã thật sự ghi.
Success ResultDòng ở FAILED · ERR-04; entry_id trong bag

Error cases:

CaseExpected Handling
Lớp chưa có dòng sổ cáiCâu ① trả rỗng, entry_id trống
A19 / A21 - Đồng bộ lại theo dòng / theo lớp (bước 19, 21) ​
ItemDescription
TriggerBấm chạy (lặp được)
BehaviorGửi lại qua Ops dev/staging → SAP (BR-04, BR-05). Hint: gọi lần hai ngay sau lần một bị chặn vì dòng đã sang SENT (ca EC-M1.1 của story — kết quả đúng); entries_queued là số dòng được chọn (trần 200), không phải số đã gửi.
Success ResultGọi thành công

Error cases:

CaseExpected Handling
Dòng đã SUCCESS / đã đảo / không tồn tạiAPI trả lỗi ngay (hint)
Lớp không còn dòng chưa chốtAPI trả lỗi "không tìm thấy dòng sổ cái" (hint: đúng thiết kế)
A22 - Dựng sáu chốt chặn (bước 22) ​
ItemDescription
TriggerChạy một câu SQL (xác nhận) → quay lại bước 19 bấm gửi lại → đọc lại ở bước 20; lặp cho từng ca; bấm "Đã đọc sáu chốt chặn"
BehaviorGhi Ops DB dev/staging (BR-07, BR-08): ① đã có bút toán trên SAP, ② đã bị đảo, ③ đã chốt SUCCESS, ④ ERR-05, ⑤ đang chờ SAP (SENT), ⑥ đưa dòng về trạng thái test được + xóa lượt EVENT_RESYNC. Guide: kết quả đúng của mọi ca chặn là "được chọn nhưng không gửi".
Success ResultBước xong khi xác nhận

Error cases:

CaseExpected Handling
Chạy ⑥ khi SAP đã thật sự tạo bút toánGuide cảnh báo: vô hiệu hóa chốt chặn chống trùng; tool không chặn
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-08 phase 2
When người dùng xem stepper
Then bước 1–16 trùng US-01, bước 17–22 lần lượt "Đọc sổ cái", "Dựng dòng lỗi", "Đồng bộ lại theo dòng", "Đọc kết quả gửi lại", "Đồng bộ lại theo lớp", "Dựng sáu chốt chặn"
And không có bước "Trả lại mã lớp"

Maps to:

  • Business Rule: BR-01
AC-M1.2 - Ép dòng về lỗi ​
gherkin
Given lớp đã có dòng sổ cái
When mở bước 18
Then câu ① tự chạy và điền entry_id của dòng sớm nhất
When chạy câu ② và xác nhận
Then dòng đó có status = FAILED, error_code = ERR-04

Maps to:

  • Business Rule: BR-03, BR-08
AC-M1.3 - Gửi lại theo dòng ​
gherkin
Given bag có entry_id
When bấm chạy bước 19
Then tool gọi gửi lại đúng dòng đó, không kèm thân request

Maps to:

  • Business Rule: BR-04
AC-M1.4 - Gửi lại theo lớp ​
gherkin
When bấm chạy bước 21
Then tool gọi gửi lại theo class_id của lượt, không kèm thân request, và hiện entries_queued trong response

Maps to:

  • Business Rule: BR-05
AC-M1.5 - Dựng chốt chặn ​
gherkin
When mở bước 22
Then thấy 6 câu SQL đều là câu ghi (tô đỏ, cần xác nhận) và checklist các ca chặn

Maps to:

  • Business Rule: BR-07, BR-08
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 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 (OQ-D-18) — guide bước 18 ghi "⚠ Chỉ làm trên dev"Bước không bị khóa trên Staging; runbook §6i ghi đã chạy US-08 trên staging. Đề xuất OQ — điều phối viên cấp mã
EC-M1.3⚠️ Observed (OQ-D-19) — câu ⑥ bước 22 xóa mọi lượt EVENT_RESYNC của môi trườngKhông lọc theo lớp (sapp-26878-flows.ts:5866) — cùng dạng US-D13 EC-M2.3; đề xuất OQ
EC-M1.4Ca "kỳ đã đóng sổ" (checklist ⑤)Không có câu SQL dựng; guide: chọn dòng thuộc tháng đã qua mốc đóng sổ, chỉ chạy đúng khi đã nạp lịch nghỉ lễ
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 "Đọc sổ cái" và bước 20 "Đọc kết quả gửi lại" ​

FieldValue
Figma frameN/A — as-built, không có Figma
Trigger vào mànMở bước 17 / 20
Mô tả ngắnHai bước đọc lọc theo deal_id (→ US-P05); bước 17 không có kiểm chứng, bước 20 có 3.
UI States ​
StateKhi nàoHiển thịFigma frame
DefaultMở bướcHint + mã lớp + trace tự chạy (+ panel SQL us08.read ở bước 17)N/A
LoadingĐang traTrace đang tảiN/A
Has dataCó trailBước 20: kết quả 3 kiểm chứngN/A
EmptyChưa có lượt gửi lạiTrace không có phần gửi lạiN/A
ErrorTrace lỗi→ US-P05N/A
DisabledN/AN/AN/A
Fields ​

N/A — bước chỉ đọc.

Actions ​
A17 / A20 - Đọc sổ cái / Đọc kết quả gửi lại ​
ItemDescription
TriggerMở bước (tự chạy)
BehaviorBước 17: trace + 2 câu SQL đọc (sổ cái lớp; dấu vết lượt gửi lại trong log) (BR-02). Bước 20: trace + 3 kiểm chứng (BR-06). Không ghi.
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-M2.2 → AC-M2.4 = kiểm chứng tự chấm của bước 20 (sapp-26878-flows.ts:5772-5800).

AC-M2.1 - Đọc sổ cái không chấm ​
gherkin
When mở bước 17
Then trace tự chạy, không có kiểm chứng tự động, và panel có 2 câu SQL chỉ đọc

Maps to:

  • Business Rule: BR-02
AC-M2.2 - Gửi lại mang ngày gửi lại, giữ nguyên ngày buổi ​
gherkin
Then pass khi có ít nhất một phần tử payload có document_date khác u_lesson_date

Maps to:

  • Business Rule: BR-06
AC-M2.3 - Giữ nguyên công thức của dòng gốc ​
gherkin
Then pass khi phần tử cuối của payload có recognition_type = PER_LESSON

Maps to:

  • Business Rule: BR-06
AC-M2.4 - Giữ nguyên khóa của dòng cũ ​
gherkin
Then pass khi phần tử cuối của payload CÓ external_reference

Maps to:

  • Business Rule: BR-06
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 20 vẫn "xong" và bước 21 mở

Maps to:

  • Business Rule: BR-06
Negative AC / Edge Cases của màn M2 ​
IDTình huốngHành vi mong đợi
EC-M2.1Gửi lại một dòng không phải buổi thườngKiểm chứng "Giữ nguyên công thức" cố định PER_LESSON → fail; theo hint, người dùng tự đổi giá trị mong đợi theo loại dòng
EC-M2.2Ca chặn: "được chọn" > 0 mà "đã gửi" = 0Theo hint: kết quả đúng; tool không tự chấm các ca chặn — người dùng đọc counters.skipped — 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-08 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 - Gửi lại thô cùng thao tác Ops ​

gherkin
Given chip Trace "Gửi lại bút toán (P2)" / "Gửi lại lớp (P2)"
When người dùng gửi lại theo id ở đó
Then đó là cùng loại thao tác gửi lại dòng / lớp qua Ops như bước 19 / 21, không qua stepper (inventory A-91 → US-D18)

Maps to:

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

AC-X.3 - US-09 chặn gửi lại dòng ERR-05 ​

gherkin
Given US-D17 dựng dòng thiếu trường (SENT + ERR-05, có mốc đã post)
When gửi lại dòng đó ở bước 19
Then theo guide US-09, dòng bị chặn (skipped.ALREADY_POSTED)

Maps to:

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