Skip to content

SAPP-24395 — Contact / Deal instances & Bulk product creation - FS Overview ​

File tổng quan + index của FS. Mỗi User Story là 1 file riêng trong cùng thư mục (US-I0x-<slug>.md). Các phần dùng chung (tổng quan, flow tổng, related features, NFR, Open Questions, References) đặt tập trung tại đây — file US chỉ tham chiếu ID, không lặp lại.

⚠️ As-built dựng từ đọc source tại commit e77c47a, KHÔNG chạy app / API thật. Mọi hành vi mô tả là suy từ code; các chỗ nghi lỗi ghi ⚠️ Observed và chưa được xác nhận bằng chạy thử.

FieldValue
Doc IDFS-SAPP-24395
ModeB – As-built
As-built tại commite77c47a
Last Updated2026-09-30
AuthorAI (lane ba/)
ReviewersBA
StatusDRAFT
Figma ProjectN/A — as-built, không có Figma
Related BRDbrd-as-built-v0.1-20260930.md
Related Impact MatrixN/A — Mode B, không có Impact Matrix

1. Tổng quan dự án &ZeroWidthSpace;

Nhóm SAPP-24395 ("Tự động ghi nhận doanh thu bán hàng CX") gồm hai sub-tool trong workspace /works/sapp/tools:

  • sapp.006 — Contact / Deal instances (/works/sapp/tools/sapp-24395): tạo contact và deal mẫu trên HubSpot theo 14 deal case, ở môi trường Dev / Staging (Prod đang tắt trên giao diện), rồi xem lại danh sách đã tạo.
  • sapp.007 — Bulk product creation (/works/sapp/tools/sapp-24395-products): tạo hàng loạt payment product trên SAPP Ops từ một danh sách cố định 102 dòng, theo một session nhiều bước (category → subject → product) lưu trên Redis.

1.1 Bối cảnh &ZeroWidthSpace;

[Assumption — chưa có nguồn nghiệp vụ trong shared/external/sapp/** cho SAPP-24395; G-05 chưa trả lời] Đội kiểm thử luồng "tự động ghi nhận doanh thu" cần dựng nhanh dữ liệu đầu vào trên HubSpot (contact + deal theo từng loại giao dịch) và dữ liệu danh mục sản phẩm trên SAPP Ops, thay vì tạo tay từng bản ghi. Mô tả ở header màn sapp.006: "Tạo contact & deal instance mẫu trên HubSpot để kiểm thử luồng tự động ghi nhận doanh thu" (fe/src/ui/components/works/sapp/sapp-24395-tool.tsx, ToolHeader).

1.2 Mục tiêu &ZeroWidthSpace;

[Assumption — OQ-I-01, G-05] Giảm thời gian chuẩn bị dữ liệu test cho luồng tự động ghi nhận doanh thu; mỗi deal case tương ứng một tình huống nghiệp vụ cần kiểm thử. Không có KPI được BA xác nhận.

1.3 In Scope &ZeroWidthSpace;

Phạm vi đã truy vết (inventory §1):

  • Màn sapp.006: chọn môi trường, tạo contact, tạo deal theo 14 case (kèm gắn contact, tài khoản nhận phí, CCCD, trường riêng theo case), xem danh sách / lịch sử deal.
  • Màn sapp.007: session bulk product — bước 1 (nạp category), bước 2 (nạp subject) + 2.5 (tạo subject thiếu), bước 3 (tạo product), khôi phục session, bắt đầu lại.
  • Bước 1.5 (tạo category thiếu) — chỉ có ở API, không có trên màn (mô tả trong US-I04).
  • 12 route HubSpot /api/v1/sapp/{prod|staging|dev}/sapp-24395/… và 6 route /api/v1/sapp/sapp-24395/products/sessions….
  • Dữ liệu Redis (danh sách contact/deal theo môi trường, session bulk product) + localStorage (mã session).

1.4 Out Of Scope &ZeroWidthSpace;

  • Hub / khoá tool / trạng thái tool → US-P01, US-P02, US-P03.
  • Cấu hình env_systems (token HubSpot, SAPP_BASE_API_URL, SAPP_API_TOKEN) → US-P04.
  • Quyền truy cập API (@Public()) → NFR-P-01.
  • Auto-login / passthrough SAPP Ops → US-P08. Tool bulk product không dùng auto-login — dùng token tĩnh (inventory R-24).
  • Component widget theo định nghĩa property HubSpot và route đọc property → tool Property (US-H01); FS này chỉ ghi là tool gọi tới.
  • Việc tool SAPP-26878 dùng lại hàm tạo contact / deal → US-D03.
  • Hành vi hạ nguồn trên HubSpot / SAP sau khi deal được tạo (workflow, ghi nhận doanh thu) — không truy vết.

1.5 Roles And Permissions &ZeroWidthSpace;

Role IDRole NameDescriptionPermission Summary
R1Người dùng toolNgười mở được sapp.006 / sapp.007 trong workspace SAPP. Assumption (OQ về G-01 → OQ-I-16) — code không phân biệt roleKhông có quyền riêng ở BE: mọi route @Public() (NFR-I-01 → NFR-P-01). Gate duy nhất là trạng thái / khoá tool ở giao diện (US-P02)

2. Luồng tổng quan của dự án &ZeroWidthSpace;

text
[Workspace SAPP › nhóm "SAPP 24395 - Tự động ghi nhận doanh thu"]  (US-P01, US-P02)
  ├─ sapp.006 Contact / Deal instances
  │    ↓
  │  [US-I01: chọn tab Dev / Staging (Prod tắt) → nạp danh sách contact + deal đã tạo]
  │    ↓
  │  [US-I02: tạo contact]  ──(tick contact)──→  [US-I03: chọn 1/14 case → tạo deal gắn contact]
  │    ↓                                              ↓
  │  HubSpot dev  |  HubSpot PROD (tab Staging)   ← ghi   (danh sách lưu Redis theo môi trường)
  │
  └─ sapp.007 Bulk product creation  (SAPP Ops — môi trường theo SAPP_BASE_API_URL ❓)
       ↓
     [US-I04: Bước 1 bắt đầu session, nạp category]  (Bước 1.5 tạo category thiếu: chỉ API)
       ↓
     [US-I05: Bước 2 nạp subject → 2.5 tạo subject thiếu]
       ↓
     [US-I06: Bước 3 tạo 102 product → báo cáo created / skipped / failed]
       ↓
     [Hết: session hết hạn 6 giờ sau lần ghi cuối, hoặc "Bắt đầu lại"]

Link flow: N/A — không có flow vẽ riêng.

3. Các tính năng liên quan &ZeroWidthSpace;

MãTính năng liên quanLink tài liệuLoại liên quanMục bị ảnh hưởng ở feature kiaMục ảnh hưởng ở feature hiện tạiMô tả ảnh hưởng
REL-01Nền tảng — Hub mở tool / khoá toolUS-P01, US-P02Affects-US-I01.M1, US-I04.M1 — vào mànTool đang tắt / ẩn / khoá thì không vào được màn (chỉ ở giao diện)
REL-02Nền tảng — cấu hình env_systemsUS-P04Affects-US-I02/I03 (token HubSpot dev/prod); US-I04…I06 (SAPP_BASE_API_URL, SAPP_API_TOKEN)Sai / thiếu cấu hình → lỗi tạo; giá trị URL quyết định môi trường SAPP Ops bị ghi
REL-03HubSpot — Get property (sapp.003)US-H01Affects-US-I02.M1 fields, US-I03.M1 fieldsWidget (text / select / date…) và danh sách "Tài khoản nhận phí dịch vụ" dựng từ định nghĩa property đọc qua route của tool Property
REL-04SAPP-26878 — bước tạo deal / contactUS-D03Be AffectedUS-D03 — bước loại dealUS-I02 A1, US-I03 A1 (logic tạo dùng chung)Đổi cách tạo / dùng lại contact ở 24395 ảnh hưởng 26878
REL-05Dữ liệu HubSpot portal production (hệ ngoài, không có FS)N/ABe AffectedContact học viên thật, pipeline test trong portal prodUS-I02 A1, US-I03 A1 (tab Staging)Tab Staging ghi vào portal prod; email trùng → cập nhật đè contact có sẵn (OQ-I-02, OQ-I-05)
REL-06Luồng tự động ghi nhận doanh thu trên HubSpot / SAP (hệ ngoài)N/ABe Affected[Assumption] workflow hạ nguồn của pipeline testUS-I03 A1[Assumption — OQ-I-01] deal tạo ra là đầu vào của luồng đang được kiểm thử
REL-07Danh mục SAPP Ops (course category / subject / payment product)N/ABe AffectedDữ liệu danh mục trên SAPP OpsUS-I04 A3, US-I05 A2, US-I06 A1Tool tạo category / subject / product thật trên SAPP Ops (môi trường ❓ — OQ-I-04)

4. User Story Index &ZeroWidthSpace;

US IDTên User StoryFileRolePriorityStatus
US-I01Chọn môi trường và xem contact / deal đã tạo bằng toolUS-I01-xem-contact-deal.mdR1N/A — as-builtDraft
US-I02Tạo contact test (trùng email → cập nhật contact cũ)US-I02-tao-contact.mdR1N/A — as-builtDraft
US-I03Tạo deal test theo 14 deal case và gắn contactUS-I03-tao-deal.mdR1N/A — as-builtDraft
US-I04Bulk product: bắt đầu session, nạp và tạo course categoryUS-I04-bulk-category.mdR1N/A — as-builtDraft
US-I05Bulk product: nạp và tạo subject còn thiếuUS-I05-bulk-subject.mdR1N/A — as-builtDraft
US-I06Bulk product: tạo product và xem báo cáo kết quảUS-I06-bulk-product.mdR1N/A — as-builtDraft

Status = Draft (as-built chờ Gate R2).

5. Non-functional Requirements &ZeroWidthSpace;

IDRequirementApplies To (US/màn/API)Acceptance Criteria
NFR-I-01Quyền truy cập: cả 18 route của nhóm là @Public() — xem NFR-P-01. Riêng nhóm này: tab Prod bị tắt trên giao diện nhưng 4 route prod (/api/v1/sapp/prod/sapp-24395/…) vẫn mở và ghi thẳng vào HubSpot production (inventory R-20)US-I01…I06; đặc biệt route prod của US-I02/I03Gọi POST /api/v1/sapp/prod/sapp-24395/contacts không kèm đăng nhập vẫn tạo contact trên portal prod (suy từ code — chưa chạy). Cố ý hay không → OQ-I-02
NFR-I-02Thời gian xử lý bước 3: tạo product tuần tự, có thể vài phút; server nâng timeout HTTP lên 10 phút, mỗi lệnh gọi SAPP Ops timeout 10 phút (inventory R-36)US-I06 A1Request bước 3 không bị cắt trước 10 phút ở phía server (be/apps/api/src/main.ts:104-109; be/libs/constants/src/lib/sapp/sapp.constants.ts:34-38)
NFR-I-03Nạp dữ liệu SAPP Ops theo trang 100 dòng tới khi trang cuối < 100 (inventory R-26)US-I04 A1, US-I05 A1, US-I06 A1Danh mục > 100 bản ghi vẫn nạp đủ (be/libs/modules/src/lib/sapp/common.service.ts:2496-2581)
NFR-I-04Lưu trạng thái: danh sách contact / deal theo môi trường lưu Redis không hết hạn, không có API xoá; session bulk product lưu Redis TTL 6 giờ tính lại từ lần ghi gần nhất; mã session lưu localStorage trình duyệt (inventory §4a, R-21, R-25). Không có bảng DBUS-I01…I06Sau 6 giờ không có thao tác ghi, mọi route session trả 13017 (HTTP 404). Danh sách contact / deal còn nguyên sau khởi động lại service (miễn Redis còn dữ liệu)
NFR-I-05Môi trường ghi (tổng hợp): Dev → HubSpot dev; Staging → HubSpot PRODUCTION (cùng credential prod, cố ý theo comment code be/libs/constants/src/lib/hubspot/hubspot.constants.ts:19-26); Prod → HubSpot production (chỉ qua API); bulk product → SAPP Ops tại SAPP_BASE_API_URL (môi trường ❓ — OQ-I-04)US-I02, US-I03, US-I04…I06Mỗi action ghi trong file US có dòng "Ghi vào" + cảnh báo ⚠️ Ghi PROD khi có đường ghi production
NFR-I-06Logging: lỗi mỗi handler được ghi log theo tên handler; không có thông báo mail / push / MQTT; không có job / cron (inventory §6)US-I01…I06Log BE có tiền tố [<tên handler>] khi lỗi (ví dụ be/apps/api/src/sapp/sapp.controller.ts:2126)
NFR-I-07Hiển thị lỗi: mọi lỗi API hiện popup với tiêu đề theo thao tác và nội dung <message> (<code>) (fe/src/ui/components/works/sapp/hubspot-property-field.tsx:41-70; fe/src/ui/components/works/sapp/sapp-24395-products-tool.tsx:143-163)US-I01…I06Lỗi 13011 hiện "Tạo deal instance thất bại" + "Invalid SAPP-24395 deal case (13011)"

6. Open Questions &ZeroWidthSpace;

IDQuestionOwnerDue DateStatusBlocks (US)
OQ-I-01Ý nghĩa nghiệp vụ của từng deal case (14 case) và luồng "tự động ghi nhận doanh thu" mà mỗi case dùng để kiểm thử là gì? Code chỉ có nhãn + pipeline / dealstage. FS đang ghi ý nghĩa là Assumption. (inventory Q-01; G-05)BA / Owner SAPP-24395TBDOpenUS-I03
OQ-I-02Tab "Staging" thực chất ghi contact / deal vào portal HubSpot production (comment code nói là chủ đích — không có portal staging). Tab Prod tắt ở giao diện nhưng route prod BE vẫn mở không cần đăng nhập. Có chấp nhận rủi ro này không, có cần cảnh báo trên màn / chặn route prod? (inventory Q-02, R-19, R-20; G-02, G-04)BA / Owner tool / BETBDOpenUS-I01, US-I02, US-I03
OQ-I-03Ở môi trường prod, không case nào có loai_phi_dich_vu cố định, trong khi staging (cùng portal prod) và dev có; ở prod client còn tự ghi được thuộc tính này cho mọi case. Cố ý hay thiếu sót? (inventory Q-03, R-14)BA / BETBDOpenUS-I03
OQ-I-04Bulk product ghi vào SAPP Ops môi trường nào trên thực tế (giá trị SAPP_BASE_API_URL hiện tại)? Đã từng chạy vào prod chưa? Token JWT tĩnh do ai thay khi hết hạn? (inventory Q-04, R-23, R-24; G-09)BA / Ops / BETBDOpenUS-I04, US-I05, US-I06
OQ-I-05Email đã tồn tại → tool cập nhật đè contact HubSpot có sẵn bằng dữ liệu vừa nhập, kể cả trên portal prod (tab Staging) → contact học viên thật có thể bị sửa. Cố ý hay bug; có chấp nhận không? (inventory Q-05, R-04; G-04)BA / Owner toolTBDOpenUS-I02
OQ-I-06Hai lệnh tạo deal đồng thời có thể trùng số thứ tự trong tên và mất một mục trong danh sách (bộ đếm đọc-rồi-ghi không khoá). Có cần đảm bảo tên duy nhất? (inventory Q-06, R-09)BA / BETBDOpenUS-I03
OQ-I-07Trường tự do properties khi tạo deal không có whitelist — người gọi API ghi được bất kỳ thuộc tính deal nào (trừ khoá cố định của case). Cố ý (linh hoạt cho tester) hay cần giới hạn như tool 26878? (inventory Q-07, R-12)BA / BETBDOpenUS-I03
OQ-I-08Danh sách contact / deal của tool không hết hạn, không có chức năng xoá / reset; bộ đếm tên deal tăng mãi. Có cần không? (inventory Q-08, R-21)BATBDOpenUS-I01
OQ-I-09Nghi lỗi FE bước 3 (suy từ code, chưa chạy): FE coi kết quả bước 3 là session → popup luôn "Tạo thành công 0, lỗi 0", màn không hiện kết quả, mã session trong trình duyệt bị thay bằng giá trị không xác định. Bug hay cố ý? Cần chạy thử xác nhận. (inventory Q-09, R-33, DR-08; G-06)BA / QA / FETBDOpenUS-I06
OQ-I-10Nghi lỗi FE nhận diện hết hạn session (suy từ code): FE so mã lỗi với chuỗi tên lỗi, trong khi BE trả mã số 13017 → popup "Session đã hết hạn" có thể không bao giờ hiện, key cũ không bị xoá. Bug hay cố ý? (inventory Q-10, R-34; G-06)BA / QA / FETBDOpenUS-I04, US-I05, US-I06
OQ-I-11Deal có tên rỗng (null) có làm hỏng ô tìm kiếm lịch sử deal không (FE gọi chuyển chữ thường trên tên không chặn null)? (inventory Q-11, R-22)QA / FETBDOpenUS-I01
OQ-I-12SAPP Ops có trường hợp trả thành công mà không kèm id không? Hiện mục đó vẫn tính là "created" với id rỗng (category / subject / product). (inventory Q-12, R-32)BE / OpsTBDOpenUS-I04, US-I05, US-I06
OQ-I-13Bước 1.5 (tạo category thiếu) và danh sách "skipped" không có trên màn (chỉ có ở API). Chủ đích (chưa làm) hay thiếu? Nếu category thiếu, người dùng xử lý thế nào — hiện các product thuộc category đó rơi vào "failed". (inventory Q-13, R-35, DR-07)BA / FETBDOpenUS-I04, US-I06
OQ-I-14Cảnh báo "API gốc chặn CORS … chỉ chạy khi local / ngrok" trên màn bulk product còn đúng không, khi BE gọi SAPP Ops phía server (CORS không áp dụng)? (inventory Q-14, R-38)BA / FETBDOpenUS-I04
OQ-I-15Danh sách 102 product cố định (lấy từ CSV "Đồng bộ Hubspot ↔ Order" theo chú thích code): ai là owner, khi nào cập nhật, quy tắc giá là của nghiệp vụ hay chỉ là dữ liệu test? (inventory Q-15, R-37)BATBDOpenUS-I06
OQ-I-16Ai được dùng 2 tool này (role)? FS đang ghi "Người dùng tool" là Assumption. (inventory Q-16; G-01)BATBDOpenUS-I01…I06
OQ-I-17Mục đích tiền tố [IT TEST][SAPP-24395] (tên deal) và [SAPP-24395][AUTO] (tên product): để nhận diện / dọn dữ liệu test? Có quy trình dọn không? (inventory Q-17)BA / OpsTBDOpenUS-I03, US-I06
OQ-I-18Phát hiện khi viết FS (suy từ đoạn code inventory đã trích be/libs/modules/src/lib/sapp/common.service.ts:1566-1569): khi email trùng, contact dùng lại vẫn được thêm thêm một lần vào danh sách tool (không kiểm id đã có) → danh sách có thể lặp cùng một contact; popup vẫn báo "đã được tạo" dù thực tế là cập nhật (fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:262-268). Cố ý hay bug? (không có mã inventory — bổ sung ở R3)BA / FE / BETBDOpenUS-I01, US-I02
OQ-I-19Chữ hướng dẫn lệch hành vi (đọc trực tiếp từ code, R3): (a) danh sách contact trống ghi "Bấm 'Tạo contact mặc định'" trong khi nút tên là "Tạo contact" (fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:359); (b) Deal Lost ghi "Đổi tab sẽ xóa dữ liệu đã nhập ở tab trước" nhưng code chỉ bỏ qua (không gửi) giá trị của tab kia, giá trị vẫn còn khi quay lại tab (:740, :501-516). Sửa chữ hay sửa hành vi?BA / FETBDOpenUS-I01, US-I03

6b. Drift: tài liệu ↔ code (Mode B/C — Mode A ghi N/A) &ZeroWidthSpace;

Từ inventory §7. Không tự chọn bên đúng — shared/api-docs/sapp.md chỉ lane be/ được sửa.

IDTài liệu nóiCode đang làm (bằng chứng file:dòng)Ảnh hưởngOwner quyết
DR-I-01shared/api-docs/sapp.md:797: bộ thuộc tính theo case trong một môi trường "currently identical"; prod/staging và dev chỉ khác pipeline / dealstage (inventory DR-01)4 case Chuyển đổi dùng pipeline khác (prod/staging 882511134); ở dev 3 case Chuyển nhượng cũng khác; staging/dev có loai_phi_dich_vu khác nhau theo case — be/apps/api/src/sapp/sapp.controller.ts:1780-1826, :1843-1927, :1975-2027Reader lane / QA hiểu sai deal sinh ra theo caseBE
DR-I-02shared/api-docs/sapp.md:722, :797: staging dùng "the same fixed per-case deal properties as prod" (inventory DR-02)Staging có loai_phi_dich_vu theo case; prod không có — be/apps/api/src/sapp/sapp.controller.ts:1743-1828 vs :1832-1931Cùng portal, deal khác nhau tuỳ tab (OQ-I-03)BE
DR-I-03shared/api-docs/sapp.md:832: loai_phi_dich_vu là thuộc tính cố định, không ghi đè được (inventory DR-03)Deal Lost cho client ghi đè (doc :879 lại nói đúng — mâu thuẫn nội bộ); ở prod không cố định nên client ghi được — be/libs/constants/src/lib/sapp/sapp.constants.ts:267; be/apps/api/src/sapp/sapp.controller.ts:2058-2067Doc tự mâu thuẫnBE
DR-I-04shared/api-docs/sapp.md:879: Deal Lost loai_phi_dich_vu "defaults to empty when omitted" (inventory DR-04)Chỉ đúng ở staging/dev; prod không gửi thuộc tính này — be/apps/api/src/sapp/sapp.controller.ts:1744-1749 vs :1833-1839Như DR-I-02BE
DR-I-05shared/api-docs/sapp.md:745, :771-775: response tạo contact { id, name }, không nói email trùng (inventory DR-05)Email trùng → cập nhật contact cũ, response thêm reused — be/libs/modules/src/lib/hubspot/common.service.ts:622-661; be/libs/interface/src/lib/dto/sapp/sapp-instance.dto.ts:66-70Rủi ro ghi đè không được tài liệu hoá (OQ-I-05)BE
DR-I-06shared/api-docs/sapp.md:1153: "session lives in Redis for 6 hours" (inventory DR-06)6 giờ tính từ lần ghi gần nhất — be/libs/modules/src/lib/sapp/common.service.ts:2600-2608Người dùng tưởng hết hạn sớm hơnBE
DR-I-07shared/api-docs/sapp.md:1133-1148: FE nên hiện missingCategoryNames và cho tạo category thiếu (bước 1.5) (inventory DR-07)FE không có URL, service, type hay UI cho bước 1.5 — fe/src/data/constants/api.ts:439-449; fe/src/data/services/sapp/sapp-24395-products.service.ts:1-82Category thiếu → product "failed" (OQ-I-13)BA / FE
DR-I-08shared/api-docs/sapp.md:1337-1353: response bước 3 là báo cáo {created, skipped, failed} (inventory DR-08)FE khai báo và dùng như session — fe/src/data/services/sapp/sapp-24395-products.service.ts:61-71; fe/src/ui/components/works/sapp/sapp-24395-products-tool.tsx:329-331Nghi lỗi "0/0" (OQ-I-09)FE
DR-I-09Chú thích code be/apps/api/src/sapp/sapp.controller.ts:1724-1728: "no request body… separate prod / dev route" (inventory DR-09)Contact và deal đều nhận body; có thêm route staging — :2198-2200, :2261Chú thích lỗi thờiBE
DR-I-10Chú thích code be/libs/modules/src/lib/sapp/common.service.ts:236-237: sessionKey "client-supplied" (inventory DR-10)sessionKey do server sinh (UUID) — :2619Chú thích lỗi thờiBE
DR-I-11Swagger be/apps/api/src/sapp/sapp.controller.ts:2302, :2342, :2406: "currently identical per case"; staging "the same fixed per-case property set" (inventory DR-11)Như DR-I-01 / DR-I-02Swagger saiBE
DR-I-12Chú thích FE fe/src/data/services/sapp/sapp-24395.service.ts:17-18: mỗi thao tác nhắm portal prod / dev (inventory DR-12)Có 3 môi trường, staging dùng portal prod — fe/src/data/constants/api.ts:222-227Chú thích lỗi thời, che mất rủi ro Staging = prodFE

7. References &ZeroWidthSpace;

  • BRD: brd-as-built-v0.1-20260930.md
  • Impact Matrix: N/A — Mode B
  • Solution Decision: project-decisions.md
  • Figma: N/A — as-built, không có Figma
  • API Spec: shared/api-docs/sapp.md §"sapp-24395 tool" (:716-1372) — có drift, xem §6b
  • Code đã đọc (Mode B/C): chi tiết ở feature-inventory-24395-20260930.md §9. File chính:
    • fe/src/ui/components/works/sapp/sapp-24395-tool.tsx, fe/src/ui/components/works/sapp/sapp-24395-products-tool.tsx
    • fe/src/data/services/sapp/sapp-24395.service.ts, fe/src/data/services/sapp/sapp-24395-products.service.ts
    • be/apps/api/src/sapp/sapp.controller.ts:1720-2690
    • be/libs/modules/src/lib/sapp/common.service.ts:115-302, :1535-1684, :2489-3008
    • be/libs/modules/src/lib/hubspot/common.service.ts:40-70, :530-700
    • be/libs/constants/src/lib/sapp/sapp.constants.ts, be/libs/constants/src/lib/sapp/sapp-24395-products.constants.ts, be/libs/constants/src/lib/hubspot/hubspot.constants.ts:10-30
    • be/libs/interface/src/lib/dto/sapp/sapp-instance.dto.ts, be/libs/constants/src/lib/error-codes/error-codes.constants.ts:574-648
  • Meeting Notes / Q&A: gate-r1-summary-20260930.md (G-01…G-10 chưa trả lời); us-backlog-r2-20260930.md (FS 4)

Traceability A-xx → US &ZeroWidthSpace;

Hành động inventoryUS
A-01, A-02, A-08US-I01
A-03, A-04US-I02
A-05, A-06, A-07US-I03
A-09, A-10, A-11, A-16, A-17US-I04
A-12, A-13US-I05
A-14, A-15US-I06

Template Conformance Check &ZeroWidthSpace;

Quét từng file US, so khớp mục lục với ba/_workflow/templates/fs/User-Story.md (Metadata · 1 US Statement · 2 Dependencies & DoR · 3 Business Rules [cột "Đã cover bởi (AC)" + "Nguồn code"] · 4 Design [a flow; b mỗi màn: UI States / Fields / Filter-Search-Sort nếu List / Actions / AC G/W/T / Negative AC-Edge Cases] · 5 Cross-feature AC).

US fileSection thiếuTrạng thái
US-I01-xem-contact-deal.md(đủ — M2 là màn List: có Filter/Search/Sort; M1 Filter ghi N/A có lý do)✅
US-I02-tao-contact.md(đủ — Filter/Search/Sort N/A: màn form)✅
US-I03-tao-deal.md(đủ — Filter/Search/Sort N/A: màn form)✅
US-I04-bulk-category.md(đủ — Filter/Search/Sort N/A: màn wizard)✅
US-I05-bulk-subject.md(đủ — Filter/Search/Sort N/A: danh sách chọn, không lọc)✅
US-I06-bulk-product.md(đủ — Filter/Search/Sort N/A: báo cáo không lọc)✅