Skip to content

US-I03: Tạo deal test theo 14 deal case và gắn contact ​

Thuộc FS: 00-overview.md — SAPP-24395 Contact / Deal instances & Bulk product creation 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 — suy từ code, chưa chạy thử.

FieldValue
US IDUS-I03
Role thực hiệnR1 - Người dùng tool (Assumption — OQ-I-16 về G-01)
PhaseAs-built (đã triển khai)
PriorityN/A — as-built
StatusDraft
NFR liên quanNFR-I-01, NFR-I-04, NFR-I-05, NFR-I-06, NFR-I-07 — xem Overview §5
OQ liên quanOQ-I-01, OQ-I-02, OQ-I-03, OQ-I-06, OQ-I-07, OQ-I-16, OQ-I-17, OQ-I-19 — xem Overview §6

Nguồn inventory: A-05, A-06, A-07. Ghi: HubSpot dev · HubSpot PROD (qua tab "Staging").

1. US Statement ​

text
As a Người dùng tool (Assumption — OQ-I-16)
I want chọn một trong 14 deal case, điền các trường của case, gắn các contact đã tạo và tạo deal trên HubSpot của môi trường đang chọn
So that [Assumption — OQ-I-01] tôi có deal đầu vào đúng pipeline / stage / thuộc tính của từng tình huống để kiểm thử luồng tự động ghi nhận doanh thu

2. Dependencies & Definition Of Ready ​

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

#Cần sẵn sàngAi cung cấpTrạng thái
D1Token HubSpot dev / prod trong env_systems (US-P04)Admin CMSN/A — runtime
D2Pipeline / dealstage ghi cứng (bảng §4.b) còn tồn tại trên portal tương ứngOwner HubSpotN/A — runtime (không kiểm được từ code)
D3Contact cần gắn đã có trong danh sách tool (US-I02)Người dùngN/A — tuỳ chọn

3. Business Rules ​

IDRuleÁp dụng ởĐã cover bởi (AC)Nguồn code (Mode B/C)
BR-01Deal được gắn với các contact đang tick ở mục 1 (US-I01); dòng tóm tắt hiện "Sẽ gán n contact: <ids>". Không tick contact nào vẫn tạo được deal — dòng tóm tắt hiện "Chưa chọn contact nào — deal sẽ được tạo mà không gán contact."M1 - A1AC-M1.1, AC-M1.2fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:363-381, :598-601; be/libs/modules/src/lib/hubspot/common.service.ts:542-557
BR-02Có đúng 14 deal case (bảng §4.b); mặc định chọn "Deal Lost". Case không thuộc danh sách → lỗi 13011 "Invalid SAPP-24395 deal case"M1 - field Deal caseAC-M1.1, AC-M1.7be/libs/constants/src/lib/sapp/sapp.constants.ts:274-289; be/apps/api/src/sapp/sapp.controller.ts:2034-2046; fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:100-136, :398
BR-03Tên deal do hệ thống đặt, người dùng không đặt được: [IT TEST][SAPP-24395] <nhãn case> <n>, với n = số deal tool đã tạo trong môi trường đó + 1 (đếm chung mọi case)M1 - A1AC-M1.1be/apps/api/src/sapp/sapp.controller.ts:2325-2327; be/libs/modules/src/lib/sapp/common.service.ts:1624-1634
BR-04Pipeline và dealstage (và ở staging / dev: loại phí dịch vụ) được hệ thống gắn cố định theo cặp (môi trường, case) theo bảng §4.b; người dùng không đổi được pipeline / dealstageM1 - A1AC-M1.3, AC-M1.4be/apps/api/src/sapp/sapp.controller.ts:1739-2032
BR-05"Tài khoản nhận phí dịch vụ": danh sách lựa chọn lấy từ HubSpot của môi trường; mặc định "ACCA - Kể từ 01/01/2026"; nếu giá trị đang chọn không có trong danh sách thì quay về mặc định, không có mặc định thì lấy lựa chọn đầu tiên. Màn luôn gửi giá trị này và nó thắng mọi giá trị khác của cùng thuộc tínhM1 - field Tài khoản nhận phí dịch vụAC-M1.5fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:95-98, :435-457, :517-523; be/libs/constants/src/lib/sapp/sapp.constants.ts:243-247; be/apps/api/src/sapp/sapp.controller.ts:2080-2083
BR-06CCCD / Hộ chiếu áp dụng cho mọi case, được ghi lên deal (thuộc tính "[TVTS] CCCD/Hộ chiếu"), chỉ gửi khi có giá trịM1 - field CCCD/Hộ chiếuAC-M1.1be/apps/api/src/sapp/sapp.controller.ts:2084-2086; fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:519, :684-697
BR-07Mỗi case có bộ trường riêng (bảng §4.b cột "Trường riêng trên màn"); chỉ các trường của case đang chọn và có giá trị mới được gửiM1 - trường riêngAC-M1.6fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:203-224, :487-516
BR-08Deal Lost: người dùng chọn một loại thanh toán — Học phí (tối đa 3 đợt: số tiền, ngày, phương thức) hoặc Phí dịch vụ (Loại phí dịch vụ + tối đa 2 đợt); chỉ gửi trường của loại đang chọn. 5 số tiền đợt (3 học phí + 2 phí DV) mặc định 0 nếu không nhậpM1 - Deal LostAC-M1.3fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:148-194, :501-516; be/apps/api/src/sapp/sapp.controller.ts:2068-2073; be/libs/constants/src/lib/sapp/sapp.constants.ts:253-259
BR-09Thứ tự ưu tiên khi ghép thuộc tính deal (thấp → cao): số tiền đợt mặc định 0 (Deal Lost) → loại phí dịch vụ cố định được phép ghi đè (chỉ Deal Lost) → trường người dùng gửi → giá trị cố định được bảo vệ (pipeline, dealstage, loại phí của case khác, tài khoản mặc định) → Tài khoản nhận phí dịch vụ đã chọn → CCCD/Hộ chiếuM1 - A1AC-M1.3, AC-M1.4be/apps/api/src/sapp/sapp.controller.ts:2048-2088; be/libs/constants/src/lib/sapp/sapp.constants.ts:261-267
BR-10Đổi deal case: xoá các trường riêng đã nhập và đưa Deal Lost về tab "Học phí"; CCCD và Tài khoản nhận phí được giữM1 - field Deal caseAC-M1.6fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:413-432
BR-11Tạo thành công: deal (id + tên) được thêm vào danh sách của môi trường; popup "Đã tạo deal instance" — "Deal "<tên>" (id: <id>) đã được tạo trong portal <env>."M1 - A1AC-M1.1be/libs/modules/src/lib/sapp/common.service.ts:1636-1650; fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:481-491
BR-12Môi trường ghi theo tab như US-I02 BR-05: Dev → HubSpot dev; Staging → HubSpot production (cố ý theo comment code); Prod → production (chỉ qua API)M1 - A1AC-M1.4be/libs/constants/src/lib/hubspot/hubspot.constants.ts:19-26; be/apps/api/src/sapp/sapp.controller.ts:1829-1831

Không phải BR (⚠️ Observed → OQ): prod không có loại phí dịch vụ cố định cho case nào, client ghi được cho mọi case (inventory R-14 → OQ-I-03); trường tự do không whitelist (R-12 → OQ-I-07); bộ đếm tên không khoá khi tạo đồng thời (R-09 → OQ-I-06); Staging ghi production (R-19 → OQ-I-02); chữ hướng dẫn Deal Lost lệch hành vi (OQ-I-19).

4. Design &ZeroWidthSpace;

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

text
[M1: mục "2. Tạo HubSpot deal instance theo case" (trong màn US-I01)]
  ↓ (tuỳ chọn) tick contact ở mục 1
  ↓ chọn case ở danh sách trái → trường của case hiện bên phải
  ↓ chọn Tài khoản nhận phí, nhập CCCD, nhập trường riêng (Deal Lost: chọn tab Học phí / Phí dịch vụ)
  ↓ bấm "Tạo deal"
  ├─ OK ─────────────→ popup "Đã tạo deal instance", "Deal đã tạo (n+1)"
  └─ lỗi ────────────→ popup "Tạo deal instance thất bại", ở lại M1

Link flow chi tiết: N/A.

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

Bảng 14 deal case (Fact từ code; ý nghĩa nghiệp vụ = Assumption) &ZeroWidthSpace;

Nguồn: nhãn be/libs/constants/src/lib/sapp/sapp.constants.ts:292-314; nhãn trên màn fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:100-136; cấu hình be/apps/api/src/sapp/sapp.controller.ts:1739-2032 (prod :1743-1828, staging :1832-1931, dev :1932-2031); trường riêng fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:203-224. Mọi case, mọi môi trường còn gắn "Tài khoản nhận phí dịch vụ" = "ACCA - Kể từ 01/01/2026" (bị thay bởi giá trị người dùng chọn — BR-05). Chú thích trong code: pipeline 877604025 = "Pipeline test UAT environment"; 882511134 = "IT test đóng tiền chuyển đổi học phí" (be/apps/api/src/sapp/sapp.controller.ts:1775, :1781). Pipeline dev không có chú thích tên.

#Case (mã đường dẫn)Nhãn trên mànNhãn trong tên dealProd & Staging: pipeline / dealstageDev: pipeline / dealstageLoại phí dịch vụ — Staging & DevLoại phí dịch vụ — ProdTrường riêng trên mànÝ nghĩa nghiệp vụ
1lostDeal LostDeal Lost877604025 / 1316240409836815496 / 1244260910Rỗng — người dùng ghi đè được (tab Phí dịch vụ)Không gửiTab Học phí (3 đợt) hoặc Phí dịch vụ (Loại phí DV + 2 đợt) — BR-08[Assumption] deal bị lost có các đợt đã đóng — OQ-I-01
2cbeDeal CBEDeal CBE877604025 / 1316240409836815496 / 1244260910Phí đăng ký thi CBEKhông gửiDeal ID đã thanh toán phí[Assumption] phí đăng ký thi CBE — OQ-I-01
3certDeal CERTDeal CERT877604025 / 1316240409836815496 / 1244260910Phí tài khoản CertKhông gửiDeal ID đã thanh toán phí[Assumption] phí tài khoản Cert — OQ-I-01
4beckerDeal BECKERDeal BECKER877604025 / 1316240409836815496 / 1244260910Phí tài khoản BeckerKhông gửiDeal ID đã thanh toán phí[Assumption] phí tài khoản Becker — OQ-I-01
5gia-hanDeal Gia hạnDeal Gia hạn877604025 / 1316240409836815496 / 1244260910Phí gia hạnKhông gửiDeal ID đã thanh toán phí[Assumption] phí gia hạn khoá học — OQ-I-01
6bao-luuDeal Bảo lưuDeal Bảo lưu877604025 / 1316240409836815496 / 1244260910Phí bảo lưuKhông gửiDeal ID đã thanh toán phí[Assumption] phí bảo lưu — OQ-I-01
7chuyen-doi-ghi-nhan-doanh-thuDeal Chuyển đổi - Ghi nhận doanh thuDeal Chuyển đổi - Ghi nhận doanh thu882511134 / 1325314701878176910 / 1317215384Chuyển đổiKhông gửiDeal ID bị lost; Deal ID đã thanh toán phí[Assumption] chuyển đổi có ghi nhận doanh thu — OQ-I-01
8chuyen-nhuong-hv-chuyen-nhuongDeal Chuyển nhượng - HV Chuyển nhượngDeal Chuyển nhượng - HV Chuyển nhượng877604025 / 1316240409878343020 / 1317287583Chuyển nhượngKhông gửiKhông có[Assumption] phía học viên chuyển nhượng — OQ-I-01
9chuyen-doi-khong-ghi-nhan-phiDeal Chuyển đổi - Không ghi nhận phíDeal Chuyển đổi - Không ghi nhận phí882511134 / 1325314701878176910 / 1317215384Không ghi nhận phíKhông gửiKhông có[Assumption] chuyển đổi không ghi nhận phí — OQ-I-01
10chuyen-nhuong-hv-nhan-chuyen-nhuongDeal Chuyển nhượng - HV Nhận Chuyển nhượngDeal Chuyển nhượng - HV Nhận Chuyển nhượng877604025 / 1316240409878343020 / 1317287583Không ghi nhận phíKhông gửiKhông có[Assumption] phía học viên nhận chuyển nhượng — OQ-I-01
11tu-van-khoa-hocDeal Tư vấn khóa họcDeal Tư vấn khóa học877604025 / 1316240409836815496 / 1244260910Tư vấn khóa họcKhông gửiDeal ID đã thanh toán phí[Assumption] phí tư vấn khoá học — OQ-I-01
12chuyen-doi-dieu-chinh-giam-originalOriginal Deal – Chuyển đổi điều chỉnh giảmOriginal Deal dành cho Chuyển đổi điều chỉnh giảm882511134 / 1325314701878176910 / 1317215384Chuyển đổiKhông gửiHọc phí gốc; Amount; Gói khoá học[Assumption] deal gốc trước khi chuyển đổi điều chỉnh giảm — OQ-I-01
13chuyen-nhuong-hv-nhan-chuyen-nhuong-truDeal trừ – Chuyển nhượng HV nhận chuyển nhượngDeal trừ dành cho Chuyển nhượng HV nhận chuyển nhượng877604025 / 1316240409878343020 / 1317287583Chuyển nhượngKhông gửiGói khoá học chuyển nhượng; Amount[Assumption] deal trừ cho học viên nhận chuyển nhượng — OQ-I-01
14chuyen-doi-tang-doanh-thu-deal-truDeal trừ – Chuyển đổi tăng doanh thuDeal trừ dành cho Deal Chuyển đổi ghi nhận doanh thu882511134 / 1325314701878176910 / 1317215384Chuyển đổiKhông gửiKhoá học đem chuyển đổi; Amount[Assumption] deal trừ cho chuyển đổi tăng doanh thu — OQ-I-01

Khác biệt tóm tắt (in đậm ở bảng):

  • 4 case "Chuyển đổi" (7, 9, 12, 14) dùng pipeline riêng ở prod/staging (882511134) và ở dev (878176910).
  • 3 case "Chuyển nhượng" (8, 10, 13) chỉ ở dev dùng pipeline riêng (878343020); ở prod/staging vẫn dùng pipeline chung 877604025.
  • Prod không gửi loại phí dịch vụ cho case nào (⚠️ Observed — OQ-I-03, DR-I-02, DR-I-04), trong khi staging (cùng portal production) có → cùng một case trên cùng portal cho ra deal khác nhau tuỳ gọi "prod" hay "staging".
  • Nhãn trên màn của case 12–14 ngắn hơn nhãn nằm trong tên deal.

Tên nội bộ HubSpot của trường riêng: Deal ID đã thanh toán phí = deal_id_da_thanh_toan_phi; Deal ID bị lost = deal_id_bi_lost; Học phí gốc = hoc_phi_goc; Amount = amount; Gói khoá học = goi_khoa_hoc; Gói khoá học chuyển nhượng = goi_khoa_hoc_chuyen_nhuong; Khoá học đem chuyển đổi = khoa_hoc_dem_chuyen_doi (nhãn hiển thị lấy từ định nghĩa property trên HubSpot — tên tiếng Việt ở trên là diễn giải từ tên nội bộ).

Màn M1 - Form "2. Tạo HubSpot deal instance theo case" &ZeroWidthSpace;

FieldValue
Figma frameN/A
Trigger vào mànMở màn Contact / Deal instances (US-I01), chọn tab môi trường
Mô tả ngắnTrái: danh sách 14 case (dọc, cuộn). Phải: Tài khoản nhận phí dịch vụ, CCCD/Hộ chiếu, trường riêng của case, nút "Tạo deal", dòng tóm tắt contact + tài khoản. Dưới: "Deal đã tạo (n)" + icon lịch sử (US-I01 M2). Mô tả: "Chọn case và (tùy chọn) các contact để gán vào deal. Contact được chọn ở mục 1 (<đã chọn>/<tổng>)."
UI States &ZeroWidthSpace;
StateKhi nàoHiển thịFigma frame
DefaultVừa vàoCase "Deal Lost" được chọn, tab "Học phí" với 3 đợt; Tài khoản nhận phí đang tảiN/A
LoadingĐang tải lựa chọn tài khoảnÔ chọn tài khoản khoá, placeholder "Đang tải…"N/A
Loading (tạo)Đang tạo dealNút "Đang tạo…"; danh sách case và các ô bị khoáN/A
Has dataTạo xongPopup thành công; số "Deal đã tạo" tăng 1; form không bị xoáN/A
EmptyKhông có lựa chọn tài khoản từ HubSpotÔ chọn khoá, placeholder "ACCA - Kể từ 01/01/2026 (mặc định)" — vẫn gửi giá trị mặc địnhN/A
ErrorTải tài khoản lỗi / tạo lỗiPopup "Không tải được danh sách tài khoản nhận phí" / "Tạo deal instance thất bại"N/A
DisabledĐang tạoNhư Loading (tạo)N/A
Fields &ZeroWidthSpace;
FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
Deal caseYesDanh sách chọn 1 (14 mục)Deal LostBảng trênBR-02"Invalid SAPP-24395 deal case (13011)" (chỉ khi gọi API sai)Always—
Tài khoản nhận phí dịch vụ (tai_khoan_nhan_phi_dich_vu)Yes (luôn gửi)Dropdown — lựa chọn từ HubSpotACCA - Kể từ 01/01/2026—BR-05"Không tải được danh sách tài khoản nhận phí"AlwaysTab môi trường
CCCD / Hộ chiếu (cccd_ho_chieu — deal)NoTheo định nghĩa HubSpotRỗng—BR-06—Always—
Trường riêng theo caseNoTheo định nghĩa HubSpotRỗng—BR-07Lỗi HubSpot → A1Theo case (bảng trên)Deal case
Deal Lost — Loại thanh toánYes (khi Deal Lost)Tab "Học phí" / "Phí dịch vụ"Học phí—BR-08—Chỉ Deal LostDeal case = lost
Deal Lost — Loại phí dịch vụ (loai_phi_dich_vu)NoTheo HubSpotRỗng—BR-08, BR-09—Chỉ tab Phí dịch vụLoại thanh toán
Deal Lost — Đợt i: Số tiền / Ngày / Phương thứcNoTheo HubSpotSố tiền: "0 (mặc định)"Học phí: so_tien_hoc_vien_thanh_toan_lan_i, ngay_thanh_toan_hoc_phi_lan_i, phuong_thuc_thanh_toan_lan_i (i=1..3). Phí DV: phi_dich_vu_dong_lan_i, ngay_thanh_toan_phi_dv_lan_1 / ngay_thanh_toan_phi_lan_2, phuong_thuc_thanh_toan_phi_lan_i (i=1..2)BR-08—Theo tabLoại thanh toán

Ghi chú trên màn Deal Lost: "Điền lần lượt từ đợt 1; các trường đều tùy chọn (số tiền bỏ trống mặc định là 0). Đổi tab sẽ xóa dữ liệu đã nhập ở tab trước." — phần sau lệch hành vi (OQ-I-19).

Filter / Search / Sort (chỉ màn List/Report — xóa nếu không phải) &ZeroWidthSpace;

N/A — màn form. Danh sách case cố định 14 mục, không lọc.

Actions &ZeroWidthSpace;
A1 - Tạo deal &ZeroWidthSpace;
ItemDescription
TriggerBấm "Tạo deal"
BehaviorGom trường của case đang chọn có giá trị (BR-07, BR-08) + Tài khoản nhận phí (BR-05) + CCCD (BR-06) + danh sách contact đã tick (BR-01) → BE kiểm case (BR-02), ghép thuộc tính theo BR-09 với giá trị cố định của (môi trường, case) (BR-04), đặt tên (BR-03), tạo deal và liên kết deal → contact trong cùng một lệnh HubSpot, rồi thêm {id, tên} vào danh sách Redis (BR-11). Ghi vào: HubSpot (dev hoặc production theo BR-12) + Redis mind_keep. ⚠️ Ghi PROD (qua Staging): ở tab Staging, deal được tạo trên portal HubSpot production (pipeline test 877604025 / 882511134) và liên kết với contact production
Success ResultPopup "Đã tạo deal instance"; "Deal đã tạo (n)" tăng 1

Error cases:

CaseExpected Handling
Case không hợp lệ (chỉ khi gọi API trực tiếp)13011 "Invalid SAPP-24395 deal case"
HubSpot từ chối (giá trị thuộc tính sai, contact id không tồn tại, pipeline không có…)Popup "Tạo deal instance thất bại" với lỗi tạo đối tượng HubSpot (12006)
Lỗi khácPopup "Tạo deal instance thất bại" — "Failed to create SAPP deal instance (13009)"
A2 - Chọn case / đổi loại thanh toán Deal Lost &ZeroWidthSpace;
ItemDescription
TriggerBấm một case ở danh sách trái; hoặc bấm tab "Học phí" / "Phí dịch vụ" khi đang ở Deal Lost
BehaviorĐổi case: BR-10. Đổi tab Deal Lost: chỉ đổi nhóm trường hiển thị và nhóm được gửi; giá trị tab kia vẫn giữ trong màn nhưng không gửi (OQ-I-19)
Success ResultTrường của case / tab mới hiện

Error cases:

CaseExpected Handling
—Không có (thao tác cục bộ)
Acceptance Criteria của màn M1 &ZeroWidthSpace;
AC-M1.1 - Tạo deal CBE gắn contact ở Dev &ZeroWidthSpace;
gherkin
Given tab Dev, tool đã tạo 4 deal ở Dev, đã tick contact 101 và 102
And chọn case "Deal CBE", nhập CCCD "012345678901", Deal ID đã thanh toán phí "999"
When bấm "Tạo deal"
Then HubSpot dev có deal "[IT TEST][SAPP-24395] Deal CBE 5" liên kết contact 101, 102
And deal có pipeline 836815496, dealstage 1244260910, loại phí dịch vụ "Phí đăng ký thi CBE", tài khoản nhận phí = giá trị đang chọn, CCCD = "012345678901", Deal ID đã thanh toán phí = "999"
And popup "Đã tạo deal instance"; "Deal đã tạo (5)"

Maps to:

  • Business Rule: BR-01, BR-03, BR-04, BR-05, BR-06, BR-11
  • Field/Action: A1
AC-M1.2 - Tạo deal không gắn contact &ZeroWidthSpace;
gherkin
Given không tick contact nào
When bấm "Tạo deal"
Then dòng tóm tắt trước đó hiện "Chưa chọn contact nào — deal sẽ được tạo mà không gán contact."
And deal được tạo không có liên kết contact

Maps to:

  • Business Rule: BR-01
AC-M1.3 - Deal Lost tab Phí dịch vụ &ZeroWidthSpace;
gherkin
Given tab Dev, case "Deal Lost", tab "Phí dịch vụ"
And nhập Loại phí dịch vụ "Phí bảo lưu", Đợt 1 số tiền "1500000", để trống Đợt 2
When bấm "Tạo deal"
Then deal có loại phí dịch vụ "Phí bảo lưu" (ghi đè giá trị rỗng mặc định), phí dịch vụ đợt 1 = 1500000
And phí dịch vụ đợt 2 và cả 3 số tiền học phí đều = "0" (mặc định)
And không có trường ngày / phương thức nào của tab "Học phí" được gửi

Maps to:

  • Business Rule: BR-08, BR-09
AC-M1.4 - ⚠️ Ghi PROD qua Staging, pipeline riêng cho Chuyển đổi &ZeroWidthSpace;
gherkin
Given tab Staging, case "Deal Chuyển đổi - Ghi nhận doanh thu"
When bấm "Tạo deal"
Then deal được tạo trên portal HubSpot **production** với pipeline 882511134, dealstage 1325314701, loại phí dịch vụ "Chuyển đổi"
And người dùng không thể đổi pipeline / dealstage kể cả khi gửi thuộc tính cùng tên

Maps to:

  • Business Rule: BR-04, BR-09, BR-12 — OQ-I-02
AC-M1.5 - Tài khoản nhận phí mặc định / dự phòng &ZeroWidthSpace;
gherkin
Given danh sách lựa chọn "Tài khoản nhận phí dịch vụ" từ HubSpot không chứa "ACCA - Kể từ 01/01/2026"
When danh sách tải xong
Then ô chọn tự chuyển sang lựa chọn đầu tiên của danh sách
And giá trị này được gửi khi tạo deal

Maps to:

  • Business Rule: BR-05
AC-M1.6 - Đổi case xoá trường riêng &ZeroWidthSpace;
gherkin
Given case "Deal trừ – Chuyển đổi tăng doanh thu" đã nhập Amount "5000000" và CCCD "0123"
When chọn case "Deal CBE" rồi quay lại case cũ
Then Amount trống, CCCD vẫn là "0123"
And khi tạo deal ở case "Deal CBE", Amount không được gửi

Maps to:

  • Business Rule: BR-07, BR-10
  • Field/Action: A2
AC-M1.7 - Case không hợp lệ qua API &ZeroWidthSpace;
gherkin
Given gọi POST /api/v1/sapp/dev/sapp-24395/deals/abc
When BE xử lý
Then trả lỗi 13011 "Invalid SAPP-24395 deal case" (HTTP 400), không tạo deal

Maps to:

  • Business Rule: BR-02
AC-M1.8 - ⚠️ Observed: prod không có loại phí dịch vụ cố định &ZeroWidthSpace;
gherkin
Given gọi trực tiếp POST /api/v1/sapp/prod/sapp-24395/deals/cbe (tab Prod bị tắt trên màn)
When BE tạo deal
Then (hành vi hiện tại) deal trên production không có loại phí dịch vụ "Phí đăng ký thi CBE"
And nếu client gửi loại phí dịch vụ trong trường tự do thì giá trị đó được ghi

Maps to:

  • Business Rule: N/A — ⚠️ Observed (inventory R-14, R-20) → OQ-I-03, OQ-I-02, NFR-I-01
Negative AC / Edge Cases của màn M1 &ZeroWidthSpace;
IDTình huốngHành vi mong đợi
EC-M1.1Hai người / hai tab bấm "Tạo deal" cùng lúc trong cùng môi trường⚠️ Observed — hai deal có thể trùng số thứ tự trong tên, danh sách tool mất một mục (inventory R-09 → OQ-I-06)
EC-M1.2Gọi API với trường tự do chứa thuộc tính bất kỳ (ví dụ amount cho case CBE)⚠️ Observed — được chuyển thẳng sang HubSpot, không có whitelist (trừ khoá cố định của case) (inventory R-12 → OQ-I-07)
EC-M1.3Tick contact rồi đổi tab môi trườngLựa chọn bị xoá (US-I01 BR-02) — không thể gắn contact của môi trường khác
EC-M1.4Contact đã tick bị xoá trên HubSpotHubSpot từ chối liên kết → popup "Tạo deal instance thất bại"
EC-M1.5Đổi tab Deal Lost Học phí → Phí dịch vụ → Học phíSố liệu tab Học phí đã nhập vẫn còn (ghi chú trên màn nói bị xoá — OQ-I-19)
EC-M1.6Bấm "Tạo deal" hai lần nhanhNút khoá trong lúc tạo
EC-M1.7Mất mạng giữa chừngPopup lỗi chung; nếu HubSpot đã tạo xong nhưng phản hồi mất, deal tồn tại trên HubSpot mà không vào danh sách tool (suy từ trình tự: tạo HubSpot trước, ghi Redis sau)

5. Cross-feature AC &ZeroWidthSpace;

AC-X.1 - Deal test nằm trong portal production &ZeroWidthSpace;

gherkin
Given tab Staging
When tạo deal bất kỳ case
Then deal tên "[IT TEST][SAPP-24395] …" xuất hiện trên portal HubSpot production, trong pipeline test, liên kết với contact production đã chọn

Maps to:

  • REL-05 (Be Affected - Dữ liệu HubSpot portal production)

AC-X.2 - Deal là đầu vào luồng ghi nhận doanh thu &ZeroWidthSpace;

gherkin
Given deal được tạo ở pipeline / dealstage của case
When workflow hạ nguồn trên HubSpot / SAP xử lý pipeline đó
Then [Assumption — OQ-I-01] luồng tự động ghi nhận doanh thu được kích hoạt theo case (không truy vết trong code mind_keep)

Maps to:

  • REL-06 (Be Affected - Luồng tự động ghi nhận doanh thu)

AC-X.3 - Logic tạo deal dùng chung với SAPP-26878 &ZeroWidthSpace;

gherkin
Given tool SAPP-26878 chạy bước tạo deal
When cách đặt tên / đếm / lưu danh sách deal của 24395 thay đổi
Then bước tạo deal của 26878 chịu ảnh hưởng tương ứng

Maps to:

  • REL-04 (Be Affected - SAPP-26878 US-D03)