Skip to content

US-D03: Thực hiện một bước theo loại (deal · guide · stage · sync · link · resync · ops · option · classcode · scan · trace · sql) ​

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. As-built tại commit e77c47a. Nguồn Fact: inventory 26878 A-20 … A-31 (§3.1), R-03 … R-33 (§5). Đây là danh mục loại bước. Các US flow (US-D04 … US-D17) chỉ ghi "bước n = loại X" và tham chiếu khối M<n> ở đây, không lặp lại hành vi.

FieldValue
US IDUS-D03
Role thực hiệnR1 - Người dùng tool (Assumption (OQ về G-01), OQ-D-05)
PhaseAs-built (đã triển khai) — dùng chung cho phase 1 và phase 2
PriorityN/A (as-built)
StatusDraft
NFR liên quanNFR-D-01, NFR-D-02, NFR-D-03, NFR-D-04, NFR-D-06, NFR-D-07, NFR-D-08 — xem Overview §5
OQ liên quanOQ-D-02, OQ-D-06, OQ-D-09, OQ-D-12, OQ-D-14, OQ-D-15, OQ-D-16 — xem Overview §6

1. US Statement &ZeroWidthSpace;

text
As a Người dùng tool (Assumption — OQ về G-01)
I want thực hiện từng bước của flow bằng một khối giao diện đúng loại bước đó (tạo deal, làm theo hướng dẫn,
       chuyển stage, ghi property, gọi Ops, quét, đọc kết quả, chạy SQL)
So that dữ liệu test được tạo đúng hệ thống và đúng môi trường cho kịch bản "Đồng bộ Deal → hóa đơn SAP" (phase 1)
        và "DTTH — ghi nhận theo buổi…" (phase 2) (trích shared/runbooks/sapp/sapp-26878/README.md:10-11);
        lợi ích cụ thể cho người dùng: [Assumption]

2. Dependencies & Definition Of Ready &ZeroWidthSpace;

N/A — đã triển khai (Mode B). Dependency runtime:

#Cần sẵn sàngAi cung cấpTrạng thái
D1Credential HubSpot dev / prod portal (staging dùng credential prod)BE / AdminN/A — runtime
D2Danh mục pipeline theo flow × portal ở BEBEN/A — runtime
D3env_systems cho Ops API, Ops DB, SAP service theo môi trường (→ US-P04)Admin CMSN/A — runtime
D4Dịch vụ nền tảng: Ops passthrough (US-P08), SQL runner (US-P09), tra log / quét (US-P05), option property (US-P07)BEN/A — runtime

3. Business Rules &ZeroWidthSpace;

IDRuleÁp dụng ởĐã cover bởi (AC)Nguồn code (Mode B/C)
BR-01Tạo deal bị chặn cho tới khi có: pipeline, deal stage, mọi property bắt buộc của flow (chung + theo nhánh cá nhân / doanh nghiệp + nhóm có điều kiện), và contact (contact mới phải có tên, hoặc chọn ≥ 1 contact có sẵn). Nút tắt, dưới nút hiện "Còn thiếu: <danh sách>". Chế độ "Dùng deal có sẵn" chỉ cần Deal id.M1 - action Tạo dealAC-M1.1, AC-M1.3sapp-26878-step1.tsx:448-485,1156-1175
BR-02Property "khuyến nghị" để trống và cảnh báo theo flow chỉ là cảnh báo mềm (danh sách cảnh báo), không chặn tạo deal.M1AC-M1.2sapp-26878-step1.tsx:487-508; sapp-26878-flows.ts:893-894
BR-03Khi tạo deal, ô để trống không gửi lên; pipeline và deal stage luôn gửi.M1AC-M1.1sapp-26878-step1.tsx:577-584
BR-04BE chỉ nhận property trong danh sách cho phép (52 property); property lạ → lỗi 400 13027; hs_object_id bị bỏ qua.M1EC-M1.2sapp.controller.ts:2596-2621; sapp-26878.constants.ts:18-99,176
BR-05Tên deal do server sinh theo mẫu [IT TEST][SAPP-26878] <nhãn flow> <n>, n đếm theo cùng tiền tố; người dùng không đặt được.M1AC-M1.1sapp.controller.ts:2623-2645; common.service.ts:1624-1634; sapp-26878.constants.ts:512-539
BR-06Danh tính test (SĐT, CCCD, email suy từ SĐT, tên chứa SĐT, địa chỉ) sinh một lần cho mỗi deal, chỉ điền vào ô người dùng chưa sửa và chỉ vào property mà flow hiển thị.M1AC-M1.4sapp-26878-tool.tsx:399-404,541-547,616-710
BR-07Danh sách pipeline theo flow × portal do BE cấu hình; portal không có pipeline (prod) → danh sách rỗng, không gọi HubSpot; flow lạ → lỗi SAPP_26878_UNKNOWN_FLOW. Rỗng → cảnh báo "Chưa cấu hình pipeline nào cho luồng này ở môi trường <env>…".M1 - field PipelineEC-M1.3sapp.controller.ts:3616-3649; sapp-26878-step1.tsx:704-714
BR-08Mọi thao tác đọc / ghi trên một deal có sẵn (đọc stage, chuyển stage, gán mã lớp, sync, gắn deal gốc, đồng bộ lại) chỉ chấp nhận deal nằm trong danh sách deal tool đã tạo trên đúng môi trường; ngược lại lỗi 400 13033.M3, M4, M5, M6, M9AC-M3.3sapp.controller.ts:2762-2773,2789,2810,2892,3047,3112,3341
BR-09Bước hướng dẫn (guide) không gọi API; hiện nội dung làm tay trên SAPP OPS, deal id cần mang theo, "công thức" đơn (flow chuỗi); xong khi bấm "Đã hiểu" (hoặc nhãn riêng của bước).M2AC-M2.1sapp-26878-step-guide.tsx:45-60; sapp-26878-tool.tsx:870,1360-1373
BR-10Chuyển stage chỉ ghi dealstage, không sửa property khác.M3AC-M3.1sapp.controller.ts:2755-2757,2810-2815
BR-11Stage gợi ý so khớp theo nhãn stage (bỏ khoảng trắng đầu cuối, không phân biệt hoa thường), không theo id.M3AC-M3.2sapp-26878-step-stage.tsx:35,100-107; sapp-26878-flows.ts:624-629
BR-12Sync gói khóa học: gộp các giá trị (tách bằng ;) từ 6 property lộ trình, chỉ giữ giá trị có trong danh sách option không ẩn của goi_khoa_hoc, gộp với giá trị cũ; không có giá trị mới → không ghi.M4AC-M4.1, EC-M4.1sapp.controller.ts:2887-2957; sapp-26878.constants.ts:114-121
BR-13Gắn deal gốc và gán mã lớp không ghi lại nếu giá trị trên HubSpot đã đúng (báo "không ghi lại").M5, M9AC-M5.2, AC-M9.2sapp.controller.ts:3075-3083,3121-3126; sapp-26878-step-link.tsx:128-130
BR-14Đồng bộ lại luôn ghi chuỗi Đồng bộ lại vào property đích (hóa đơn → trang_thai_dong_bo_hoa_don, reconcile → trang_thai_tu_dong_reconcile), vô điều kiện, và trả về giá trị trước đó; giá trị trước đó trống → cảnh báo "chưa từng qua SAP" hiện sau khi đã ghi.M6AC-M6.1, AC-M6.2sapp.controller.ts:3328-3366; sapp-26878-step-resync.tsx:58,75,145
BR-15Deal và loại đồng bộ lại được phép lấy từ chính các bước resync của flow (US-11/13: chỉ Deal cộng + hóa đơn; US-03/05/06: cả hóa đơn và reconcile).M6AC-M6.3sapp-26878-flows.ts:2458-2470
BR-16Bước Ops: ô trống bị bỏ khỏi payload, trừ ô được khai cho phép trống (vd link_meeting); giá trị thu được từ response được lưu vào kho id của phiên cho bước sau.M7AC-M7.1sapp-26878-flows.ts:154-162; sapp-26878-step-ops.tsx:648-690
BR-17Tạo đơn hàng Ops mà đơn ra số tiền 0 → báo lỗi "Đơn hàng tạo ra có số tiền bằng 0", bước không được tính là xong.M7AC-M7.2sapp-26878-step-ops.tsx:636-646
BR-18Số tiền giao dịch lấy từ số tiền của đơn (order_amount), không có giá trị mặc định.M7AC-M7.3sapp-26878-flows.ts:3254-3259; sapp-26878-step-ops.tsx:670-672
BR-19Danh mục dropdown phase 2 (môn, khoá, cơ sở, nhân sự, sản phẩm, phòng) chỉ có cho Dev + Staging; portal không có danh mục → lỗi 501 (không trả rỗng).M7 - field dropdownEC-M7.2sapp.controller.ts:640-657
BR-20Thêm option mã lớp chỉ chạy ở Dev (Staging dùng credential portal prod → phải làm tay rồi bỏ qua); ghi tuần tự vào 3 property; bước chỉ xong khi cả 3 đều có giá trị.M8AC-M8.1, AC-M8.2sapp-26878-step-option.tsx:69-117,165-166; sapp-26878-flows.ts:3080-3093
BR-21Chạy lượt quét tắt ở Prod (không có route prod); chỉ khi lượt quét được xếp hàng thì bước mới xong — tính năng quét đang tắt thì không mở bước sau.M10AC-M10.1, AC-M10.2sapp-26878-step-scan.tsx:56-70,89; fe/src/data/constants/api.ts:261-266
BR-22Bước "Đọc kết quả" (trace) luôn được tính là xong, không chặn bước sau; tra log lọc theo deal_id (mặc định) hoặc class_code; check kịch bản không đọc được field → "unknown", không phải "fail".M11AC-M11.1, AC-M11.2sapp-26878-tool.tsx:883-884,1465-1501; sapp-26878-flows.ts:382-384
BR-23Panel SQL chỉ chạy Dev / Staging, theo statement id (không gửi text SQL); câu đọc có thể tự chạy khi mở bước; câu ghi tô đỏ, không bao giờ tự chạy, phải qua hộp xác nhận "Chạy câu GHI này trên <ENV>? … Không có undo."; panel không ảnh hưởng gate bước.M12AC-M12.1, AC-M12.2sapp-26878-step-sql.tsx:40,190-213; sapp-26878-flows.ts:584-590,607-612; sapp-26878-tool.tsx:1640-1650

⚠️ Observed (không viết thành BR):

  • BE có route prod cho mọi thao tác ghi của các khối M1, M3–M7, M9 — chặn prod chỉ ở giao diện (NFR-D-02, OQ-D-02).
  • "Dùng deal có sẵn" không kiểm deal id có tồn tại / do tool tạo (EC-M1.4, OQ-D-06).
  • Tạo contact trùng email → cập nhật contact cũ (EC-M1.5, OQ-D-16).
  • Chạy lượt quét là GET có tác dụng phụ (EC-M10.2, OQ-D-09).
  • Id câu SQL phía FE có thể lệch id phía BE (EC-M12.3, OQ-D-14).

4. Design &ZeroWidthSpace;

a. Mối liên hệ giữa các màn & User Flow &ZeroWidthSpace;

Mỗi bước của stepper (US-D01.M2) render một khối theo loại. Khối xong → stepper tự chuyển bước (US-D01 BR-08). Panel SQL (M12) có thể gắn vào bất kỳ khối nào.

text
[US-D01.M2 Stepper] ── bước n, loại X ──→ [Khối M<X>]
   ├─ thành công ──→ bước n "xong" ──→ bước n+1
   ├─ lỗi ──────────→ ở lại khối, thông báo lỗi
   └─ "Bỏ qua bước này" ──→ US-D01.M3

Ma trận ghi dữ liệu theo loại bước (Dev / Staging / Prod là portal chọn ở US-D01.M1):

KhốiLoạiGhi vào hệ thống nàoDevStagingProdĐiều kiện "xong"
M1dealHubSpot deal + contact; Redis mind_keep (danh sách deal/contact tool đã tạo)HubSpot dev portal⚠️ HubSpot prod portal (pipeline [UAT-TEST])FE chặn; BE có route (⚠️ Observed)Có deal của khối (chuỗi: đủ deal của khối)
M2guide— (làm tay trên SAPP OPS)———Bấm "Đã hiểu"
M3stageHubSpot deal dealstage → kéo Won bắn event SAP (qua webhook)dev portal⚠️ prod portalFE chặn; BE có routeChuyển thành công
M4syncHubSpot deal goi_khoa_hocdev portal⚠️ prod portalFE chặn; BE có routeGọi thành công
M5linkHubSpot deal deal_id_goc_cua_chuyen_doidev portal⚠️ prod portalFE chặn; BE có routeGọi thành công
M6resyncHubSpot deal (property trạng thái đồng bộ) → webhook SAPdev portal⚠️ prod portalFE chặn; BE có routeBấm ≥ 1 lần thành công
M7opsSAPP Ops API (qua passthrough, US-P08)Ops devOps stagingFE chặn; BE có route ghi prodGọi thành công
M8optionĐịnh nghĩa property HubSpot (US-P07)HubSpot devTự chặn (làm tay)FE chặnCả 3 property có option
M9classcodeHubSpot deal + contact (mã lớp)dev portal⚠️ prod portalFE chặn; BE có routeGọi thành công
M10scanSAP service (lms-be) — bắn lượt quét (US-P05)devstagingKhông có routeLượt quét được xếp hàng
M11trace— chỉ đọc (US-P05)devstaging(stepper không chạy prod)Luôn xong
M12sqlSAPP Ops DB (US-P09)Ops DB devOps DB stagingKhông có routeKhông ảnh hưởng gate

b. Chi tiết từng màn &ZeroWidthSpace;

Màn M1 - Khối deal — "Tạo deal" &ZeroWidthSpace;

FieldValue
Figma frameN/A
Trigger vào mànMở bước loại deal (mỗi flow có ≥ 1; flow chuỗi có một bước deal cho mỗi mắt xích)
Mô tả ngắnChọn "Tạo deal mới" / "Dùng deal có sẵn" (nếu flow cho phép), chọn pipeline + stage, điền property theo spec của flow (khối bắt buộc, khuyến nghị, tuỳ chọn, bị loại kèm lý do), tạo contact mới hoặc chọn contact có sẵn, rồi "Tạo deal". Flow chuỗi hiện thêm bảng "Chuỗi deal đã dựng (<x>/<n>)" và công thức đơn Ops.
UI States &ZeroWidthSpace;
StateKhi nàoHiển thịFigma frame
DefaultVừa mởForm theo spec deal của flow; nút "Tạo deal"N/A
LoadingĐang tải pipeline / contact"Đang tải…" ở ô PipelineN/A
Has dataĐã tạo deal (lần này hoặc trước đó trong phiên)Khung xanh "Đã tạo xong data cho bước 1" + Deal id — tên deal + Contact id + "Giữ lại deal id này cho các bước sau của luồng."N/A
EmptyKhông có pipeline cho flow × portalCảnh báo "Chưa cấu hình pipeline nào cho luồng này ở môi trường <env>. Bổ sung id vào SAPP_26878_PIPELINE_IDS ở BE trước khi test."N/A
ErrorTạo contact / deal lỗiThông báo "Tạo contact thất bại" / "Tạo deal thất bại" / "Đã tạo contact <id> nhưng tạo deal thất bại"N/A
DisabledThiếu field bắt buộc / đang gửiNút tắt; "Còn thiếu: <…>"; khi gửi nút "Đang tạo…"N/A
Cảnh báoThiếu property khuyến nghị / cảnh báo flow / contact chuỗi sai vai tròDanh sách cảnh báo vàng (không chặn)N/A
Fields &ZeroWidthSpace;
FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
Chế độ dealYesTab "Tạo deal mới" / "Dùng deal có sẵn"Tạo deal mới———Flow có cho phép deal có sẵn—
Deal id (có sẵn)Yes (chế độ có sẵn)Text——Không trống (BR-01); không kiểm tồn tại (⚠️ Observed)"Còn thiếu: Deal id"Chế độ có sẵnChế độ deal
PipelineYesDropdown——BR-01, BR-07"Còn thiếu: Pipeline"Chế độ mớiFlow × portal
Deal stageYesDropdown— (đổi pipeline thì xoá)—BR-01"Còn thiếu: Deal stage"Chế độ mớiPipeline
Property bắt buộc của flowYesTheo property HubSpot (text / enum / date)Danh tính test (BR-06) hoặc từ kho id (phase 2)Theo HubSpotBR-01; enum có thể bị thu hẹp theo flow"Còn thiếu: <tên property>"Theo nhánh doi_tuong_mua_hang / nhóm có điều kiệnSpec flow (US-D04…)
Property khuyến nghịNoNhư trên——BR-02Cảnh báo mềmChế độ mớiSpec flow
Property tuỳ chọn (vd hubspot_owner_id — danh sách 3 owner cố định, OQ-D-12)NoNhư trên————Chế độ mớiSpec flow
Property bị loại—Chỉ hiện tên + lý do——Không gửi—Chế độ mớiSpec flow
Contact: chế độYes (nếu flow cần contact)Tạo mới / Dùng contact có sẵnTạo mới———Flow cần contact—
Contact: tênYes (tạo mới)TextDanh tính test—Không trống"Còn thiếu: Tên contact"Tạo mới—
Contact: họ, tên, email, SĐT, địa chỉ, tỉnh, ngày sinh, CCCD, lớp đăng kýNoTextDanh tính test———Tạo mới—
Contact id (có sẵn)Yes (dùng có sẵn)Multi-select từ danh sách contact tool đã tạo——≥ 1"Còn thiếu: Contact id"Dùng có sẵn—
Filter / Search / Sort &ZeroWidthSpace;

N/A — không phải màn List.

Actions &ZeroWidthSpace;
A1 - Tạo deal &ZeroWidthSpace;
ItemDescription
TriggerBấm "Tạo deal"
Behavior(1) Contact mới → tạo contact trên HubSpot (BE sao phone_number sang phone, cccd_passport sang cccd_ho_chieu), ghi vào danh sách contact tool đã tạo (Redis mind_keep). (2) Tạo deal trên HubSpot với pipeline, stage, property không trống (BR-03), gắn contact; BE lọc property (BR-04), sinh tên (BR-05), ghi vào danh sách deal tool đã tạo (Redis mind_keep). (3) Ghi lượt test (US-D02 BR-02). Hệ thống / môi trường: Dev → HubSpot dev portal; Staging → HubSpot prod portal. ⚠️ Ghi PROD: Staging ghi deal + contact vào portal HubSpot production (NFR-D-03); BE còn có route prod/sapp-26878/deals và …/contacts dù giao diện chặn Prod (NFR-P-01, NFR-D-02, OQ-D-02).
Success ResultHộp thành công "Đã tạo <nhãn deal>" — "Deal "<tên>" (id: <id>) đã được tạo trong portal <env>." + contact liên kết; bước xong

Error cases:

CaseExpected Handling
Tạo contact lỗi"Tạo contact thất bại", dừng, không tạo deal
Contact tạo được, deal lỗi"Đã tạo contact <id> nhưng tạo deal thất bại"
Property lạ400 13027 từ BE, hiện như lỗi tạo deal
A2 - Dùng deal có sẵn &ZeroWidthSpace;
ItemDescription
TriggerChế độ "Dùng deal có sẵn", nhập Deal id (và contact id nếu có), bấm "Tạo deal"
BehaviorKhông gọi API; ghi deal vào chuỗi ở chế độ "deal có sẵn", tên hiển thị "(deal có sẵn)". Không ghi dữ liệu ra hệ ngoài.
Success ResultBước xong; ⚠️ Observed: các bước còn lại của deal tự đánh dấu xong (US-D01 EC-M2.3)

Error cases:

CaseExpected Handling
Deal id trốngNút tắt, "Còn thiếu: Deal id"
Acceptance Criteria của màn M1 &ZeroWidthSpace;
AC-M1.1 - Tạo deal hợp lệ &ZeroWidthSpace;
gherkin
Given flow "US-03 · Học phí thường" trên Dev, đã chọn pipeline, stage và điền đủ property bắt buộc, contact mới có tên
When người dùng bấm "Tạo deal"
Then tool tạo contact rồi deal trên HubSpot dev portal, chỉ gửi ô có giá trị cùng pipeline và dealstage
And tên deal có dạng "[IT TEST][SAPP-26878] <nhãn flow> <n>"
And hiện khung "Đã tạo xong data cho bước 1" với deal id

Maps to:

  • Business Rule: BR-01, BR-03, BR-05
  • Field/Action: A1 - Tạo deal
AC-M1.2 - Cảnh báo mềm không chặn &ZeroWidthSpace;
gherkin
Given property khuyến nghị "ngay_ghi_nhan_doanh_thu" để trống
When người dùng xem form
Then hiện cảnh báo tương ứng của flow
And nút "Tạo deal" vẫn bấm được nếu các field bắt buộc đã đủ

Maps to:

  • Business Rule: BR-02
AC-M1.3 - Thiếu field bắt buộc &ZeroWidthSpace;
gherkin
Given chưa chọn pipeline và chưa điền "doi_tuong_mua_hang"
When người dùng nhìn nút "Tạo deal"
Then nút tắt và dưới nút hiện "Còn thiếu: Pipeline, Deal stage, doi_tuong_mua_hang, …"

Maps to:

  • Business Rule: BR-01
AC-M1.4 - Danh tính test không đè ô đã sửa &ZeroWidthSpace;
gherkin
Given tool đã điền sẵn SĐT, CCCD, email, tên từ danh tính test
When người dùng sửa ô email
Then các lần điền lại sau đó không ghi đè email đã sửa

Maps to:

  • Business Rule: BR-06
Negative AC / Edge Cases của màn M1 &ZeroWidthSpace;
IDTình huốngHành vi mong đợi
EC-M1.1Bấm "Tạo deal" hai lầnNút tắt khi đang gửi ("Đang tạo…")
EC-M1.2Gửi property ngoài danh sách cho phépBE trả 400 13027 (BR-04)
EC-M1.3Portal không có pipeline cho flowCảnh báo "Chưa cấu hình pipeline…" (BR-07), không tạo được deal
EC-M1.4⚠️ Observed: "Dùng deal có sẵn" với id không tồn tại / không do tool tạoHành vi hiện tại: tool chấp nhận id, không kiểm; các bước sau gọi BE sẽ bị 13033 (BR-08). Cố ý? → OQ-D-06
EC-M1.5⚠️ Observed: tạo contact mới với email đã cóHành vi hiện tại: HubSpot trả contact cũ; tool cập nhật contact đó theo form rồi gắn vào deal, hiện hộp "Dùng lại contact đã có" (property form không set giữ giá trị cũ) (sapp-26878-step1.tsx:547-560). Trên Staging = contact trên portal prod → OQ-D-16
EC-M1.6Flow chuỗi: hai mắt xích cùng vai trò gán hai contact khác nhau, hoặc khác vai trò gán cùng contactCảnh báo "… phải là CÙNG một học viên" / "… phải là HAI học viên khác nhau" (không chặn) (sapp-26878-tool.tsx:1764-1800)

Màn M2 - Khối guide — bước hướng dẫn làm tay &ZeroWidthSpace;

FieldValue
Figma frameN/A
Trigger vào mànMở bước loại guide (vd "Đơn hàng Ops", "Giao dịch trong đơn")
Mô tả ngắnGợi ý "Bước này chỉ hướng dẫn: việc thao tác nằm ngoài tool, trên SAPP OPS." Hiện đoạn hướng dẫn, checklist, quy tắc, deal id cần mang theo, công thức đơn (flow chuỗi), panel SQL (nếu có).
UI States &ZeroWidthSpace;
StateKhi nàoHiển thịFigma frame
DefaultVừa mởNội dung hướng dẫn + nút "Đã hiểu" (hoặc nhãn riêng)N/A
Loading / Empty / Error—N/A — không gọi APIN/A
Has dataĐã xác nhận"Đã xác nhận — bước sau đã mở." / "Đã xác nhận — hết luồng."N/A
Disabled—N/AN/A
Fields &ZeroWidthSpace;
FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
Deal id tham chiếu—Id sao chép được (readonly)Từ chuỗi deal———Khi bước khai deal tham chiếuDeal đã tạo
Công thức đơn (order-cong / order-tru / order-in / order-out)—Text readonly có deal id thật————Flow chuỗiDeal đã tạo
Filter / Search / Sort &ZeroWidthSpace;

N/A — không phải màn List.

Actions &ZeroWidthSpace;
A1 - Đã hiểu &ZeroWidthSpace;
ItemDescription
TriggerBấm "Đã hiểu"
BehaviorĐánh dấu bước xong (BR-09). Không ghi dữ liệu ra hệ ngoài — thao tác Ops do người dùng tự làm trên SAPP OPS (môi trường tương ứng).
Success ResultBước xong

Error cases:

CaseExpected Handling
—Không có lỗi (không gọi API)
Acceptance Criteria của màn M2 &ZeroWidthSpace;
AC-M2.1 - Xác nhận hướng dẫn &ZeroWidthSpace;
gherkin
Given bước "Đơn hàng Ops" của US-03 đang mở
When người dùng bấm "Đã hiểu"
Then bước được tính là xong mà không có lời gọi API nào
And hiện "Đã xác nhận — bước sau đã mở."

Maps to:

  • Business Rule: BR-09
Negative AC / Edge Cases của màn M2 &ZeroWidthSpace;
IDTình huốngHành vi mong đợi
EC-M2.1Bấm "Đã hiểu" mà chưa làm trên OpsTool không kiểm được; bước sau có thể hỏng ở phía hệ ngoài
EC-M2.2Công thức đơn khi chưa đủ dealDeal id còn thiếu hiện trống trong công thức

Màn M3 - Khối stage — "Chuyển deal stage" / "Kéo sang Won" / "Hoàn thiện hồ sơ" &ZeroWidthSpace;

FieldValue
Figma frameN/A
Trigger vào mànMở bước loại stage
Mô tả ngắnGợi ý "Vẫn là deal của bước 1. Tool chỉ ghi dealstage, không sửa property nào khác." Hiện deal của bước, stage hiện tại (nút đọc lại từ HubSpot), dropdown stage của pipeline với stage gợi ý chọn sẵn, lý do nghiệp vụ của stage.
UI States &ZeroWidthSpace;
StateKhi nàoHiển thịFigma frame
DefaultVừa mởDeal id, stage hiện tại, dropdown stage (gợi ý chọn sẵn), nút "Chuyển stage"N/A
LoadingĐọc deal / pipeline"Đang tải pipeline…"N/A
Has dataĐã chuyểnHộp "Đã chuyển stage — <tên bước>"; "Đã chuyển — bước sau đã mở."N/A
EmptyPipeline không có stage"Không có stage để chọn"N/A
ErrorĐọc / ghi lỗi"Không đọc được stage hiện tại của deal" / "Không tải được danh sách pipeline" / "Không chuyển được deal stage"N/A
DisabledĐang gửiNút "Đang chuyển…"N/A
Fields &ZeroWidthSpace;
FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
Deal của bước này—Id readonlyDeal của khối———AlwaysChuỗi deal
Stage đíchYesDropdown stage của pipelineStage khớp nhãn gợi ý (BR-11)———AlwaysPipeline của deal
Filter / Search / Sort &ZeroWidthSpace;

N/A — không phải màn List.

Actions &ZeroWidthSpace;
A1 - Chuyển stage &ZeroWidthSpace;
ItemDescription
TriggerBấm "Chuyển stage"
BehaviorBE kiểm deal do tool tạo (BR-08), ghi dealstage trên HubSpot (BR-10). Kéo sang stage Won là mốc hệ ngoài bắn event SAP (REL-08). Dev → HubSpot dev portal; Staging → prod portal. ⚠️ Ghi PROD: Staging chuyển stage deal trên portal HubSpot production (NFR-D-03); BE có route prod/…/stage (NFR-P-01, NFR-D-02, OQ-D-02).
Success ResultDeal ở stage mới; bước xong

Error cases:

CaseExpected Handling
Deal không do tool tạo400 13033 → "Không chuyển được deal stage"
HubSpot lỗi"Không chuyển được deal stage"
Acceptance Criteria của màn M3 &ZeroWidthSpace;
AC-M3.1 - Chuyển stage chỉ ghi dealstage &ZeroWidthSpace;
gherkin
Given deal của bước ở stage "Thông tin hợp đồng"
When người dùng chọn "Soạn thảo hợp đồng" và bấm "Chuyển stage"
Then HubSpot deal có dealstage mới và không property nào khác bị sửa

Maps to:

  • Business Rule: BR-10
AC-M3.2 - Stage gợi ý theo nhãn &ZeroWidthSpace;
gherkin
Given pipeline có stage nhãn "Won - Hoàn tất thủ tục " (thừa khoảng trắng)
When mở bước "Kéo sang Won" có nhãn gợi ý "Won - Hoàn tất thủ tục"
Then dropdown chọn sẵn stage đó

Maps to:

  • Business Rule: BR-11
AC-M3.3 - Từ chối deal không do tool tạo &ZeroWidthSpace;
gherkin
Given deal id trong bước là deal có sẵn không nằm trong danh sách deal tool đã tạo trên portal đó
When người dùng bấm "Chuyển stage"
Then BE trả 400 mã 13033 "Deal was not created by the SAPP-26878 tool" và tool hiện "Không chuyển được deal stage"

Maps to:

  • Business Rule: BR-08
Negative AC / Edge Cases của màn M3 &ZeroWidthSpace;
IDTình huốngHành vi mong đợi
EC-M3.1Không có stage nào khớp nhãn gợi ýDropdown không chọn sẵn; người dùng chọn tay
EC-M3.2Deal đã bị người khác kéo stageStage hiện tại đọc lại được bằng nút đọc lại

Màn M4 - Khối sync — "Sync gói khóa học" &ZeroWidthSpace;

FieldValue
Figma frameN/A
Trigger vào mànMở bước loại sync (chỉ Deal gốc của US-11)
Mô tả ngắnHiện property đích goi_khoa_hoc, 6 property nguồn, lý do; nút "Đồng bộ gói khóa học" (đã chạy → "Đồng bộ lại"); sau khi chạy hiện giá trị trước / giá trị ghi / số giá trị thêm.
UI States &ZeroWidthSpace;
StateKhi nàoHiển thịFigma frame
DefaultVừa mởNút "Đồng bộ gói khóa học"N/A
LoadingĐang gọi"Đang đồng bộ…"N/A
Has dataĐã chạyGiá trị trước / ghi; "Đã đồng bộ — bước sau đã mở."N/A
EmptyKhông có giá trị mới"Không có giá trị mới nào để thêm." / "Chưa có giá trị nào trước đó."N/A
ErrorLỗi"Không đồng bộ được goi_khoa_hoc"N/A
DisabledĐang gọiNút tắtN/A
Fields &ZeroWidthSpace;

N/A — không có ô nhập; deal lấy từ chuỗi.

Filter / Search / Sort &ZeroWidthSpace;

N/A — không phải màn List.

Actions &ZeroWidthSpace;
A1 - Đồng bộ gói khóa học &ZeroWidthSpace;
ItemDescription
TriggerBấm "Đồng bộ gói khóa học"
BehaviorBE kiểm deal (BR-08), tính giá trị theo BR-12 và ghi goi_khoa_hoc lên deal HubSpot (Dev → dev portal; Staging → prod portal). ⚠️ Ghi PROD: Staging ghi lên portal production (NFR-D-03); BE có route prod/…/sync-course-package (NFR-D-02, OQ-D-02).
Success Resultgoi_khoa_hoc đã gộp giá trị; bước xong

Error cases:

CaseExpected Handling
Deal không do tool tạo / HubSpot lỗi"Không đồng bộ được goi_khoa_hoc"
Acceptance Criteria của màn M4 &ZeroWidthSpace;
AC-M4.1 - Gộp giá trị hợp lệ &ZeroWidthSpace;
gherkin
Given Deal gốc có property lộ trình chứa "A;B" và goi_khoa_hoc đang là "A"; "B" là option không ẩn của goi_khoa_hoc
When người dùng bấm "Đồng bộ gói khóa học"
Then goi_khoa_hoc = "A;B" và bước xong

Maps to:

  • Business Rule: BR-12
Negative AC / Edge Cases của màn M4 &ZeroWidthSpace;
IDTình huốngHành vi mong đợi
EC-M4.1Không có giá trị mới (hoặc giá trị không nằm trong option không ẩn)Không ghi; hiện "Không có giá trị mới nào để thêm."
EC-M4.2Chạy trước khi Ops sync đơnProperty nguồn chưa có → không có gì để ghi
FieldValue
Figma frameN/A
Trigger vào mànMở bước loại link (Deal trừ của US-11 / US-13)
Mô tả ngắnHiện deal được ghi, deal nguồn, property đích deal_id_goc_cua_chuyen_doi, lý do; nút "Gắn deal gốc" (đã chạy → "Gắn lại").
UI States &ZeroWidthSpace;
StateKhi nàoHiển thịFigma frame
DefaultVừa mởNút "Gắn deal gốc"N/A
LoadingĐang gọi"Đang gắn…"N/A
Has dataĐã gắn"Property đang trống, đã ghi giá trị mới." hoặc "Property đã có đúng id này từ trước — không ghi lại."; "Đã gắn — bước sau đã mở."N/A
Empty—N/AN/A
ErrorLỗi"Không gắn được deal_id_goc_cua_chuyen_doi"N/A
DisabledChưa đủ 2 deal / đang gọiNút tắtN/A
Fields &ZeroWidthSpace;

N/A — không có ô nhập; hai deal id lấy từ chuỗi.

Filter / Search / Sort &ZeroWidthSpace;

N/A — không phải màn List.

Actions &ZeroWidthSpace;
A1 - Gắn deal gốc &ZeroWidthSpace;
ItemDescription
TriggerBấm "Gắn deal gốc"
BehaviorBE kiểm deal (BR-08), ghi id Deal gốc vào deal_id_goc_cua_chuyen_doi của Deal trừ trên HubSpot, bỏ qua nếu đã đúng (BR-13). ⚠️ Ghi PROD: Staging ghi lên portal production (NFR-D-03); BE có route prod/…/link-source-deal (NFR-D-02, OQ-D-02).
Success ResultProperty có id Deal gốc; bước xong

Error cases:

CaseExpected Handling
Deal không do tool tạo / HubSpot lỗi"Không gắn được deal_id_goc_cua_chuyen_doi"
Acceptance Criteria của màn M5 &ZeroWidthSpace;
AC-M5.1 - Gắn lần đầu &ZeroWidthSpace;
gherkin
Given Deal trừ chưa có deal_id_goc_cua_chuyen_doi
When người dùng bấm "Gắn deal gốc"
Then property = id Deal gốc và hiện "Property đang trống, đã ghi giá trị mới."

Maps to:

  • Business Rule: BR-13
AC-M5.2 - Không ghi lại khi đã đúng &ZeroWidthSpace;
gherkin
Given Deal trừ đã có đúng id Deal gốc
When người dùng bấm "Gắn lại"
Then BE không ghi và hiện "Property đã có đúng id này từ trước — không ghi lại."

Maps to:

  • Business Rule: BR-13
Negative AC / Edge Cases của màn M5 &ZeroWidthSpace;
IDTình huốngHành vi mong đợi
EC-M5.1Chưa có Deal gốc trong chuỗiKhông gắn được (thiếu deal nguồn)
EC-M5.2Property đang chứa id khácGhi đè bằng id Deal gốc hiện tại

Màn M6 - Khối resync — "Đồng bộ lại hóa đơn / reconcile" &ZeroWidthSpace;

FieldValue
Figma frameN/A
Trigger vào mànMở bước loại resync (bước cuối mỗi flow phase 1)
Mô tả ngắnHiện property đích, giải thích, các lưu ý payload (caveat) của story, nút "Đồng bộ lại" (đã bấm → "Đồng bộ lại lần nữa"), giá trị trước đó và số lần bấm trong phiên.
UI States &ZeroWidthSpace;
StateKhi nàoHiển thịFigma frame
DefaultVừa mởHint + caveat + nút "Đồng bộ lại"N/A
LoadingĐang gọi"Đang đặt…"N/A
Has dataĐã bấm"Giá trị trước đó: <giá trị> / — trống —" · "đã bấm <n> lần trong phiên này"; ghi chú mỗi lần bấm là một sự kiện SAP mới; "Đã bắn — bước sau đã mở." / "Đã bắn — hết luồng. Theo dõi callback để thấy property quay về SUCCESS/FAILED."N/A
EmptyGiá trị trước đó trốngCảnh báo "chưa từng qua SAP" của flow (BR-14)N/A
ErrorLỗi"Không đặt được <property>"N/A
DisabledĐang gọiNút tắtN/A
Fields &ZeroWidthSpace;

N/A — không có ô nhập; deal và loại lấy từ spec bước (BR-15).

Filter / Search / Sort &ZeroWidthSpace;

N/A — không phải màn List.

Actions &ZeroWidthSpace;
A1 - Đồng bộ lại &ZeroWidthSpace;
ItemDescription
TriggerBấm "Đồng bộ lại"
BehaviorBE kiểm deal (BR-08), đọc giá trị cũ, ghi Đồng bộ lại vào property đích trên HubSpot (BR-14); hệ ngoài chạy lại SAP rồi ghi SUCCESS / FAILED về property (REL-08). Ghi thêm một lượt vào bucket story trên Redis mind_keep (US-D02 BR-06). ⚠️ Ghi PROD: Staging ghi lên portal production (NFR-D-03); BE có route prod/…/resync (NFR-D-02, OQ-D-02).
Success ResultProperty = Đồng bộ lại; bước xong

Error cases:

CaseExpected Handling
Deal không do tool tạo / HubSpot lỗi"Không đặt được <property>"
Acceptance Criteria của màn M6 &ZeroWidthSpace;
AC-M6.1 - Ghi vô điều kiện, trả giá trị cũ &ZeroWidthSpace;
gherkin
Given deal đã kéo Won, trang_thai_dong_bo_hoa_don = "SUCCESS"
When người dùng bấm "Đồng bộ lại" ở bước hóa đơn
Then property = "Đồng bộ lại" và hiện "Giá trị trước đó: SUCCESS"

Maps to:

  • Business Rule: BR-14
AC-M6.2 - Cảnh báo sau khi ghi nếu chưa từng qua SAP &ZeroWidthSpace;
gherkin
Given property đích đang trống
When người dùng bấm "Đồng bộ lại"
Then tool vẫn ghi "Đồng bộ lại"
And sau đó hiện cảnh báo "Property này đang trống — deal chưa từng qua SAP…"

Maps to:

  • Business Rule: BR-14
AC-M6.3 - Đúng deal và đúng loại &ZeroWidthSpace;
gherkin
Given flow "US-11 · Chuyển đổi"
When người dùng tới bước "Đồng bộ lại hóa đơn"
Then bước ghim vào Deal cộng và chỉ đồng bộ lại hóa đơn (không có reconcile)

Maps to:

  • Business Rule: BR-15
Negative AC / Edge Cases của màn M6 &ZeroWidthSpace;
IDTình huốngHành vi mong đợi
EC-M6.1Bấm nhiều lầnMỗi lần ghi lại Đồng bộ lại; bộ đếm lần bấm tăng
EC-M6.2Ghi lượt vào bucket story lỗiKhông báo lỗi (US-D02 BR-03)

Màn M7 - Khối ops — gọi một thao tác SAPP Ops &ZeroWidthSpace;

FieldValue
Figma frameN/A
Trigger vào mànMở bước loại ops (phase 2: kiểm tra kết nối, đếm lớp, tạo lớp, tạo buổi học, gán phòng, mở lớp, tạo đơn, tạo / xác nhận giao dịch, đọc học viên, chuyển nhượng, tạo giáo viên, dời / huỷ / xoá buổi, gửi lại bút toán…)
Mô tả ngắnForm field theo spec thao tác: điền sẵn từ kho id của phiên, dropdown danh mục theo portal, template giá trị; nút chạy; panel "Phản hồi đầy đủ". Cơ chế gọi Ops → US-P08.
UI States &ZeroWidthSpace;
StateKhi nàoHiển thịFigma frame
DefaultVừa mởForm field (có giá trị điền sẵn)N/A
LoadingTải danh mục / đang gọiSpinnerN/A
Has dataGọi xongTóm tắt id thu được + "Phản hồi đầy đủ"; bước xongN/A
EmptyDanh mục rỗngDropdown trốngN/A
ErrorOps lỗi / đơn 0đ / danh mục 501Thông báo lỗi; bước không xongN/A
DisabledĐang gọiNút tắtN/A
Fields &ZeroWidthSpace;
FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
Field của thao tác (vd class_id, product_ids, amount…)Theo specText / dropdown danh mục / readonlyTừ kho id, danh mục, templateTheo specTrống thì bỏ khỏi payload (BR-16)Lỗi Ops trả vềTheo specKho id của phiên, portal
Filter / Search / Sort &ZeroWidthSpace;

N/A — không phải màn List.

Actions &ZeroWidthSpace;
A1 - Chạy thao tác Ops &ZeroWidthSpace;
ItemDescription
TriggerBấm nút chạy của bước
BehaviorGọi route sapp-ops/* tương ứng của portal (Dev → Ops dev, Staging → Ops staging) qua passthrough; lưu giá trị response vào kho id (BR-16); đơn 0đ → dừng (BR-17). ⚠️ Ghi PROD: giao diện chặn Prod, nhưng BE có route ghi prod cho các thao tác này (vd POST prod/sapp-ops/classes, …/product-orders, …/confirm) (NFR-P-01, NFR-D-02, OQ-D-02).
Success ResultId mới trong kho id; bước xong

Error cases:

CaseExpected Handling
Đơn hàng ra 0đ"Đơn hàng tạo ra có số tiền bằng 0" + giải thích; bước không xong
Ops trả lỗiHiện lỗi; bước không xong
Acceptance Criteria của màn M7 &ZeroWidthSpace;
AC-M7.1 - Bỏ ô trống, thu id &ZeroWidthSpace;
gherkin
Given bước "Tạo lớp" có ô tuỳ chọn để trống và ô "link_meeting" (cho phép trống) để trống
When người dùng chạy bước
Then payload không có ô tuỳ chọn trống nhưng có "link_meeting" rỗng
And class_id trong response được lưu vào kho id cho bước sau

Maps to:

  • Business Rule: BR-16
AC-M7.2 - Chặn đơn 0 đồng &ZeroWidthSpace;
gherkin
Given sản phẩm chọn không có giá
When người dùng chạy "Tạo đơn hàng" và Ops trả đơn có số tiền 0
Then tool báo "Đơn hàng tạo ra có số tiền bằng 0" và bước không được tính là xong

Maps to:

  • Business Rule: BR-17
AC-M7.3 - Số tiền giao dịch theo đơn &ZeroWidthSpace;
gherkin
Given kho id có order_amount = 5000000
When người dùng mở bước "Tạo giao dịch"
Then ô amount = 5000000 (readonly)

Maps to:

  • Business Rule: BR-18
Negative AC / Edge Cases của màn M7 &ZeroWidthSpace;
IDTình huốngHành vi mong đợi
EC-M7.1Kho id thiếu giá trị (bước trước bị bỏ qua không nhập)Ô điền sẵn trống; Ops có thể từ chối
EC-M7.2Portal không có danh mụcBE trả 501 (BR-19)
EC-M7.3Hết phiên đăng nhập OpsPassthrough tự đăng nhập lại và thử lại một lần (US-P08)

Màn M8 - Khối option — "Thêm option mã lớp" &ZeroWidthSpace;

FieldValue
Figma frameN/A
Trigger vào mànMở bước loại option (phase 2)
Mô tả ngắnThêm mã lớp (từ kho id) vào danh sách option của 3 property: lop_dang_ky_cloned_ (deal), lop_dang_ky (deal), lop_dang_ky (contact). Cơ chế → US-P07.
UI States &ZeroWidthSpace;
StateKhi nàoHiển thịFigma frame
DefaultDev, có mã lớpNút chạyN/A
LoadingĐang gọi"Đang gọi HubSpot…"N/A
Has dataĐã chạyMỗi property: "Đã thêm option mới" / "Option đã có sẵn — không tạo thêm bản thứ hai"; "Xong — bước sau đã mở."N/A
EmptyChưa có mã lớpNút tắtN/A
ErrorMột property lỗi"Không thêm được option vào <property>"; bước chưa xongN/A
DisabledStaging / ProdNút tắt; Staging giải thích phải làm tay rồi bỏ quaN/A
Fields &ZeroWidthSpace;
FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
Mã lớpYesReadonlyTừ kho id (class_code)—Không trốngNút tắtAlwaysBước tạo lớp
Filter / Search / Sort &ZeroWidthSpace;

N/A — không phải màn List.

Actions &ZeroWidthSpace;
A1 - Thêm option &ZeroWidthSpace;
ItemDescription
TriggerBấm chạy (chỉ Dev)
BehaviorGọi tuần tự 3 lần route thêm option của HubSpot dev (BR-20). Ghi vào định nghĩa property HubSpot dev portal. Staging/Prod không gọi.
Success Result3 property có option; bước xong

Error cases:

CaseExpected Handling
1 trong 3 property lỗiBáo lỗi property đó; bước chưa xong
Acceptance Criteria của màn M8 &ZeroWidthSpace;
AC-M8.1 - Chỉ chạy ở Dev &ZeroWidthSpace;
gherkin
Given portal Staging
When người dùng mở bước "Thêm option mã lớp"
Then nút chạy tắt và tool hướng dẫn làm tay trên portal rồi dùng "Bỏ qua bước này"

Maps to:

  • Business Rule: BR-20
AC-M8.2 - Xong khi đủ 3 property &ZeroWidthSpace;
gherkin
Given portal Dev, mã lớp "ABC03.5"
When người dùng chạy và cả 3 property thêm được option
Then bước xong
But nếu một property lỗi thì bước chưa xong

Maps to:

  • Business Rule: BR-20
Negative AC / Edge Cases của màn M8 &ZeroWidthSpace;
IDTình huốngHành vi mong đợi
EC-M8.1Option đã có"Option đã có sẵn — không tạo thêm bản thứ hai", vẫn tính là có
EC-M8.2Chạy lạiNhãn nút "Chạy lại"; không tạo trùng option

Màn M9 - Khối classcode — "Gán mã lớp" &ZeroWidthSpace;

FieldValue
Figma frameN/A
Trigger vào mànMở bước loại classcode (phase 2)
Mô tả ngắnGhi mã lớp lên lop_dang_ky_cloned_ + lop_dang_ky của Deal và lop_dang_ky của Contact; nút "Gán mã lớp vào Deal & Contact" (đã chạy → "Ghi lại").
UI States &ZeroWidthSpace;
StateKhi nàoHiển thịFigma frame
DefaultVừa mởDeal id, contact id, mã lớp, nútN/A
LoadingĐang gọi"Đang ghi…"N/A
Has dataĐã ghiKết quả từng property (ghi mới / "đã có sẵn giá trị này, không ghi lại"); "Xong — bước sau đã mở."N/A
EmptyThiếu mã lớp / dealNút tắtN/A
ErrorLỗi"Không gán được mã lớp"N/A
DisabledĐang gọiNút tắtN/A
Fields &ZeroWidthSpace;
FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
Mã lớpYesReadonlyKho id class_code—Không trống—AlwaysBước tạo lớp
Contact idNoReadonlyContact của deal———AlwaysBước deal
Filter / Search / Sort &ZeroWidthSpace;

N/A — không phải màn List.

Actions &ZeroWidthSpace;
A1 - Gán mã lớp &ZeroWidthSpace;
ItemDescription
TriggerBấm "Gán mã lớp vào Deal & Contact"
BehaviorBE kiểm deal (BR-08), ghi mã lớp lên deal + contact trên HubSpot, bỏ qua property đã đúng (BR-13). ⚠️ Ghi PROD: Staging ghi lên portal production (NFR-D-03); BE có route prod/…/assign-class-code (NFR-D-02, OQ-D-02). Route này chưa có trong API doc (DR-D-04).
Success ResultDeal + contact mang mã lớp; bước xong

Error cases:

CaseExpected Handling
Deal không do tool tạo / HubSpot lỗi"Không gán được mã lớp"
Acceptance Criteria của màn M9 &ZeroWidthSpace;
AC-M9.1 - Gán lên deal và contact &ZeroWidthSpace;
gherkin
Given deal và contact chưa có mã lớp
When người dùng bấm "Gán mã lớp vào Deal & Contact"
Then lop_dang_ky_cloned_ và lop_dang_ky của deal, lop_dang_ky của contact = mã lớp

Maps to:

  • Business Rule: BR-13
AC-M9.2 - Không ghi lại giá trị đã đúng &ZeroWidthSpace;
gherkin
Given contact đã có đúng mã lớp
When người dùng bấm "Ghi lại"
Then property của contact hiện "đã có sẵn giá trị này, không ghi lại"

Maps to:

  • Business Rule: BR-13
Negative AC / Edge Cases của màn M9 &ZeroWidthSpace;
IDTình huốngHành vi mong đợi
EC-M9.1Mã lớp chưa có trong option propertyHubSpot có thể từ chối giá trị enum — cần bước M8 trước
EC-M9.2Không có contact idChỉ ghi phần deal (TODO: xác nhận bằng chạy thử)

Màn M10 - Khối scan — "Chạy lượt quét" &ZeroWidthSpace;

FieldValue
Figma frameN/A
Trigger vào mànMở bước loại scan (phase 2)
Mô tả ngắnBắn một lượt quét doanh thu ngay (bỏ điều kiện chỉ Thứ 7). Cơ chế và kết quả lượt quét → US-P05.
UI States &ZeroWidthSpace;
StateKhi nàoHiển thịFigma frame
DefaultDev / StagingNút "Chạy lượt quét ngay"N/A
LoadingĐang gọi"Đang bắn lượt quét…"N/A
Has dataĐược xếp hàngKết quả "queued"; "Xong — bước sau đã mở."N/A
EmptyTính năng quét đang tắtKết quả "disabled"; bước chưa xongN/A
ErrorLỗi"Không chạy được lượt quét"N/A
DisabledProd / đang gọiNút tắtN/A
Fields &ZeroWidthSpace;

N/A — không có ô nhập.

Filter / Search / Sort &ZeroWidthSpace;

N/A — không phải màn List.

Actions &ZeroWidthSpace;
A1 - Chạy lượt quét &ZeroWidthSpace;
ItemDescription
TriggerBấm "Chạy lượt quét ngay"
BehaviorGọi route quét thủ công của SAP service (lms-be) ở Dev / Staging (BR-21). Không có route Prod.
Success ResultLượt quét được xếp hàng; bước xong

Error cases:

CaseExpected Handling
Tính năng tắtKết quả "disabled", bước không mở bước sau
Hai lượt trong 1 giâySAP service trả 429; nút đã khoá khi đang gọi (NFR-D-08)
Acceptance Criteria của màn M10 &ZeroWidthSpace;
AC-M10.1 - Tắt ở Prod &ZeroWidthSpace;
gherkin
Given portal Prod (không xảy ra trong stepper, chỉ để minh hoạ điều kiện)
When khối scan hiển thị
Then nút "Chạy lượt quét ngay" tắt

Maps to:

  • Business Rule: BR-21
AC-M10.2 - Chỉ xếp hàng mới xong &ZeroWidthSpace;
gherkin
Given portal Dev
When người dùng bấm "Chạy lượt quét ngay" và SAP service trả triggered = false
Then bước không được tính là xong
When SAP service trả triggered = true
Then bước xong

Maps to:

  • Business Rule: BR-21
Negative AC / Edge Cases của màn M10 &ZeroWidthSpace;
IDTình huốngHành vi mong đợi
EC-M10.1"Đã xếp hàng" chưa phải "đã xong"Xem kết quả thật ở danh sách lượt quét (US-P05)
EC-M10.2⚠️ Observed: route quét là GET có tác dụng phụ→ OQ-D-09

Màn M11 - Khối trace — "Đọc kết quả" &ZeroWidthSpace;

FieldValue
Figma frameN/A
Trigger vào mànMở bước loại trace
Mô tả ngắnTiêu đề "<bước> — đọc kết quả"; mở màn tra log SAP của nền tảng, tự chạy với bộ lọc deal_id (mặc định) hoặc class_code từ kho id, kèm các check kịch bản. Cơ chế tra log → US-P05.
UI States &ZeroWidthSpace;
StateKhi nàoHiển thịFigma frame
DefaultVừa mởTự chạy tra log với bộ lọc; mã lớp sao chép được (nếu lọc theo lớp)N/A
Loading / Has data / Empty / Error—Theo US-P05; mỗi check hiện pass / fail / unknownN/A
Disabled—N/A — bước luôn xongN/A
Fields &ZeroWidthSpace;
FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
Bộ lọc deal_id / class_code—Điền sẵnKho id———AlwaysSpec bước
Filter / Search / Sort &ZeroWidthSpace;

Theo US-P05 (bộ lọc điền sẵn như trên).

Actions &ZeroWidthSpace;
A1 - Tự đọc kết quả &ZeroWidthSpace;
ItemDescription
TriggerMở bước
BehaviorChỉ đọc log SAP ở portal hiện tại; chạy check (BR-22). Không ghi dữ liệu.
Success ResultLog + kết quả check; bước luôn tính là xong

Error cases:

CaseExpected Handling
Không đọc được field của checkCheck = "unknown"
Acceptance Criteria của màn M11 &ZeroWidthSpace;
AC-M11.1 - Không chặn bước sau &ZeroWidthSpace;
gherkin
Given bước "Đọc kết quả" có check đang fail
When người dùng nhìn rail bước
Then bước vẫn được tính là xong và bước sau (nếu có) mở được

Maps to:

  • Business Rule: BR-22
AC-M11.2 - Unknown khác fail &ZeroWidthSpace;
gherkin
Given log không có field mà check cần đọc
When check chạy
Then check hiện "unknown", không phải "fail"

Maps to:

  • Business Rule: BR-22
Negative AC / Edge Cases của màn M11 &ZeroWidthSpace;
IDTình huốngHành vi mong đợi
EC-M11.1Kho id chưa có deal_idTra log với bộ lọc rỗng
EC-M11.2Nghiệm thu dựa vào người đọc check (không có gate "phải xanh")→ OQ-D-15

Màn M12 - Khối sql — panel SQL gắn vào bước &ZeroWidthSpace;

FieldValue
Figma frameN/A
Trigger vào mànMở một bước có khai câu SQL (mọi loại bước)
Mô tả ngắnHiện câu SQL đã thay id từ kho id, nút sao chép, nút "Chạy" (theo statement id). Cơ chế runner → US-P09.
UI States &ZeroWidthSpace;
StateKhi nàoHiển thịFigma frame
DefaultVừa mởCâu SQL; câu ghi tô đỏN/A
LoadingKiểm trạng thái runner / đang chạySpinnerN/A
Has dataChạy xongKết quả trả vềN/A
EmptyRunner chưa cấu hình cho môi trườngTrạng thái "chưa cấu hình" (phân biệt với chưa đăng nhập)N/A
ErrorChạy lỗiLỗi hiện inline (câu tự chạy không bật hộp lỗi)N/A
DisabledProd / runner chưa sẵn sàng / còn token {…} chưa thayNút "Chạy" tắtN/A
Fields &ZeroWidthSpace;
FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
Tham số câu SQLYesThay tự độngKho id{tên}Mọi token phải có giá trịNút tắtAlwaysKho id
Filter / Search / Sort &ZeroWidthSpace;

N/A — không phải màn List.

Actions &ZeroWidthSpace;
A1 - Chạy câu SQL &ZeroWidthSpace;
ItemDescription
TriggerBấm "Chạy" (câu đọc có thể tự chạy khi mở bước)
BehaviorCâu ghi → hộp xác nhận trước (BR-23). Gửi statement id + tham số tới SQL runner; chạy trên SAPP Ops DB Dev / Staging. Không có route Prod. Câu ghi (backdate buổi, seed mốc, ép dòng FAILED, trả mã lớp…) sửa dữ liệu Ops DB staging/dev không có undo.
Success ResultKết quả câu SQL; gate bước không đổi

Error cases:

CaseExpected Handling
Huỷ hộp xác nhậnKhông gọi API
Runner lỗiLỗi inline
Acceptance Criteria của màn M12 &ZeroWidthSpace;
AC-M12.1 - Câu ghi phải xác nhận &ZeroWidthSpace;
gherkin
Given panel có câu ghi
When người dùng bấm "Chạy"
Then hiện hộp "Chạy câu GHI này trên STAGING? … Không có undo."
And huỷ thì không có lời gọi nào

Maps to:

  • Business Rule: BR-23
AC-M12.2 - Câu đọc tự chạy, không chặn bước &ZeroWidthSpace;
gherkin
Given bước có câu đọc khai tự chạy
When người dùng mở bước
Then câu đọc tự chạy; nếu lỗi thì chỉ hiện inline, không bật hộp lỗi và không chặn bước

Maps to:

  • Business Rule: BR-23
Negative AC / Edge Cases của màn M12 &ZeroWidthSpace;
IDTình huốngHành vi mong đợi
EC-M12.1Portal ProdKhông có route; nút tắt
EC-M12.2Còn token chưa thayNút tắt
EC-M12.3⚠️ Observed: id câu SQL phía FE không khớp id phía BENút "Chạy" có thể tắt âm thầm → OQ-D-14

5. Cross-feature AC &ZeroWidthSpace;

AC-X.1 - Bước ops đi qua passthrough nền tảng &ZeroWidthSpace;

gherkin
Given bước ops trên Staging
When người dùng chạy bước
Then lời gọi đi qua Ops passthrough, tự đăng nhập Ops staging (US-P08) theo cấu hình env_systems (US-P04)

Maps to:

  • REL-06 (Affects - Ops passthrough + auto-login)
  • REL-02 (Affects - Cấu hình env_systems)

AC-X.2 - Panel SQL dùng runner nền tảng &ZeroWidthSpace;

gherkin
Given panel SQL trên Dev
When người dùng chạy một câu
Then runner nền tảng thực thi theo statement id (US-P09), cùng runner với sub-tool 26297

Maps to:

  • REL-07 (Affects - Ops SQL runner)
  • REL-09 (Affects - Sub-tool 26297)

AC-X.3 - Option, scan, trace dùng dịch vụ nền tảng &ZeroWidthSpace;

gherkin
Given bước option / scan / trace
When bước chạy
Then hành vi gọi dịch vụ theo US-P07 (option) và US-P05 (scan, trace)

Maps to:

  • REL-05 (Affects - Thêm option property HubSpot dev)
  • REL-03 (Affects - Tra log SAP + quét doanh thu)

AC-X.4 - Kéo Won / Đồng bộ lại kích hoạt SAP &ZeroWidthSpace;

gherkin
Given deal đủ điều kiện
When bước stage kéo sang stage Won hoặc bước resync ghi "Đồng bộ lại"
Then hệ ngoài (webhook HubSpot → lms-be → SAP) xử lý và ghi trạng thái về deal (Fact theo hint, ngoài phạm vi truy vết)

Maps to:

  • REL-08 (Be Affected - webhook HubSpot → lms-be → SAP)