Skip to content

Feature Inventory — SAPP-24395: Contact / Deal instances & Bulk product creation ​

Kiểm kê tính năng đã triển khai, dựng từ code. Đầu vào cho FS as-built (Mode B) và là "bức tranh hiện tại" cho Mode C. Mọi dòng phải có bằng chứng file:dòng; không có bằng chứng → không ghi vào bảng (đưa sang §8 Câu hỏi).

Công thức truy vết: ba/system-profile.md §3.

⚠️ Toàn bộ nội dung dựng từ đọc source tại commit e77c47a, KHÔNG chạy app / API thật. Mọi "Kết quả quan sát được" là suy từ code, chưa đo trên môi trường nào.

FieldValue
Projectba/projects/2026-SAPP-Works-tools
ModeB – As-built
Ngày đọc code2026-09-30
Commite77c47a
Điểm vào BA cung cấpNhóm SAPP-24395 dưới /works/sapp/tools: sapp-24395 (sapp.006, "SAPP 24395: Contact / Deal instances") và sapp-24395-products (sapp.007, "SAPP 24395: Bulk product creation"); shared/api-docs/sapp.md §"sapp-24395 tool: …"
Thành phần chạm tớiFE (CMS) · BE (api) · Redis · HubSpot (portal prod & dev) · SAPP Ops REST API
StatusDraft

1. Phạm vi đã truy vết ​

  • Trong phạm vi:
    • Màn /works/sapp/tools/sapp-24395 (tạo contact / deal mẫu trên HubSpot theo 14 deal case, 3 môi trường dev / staging / prod).
    • Màn /works/sapp/tools/sapp-24395-products (tạo hàng loạt payment product trên SAPP Ops theo session nhiều bước).
    • 12 route HubSpot /api/v1/sapp/{prod|staging|dev}/sapp-24395/{contacts|deals…} và 6 route /api/v1/sapp/sapp-24395/products/sessions….
    • Service SappCommonService (phần 24395), HubSpotCommonService.createOrReuseContact / createDeal, SappService (course categories / subjects / payment products), hằng số deal case, danh sách 102 product cứng, DTO, error code, khoá Redis.
  • Ngoài phạm vi (dừng truy vết tại đây):
    • @Public() / secret gate / quyền theo TOOL_CODES → nền tảng.
    • Đọc env_systems (EnvSystemCommonService, EnvSystemMapCommonService) → nền tảng.
    • Auto-login SAPP Ops (SappAuthCommonService), Ops passthrough / SQL, SAP log trace → nền tảng (tool 24395 không dùng auto-login; xem R-24).
    • Component dùng chung HubspotPropertyField và route GET /api/v1/sapp/{env}/hubspot/{object}/properties/{property} (tool "Property") — chỉ ghi là tool 24395 gọi tới để dựng widget.
    • Shell / registry / lưu trạng thái tool chung (fe/src/ui/pages/works/sapp/tools/shell.tsx) → nền tảng.
    • Tool SAPP-26878 dùng lại createDealInstance / createContactInstance — chỉ ghi nhận việc dùng chung.

2. Điểm vào (Entry points) ​

IDLoạiTên / đường dẫn người dùng thấyBằng chứng
E-01Màn web/works/sapp/tools/sapp-24395 — nhóm "SAPP 24395 - Tự động ghi nhận doanh thu" › "Contact / Deal instances" (code sapp.006)fe/app/works/sapp/tools/sapp-24395/page.tsx:9; fe/src/ui/pages/works/sapp/tools/registry.ts:69-77; fe/src/data/constants/tool-codes.ts:37
E-02Màn web/works/sapp/tools/sapp-24395-products — "Bulk product creation" (code sapp.007)fe/app/works/sapp/tools/sapp-24395-products/page.tsx:9; fe/src/ui/pages/works/sapp/tools/registry.ts:78-82; fe/src/data/constants/tool-codes.ts:38
E-03APIPOST /api/v1/sapp/{prod|dev|staging}/sapp-24395/contactsbe/apps/api/src/sapp/sapp.controller.ts:2190 (prod), :2210 (dev), :2261 (staging); controller prefix sapp v1 :157
E-04APIGET /api/v1/sapp/{prod|dev|staging}/sapp-24395/contactsbe/apps/api/src/sapp/sapp.controller.ts:2230, :2246, :2281
E-05APIPOST /api/v1/sapp/{prod|dev|staging}/sapp-24395/deals/:dealCasebe/apps/api/src/sapp/sapp.controller.ts:2297, :2337, :2401
E-06APIGET /api/v1/sapp/{prod|dev|staging}/sapp-24395/dealsbe/apps/api/src/sapp/sapp.controller.ts:2377, :2389, :2438
E-07APIPOST /api/v1/sapp/sapp-24395/products/sessions (Bước 1)be/apps/api/src/sapp/sapp.controller.ts:2460
E-08APIPOST /api/v1/sapp/sapp-24395/products/sessions/:sessionKey/categories/create (Bước 1.5, tùy chọn)be/apps/api/src/sapp/sapp.controller.ts:2478
E-09APIPOST /api/v1/sapp/sapp-24395/products/sessions/:sessionKey/subjects (Bước 2)be/apps/api/src/sapp/sapp.controller.ts:2503
E-10APIPOST /api/v1/sapp/sapp-24395/products/sessions/:sessionKey/subjects/create (Bước 2.5, tùy chọn)be/apps/api/src/sapp/sapp.controller.ts:2525
E-11APIPOST /api/v1/sapp/sapp-24395/products/sessions/:sessionKey/create (Bước 3)be/apps/api/src/sapp/sapp.controller.ts:2550
E-12APIGET /api/v1/sapp/sapp-24395/products/sessions/:sessionKey (xem snapshot)be/apps/api/src/sapp/sapp.controller.ts:2570

Đường nối FE → URL: fe/src/data/constants/api.ts:222-227 (E-03…E-06), :440-449 (E-07, E-09…E-12). E-08 không có URL phía FE (xem DR-07).

3. Hành động người dùng / hệ thống ​

Role: code không phân biệt role (mọi route @Public(); gate thật nằm ở nền tảng) → ghi "Người dùng CMS".

3a. Tool Contact / Deal instances (E-01) ​

IDAi (role)Làm gìĐiểm vàoKết quả quan sát đượcBằng chứng
A-01Người dùng CMSChọn môi trường ở tab: Dev (mặc định), Staging; tab Prod bị vô hiệu hoá ("Tạm thời vô hiệu hóa")E-01Mỗi lần đổi tab, toàn bộ panel được dựng lại, danh sách + lựa chọn contact theo từng môi trườngfe/src/ui/components/works/sapp/sapp-24395-tool.tsx:49-54, :989, :1014-1021, :1038
A-02Hệ thống (FE)Khi mở panel một môi trường, tải danh sách contact và deal đã tạo bởi tool trong môi trường đóE-01 → E-04, E-06Hiện "Contact đã tạo (n)" và "Deal đã tạo (n)"; nút "Tải lại" gọi lạife/src/ui/components/works/sapp/sapp-24395-tool.tsx:908-928, :341-348; fe/src/data/services/sapp/sapp-24395.service.ts:39-47, :67-75
A-03Người dùng CMSNhập thông tin contact (Họ tên *, Email, SĐT, Địa chỉ, Tỉnh/TP, Ngày sinh) rồi bấm "Tạo contact"E-01 → E-03Tạo contact trên HubSpot portal của môi trường; thêm {id, name} vào danh sách; thông báo "Đã tạo contact instance"fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:64-93, :257-290; be/apps/api/src/sapp/sapp.controller.ts:2094-2108; be/libs/modules/src/lib/sapp/common.service.ts:1547-1582
A-04Hệ thống (BE)Nếu email đã tồn tại trên HubSpot (409), cập nhật contact cũ bằng dữ liệu vừa nhập và trả contact đó với cờ reused = trueE-03Contact cũ bị ghi đè các trường gửi lên; vẫn được thêm vào danh sách toolbe/libs/modules/src/lib/hubspot/common.service.ts:622-661; be/libs/modules/src/lib/sapp/common.service.ts:1554-1564
A-05Người dùng CMSTick chọn các contact trong danh sách để gắn vào dealE-01Số contact đã chọn hiện ở mục 2 ("Sẽ gán n contact: …")fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:363-381, :934-941, :598-601
A-06Người dùng CMSChọn 1 trong 14 deal case; chọn "Tài khoản nhận phí dịch vụ" (danh sách lấy từ HubSpot); nhập CCCD/Hộ chiếu; nhập các trường riêng của case (Deal Lost: chọn loại "Học phí" 3 đợt hoặc "Phí dịch vụ" 2 đợt + Loại phí dịch vụ)E-01Đổi case thì xoá dữ liệu trường riêng đã nhập; đổi tab loại thanh toán ở Deal Lost cũng chỉ gửi trường của tab đang chọnfe/src/ui/components/works/sapp/sapp-24395-tool.tsx:100-136, :148-224, :427-457, :643-819
A-07Người dùng CMSBấm "Tạo deal"E-01 → E-05Tạo deal trên HubSpot, tên tự sinh [IT TEST][SAPP-24395] {nhãn case} {số thứ tự}, gắn các contact đã chọn; thêm {id, dealname} vào danh sách; thông báo "Đã tạo deal instance"fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:459-524; be/apps/api/src/sapp/sapp.controller.ts:2312-2335; be/libs/modules/src/lib/sapp/common.service.ts:1615-1663
A-08Người dùng CMSMở "lịch sử deal đã tạo", tìm theo tên dealE-01Modal lọc danh sách deal theo chuỗife/src/ui/components/works/sapp/sapp-24395-tool.tsx:609-630, :823-899

3b. Tool Bulk product creation (E-02) ​

IDAi (role)Làm gìĐiểm vàoKết quả quan sát đượcBằng chứng
A-09Hệ thống (FE)Khi mở màn, nếu trình duyệt còn lưu sessionKey thì tải lại snapshot session và nhảy tới bước đã đạtE-02 → E-12"Đang khôi phục session…"; nếu session hết hạn thì xoá key đã lưu (im lặng)fe/src/ui/components/works/sapp/sapp-24395-products-tool.tsx:210-245; fe/src/data/constants/local-storage.ts:6
A-10Người dùng CMSBước 1 — bấm "Bắt đầu — Nạp categories"E-02 → E-07Tạo session mới, nạp toàn bộ course category của SAPP Ops, tính các category trong danh sách cứng còn thiếu; thông báo "Đã nạp n categories"fe/src/ui/components/works/sapp/sapp-24395-products-tool.tsx:260-273, :562-571; be/libs/modules/src/lib/sapp/common.service.ts:2614-2638
A-11(Chỉ BE)Bước 1.5 — tạo các course category còn thiếu (một phần hoặc tất cả)E-08Tạo category trên SAPP Ops, thêm vào session, báo created / failed. FE không có nút / không gọibe/libs/modules/src/lib/sapp/common.service.ts:2739-2799; không có trong fe/src/data/services/sapp/sapp-24395-products.service.ts
A-12Người dùng CMSBước 2 — nạp subjectsE-02 → E-09Nạp toàn bộ subject SAPP Ops vào session, tính subject code còn thiếu, session sang bước 2; thông báo "Đã nạp n subjects. Thiếu m subject code."fe/src/ui/components/works/sapp/sapp-24395-products-tool.tsx:275-294; be/libs/modules/src/lib/sapp/common.service.ts:2703-2728
A-13Người dùng CMSBước 2.5 — tick chọn subject code thiếu (hoặc không chọn = tạo tất cả) rồi tạoE-02 → E-10Tạo subject trên SAPP Ops (tên = code) dưới category tương ứng; báo "Tạo thành công x, lỗi y. Còn thiếu z subject."fe/src/ui/components/works/sapp/sapp-24395-products-tool.tsx:296-321, :345-358; be/libs/modules/src/lib/sapp/common.service.ts:2810-2890
A-14Người dùng CMSBước 3 — tạo productsE-02 → E-11BE: duyệt 102 dòng cứng, bỏ qua dòng đã có tên trùng, báo lỗi dòng thiếu category/subject, tạo phần còn lại (tuần tự). ⚠️ FE xử lý kết quả như một session (xem R-33)fe/src/ui/components/works/sapp/sapp-24395-products-tool.tsx:323-343; be/libs/modules/src/lib/sapp/common.service.ts:2900-3000
A-15Người dùng CMSDi chuyển giữa các bước bằng stepper / "Quay lại" / "Tiếp"E-02Chỉ xem được bước n khi session đã đạt bước n-1; khoá khi đang bậnfe/src/ui/components/works/sapp/sapp-24395-products-tool.tsx:250-255, :411-456, :508-527
A-16Người dùng CMSBấm "Bắt đầu lại"E-02Chỉ xoá key trong trình duyệt + state màn; session phía Redis vẫn còn tới khi hết TTLfe/src/ui/components/works/sapp/sapp-24395-products-tool.tsx:126-141, :498-507
A-17Hệ thống (FE)Khi API báo session không tồn tại → reset và hiện "Session đã hết hạn … vui lòng bắt đầu lại từ bước 1"E-02⚠️ Điều kiện so khớp có thể không bao giờ đúng (R-34)fe/src/ui/components/works/sapp/sapp-24395-products-tool.tsx:45, :143-163

4. Dữ liệu ​

Tool không có entity / bảng DB riêng. Trạng thái lưu ở Redis (store Keyv namespace mind-keep, be/libs/services/src/lib/redis/redis.module.ts:19) và ghi thẳng sang hệ thống ngoài.

4a. Khoá Redis ​

Entity / bảngFieldTypeBắt buộcMặc định / enumBằng chứng
Redis sapp:24395:contact-instances:{env}mảng { id, name, reused? }JSON array—Không TTL (không truyền ttl, module không đặt mặc định)be/libs/constants/src/lib/sapp/sapp.constants.ts:231-232; be/libs/modules/src/lib/sapp/common.service.ts:1566-1569; be/libs/services/src/lib/redis/redis.module.ts:18-20
Redis sapp:24395:deal-instances:{env}mảng { id, dealname }JSON array—Không TTL; độ dài mảng dùng làm bộ đếm tên dealbe/libs/constants/src/lib/sapp/sapp.constants.ts:239-240; be/libs/modules/src/lib/sapp/common.service.ts:1624-1650
Redis sapp:24395:product-session:{sessionKey}xem 4cJSON object—TTL 6 giờ, đặt lại mỗi lần ghibe/libs/constants/src/lib/sapp/sapp.constants.ts:57-61; be/libs/modules/src/lib/sapp/common.service.ts:2600-2608
localStorage trình duyệt sapp_24395_product_session_keysessionKeystring——fe/src/data/constants/local-storage.ts:6; fe/src/ui/components/works/sapp/sapp-24395-products-tool.tsx:188-191

4b. Request / response Contact & Deal ​

Entity / bảngFieldTypeBắt buộcMặc định / enumBằng chứng
Body tạo contactname → HubSpot leadin_h_tnipa7107b_39faf8acbcd97440649d6d3d99a5b929 ([TVTS] Họ tên)stringCó—be/libs/interface/src/lib/dto/sapp/sapp-instance.dto.ts:13-14; be/apps/api/src/sapp/sapp.controller.ts:1731-1732, :2097-2099
Body tạo contactemail → emailstringKhôngChỉ gửi khi cóbe/libs/interface/src/lib/dto/sapp/sapp-instance.dto.ts:16-17; be/apps/api/src/sapp/sapp.controller.ts:2100
Body tạo contactphone_number → mkt__phone_numberstringKhông—…sapp-instance.dto.ts:19-20; be/apps/api/src/sapp/sapp.controller.ts:2101-2102
Body tạo contactaddress → dia_chi; province → khuvucsinhsong; d_o_b → d_o_bstringKhông—…sapp-instance.dto.ts:22-29; be/apps/api/src/sapp/sapp.controller.ts:2103-2106
Response contactid, name, reusedstring / string|null / boolean—reused = true khi dùng lại contact có sẵnbe/libs/interface/src/lib/dto/sapp/sapp-instance.dto.ts:59-71
Body tạo dealcontactIdsstring[]Không[]…sapp-instance.dto.ts:33-38; be/apps/api/src/sapp/sapp.controller.ts:2321
Body tạo dealtaiKhoanNhanPhiDichVu → tai_khoan_nhan_phi_dich_vustringKhôngACCA - Kể từ 01/01/2026…sapp-instance.dto.ts:40-44; be/libs/constants/src/lib/sapp/sapp.constants.ts:243-247; be/apps/api/src/sapp/sapp.controller.ts:2080-2083
Body tạo dealcccd_passport → cccd_ho_chieustringKhông—…sapp-instance.dto.ts:46-50; be/apps/api/src/sapp/sapp.controller.ts:2084-2086
Body tạo dealproperties (map tên nội bộ HubSpot → giá trị)objectKhôngKhông có whitelist…sapp-instance.dto.ts:52-56; be/apps/api/src/sapp/sapp.controller.ts:2074-2079
Path:dealCaseenum 14 giá trịCóxem 4dbe/libs/constants/src/lib/sapp/sapp.constants.ts:274-289
Response dealid, dealnamestring / string|null——…sapp-instance.dto.ts:85-91
Deal Lost — số tiền các đợtso_tien_hoc_vien_thanh_toan_lan_1/2/3, phi_dich_vu_dong_lan_1/2string sốKhông'0' khi không gửibe/libs/constants/src/lib/sapp/sapp.constants.ts:253-259; be/apps/api/src/sapp/sapp.controller.ts:2068-2073
Deal Lost — ngày / phương thứcHọc phí: ngay_thanh_toan_hoc_phi_lan_1..3, phuong_thuc_thanh_toan_lan_1..3; Phí DV: ngay_thanh_toan_phi_dv_lan_1, ngay_thanh_toan_phi_lan_2, phuong_thuc_thanh_toan_phi_lan_1/2, loai_phi_dich_vustringKhông— (chỉ FE định nghĩa)fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:148-194
Trường riêng theo case (FE)cbe/cert/becker/gia-han/bao-luu/tu-van-khoa-hoc: deal_id_da_thanh_toan_phi; chuyen-doi-ghi-nhan-doanh-thu: deal_id_bi_lost, deal_id_da_thanh_toan_phi; …-dieu-chinh-giam-original: hoc_phi_goc, amount, goi_khoa_hoc; …-nhan-chuyen-nhuong-tru: goi_khoa_hoc_chuyen_nhuong, amount; …-tang-doanh-thu-deal-tru: khoa_hoc_dem_chuyen_doi, amount. Ba case chuyen-nhuong-hv-chuyen-nhuong, chuyen-doi-khong-ghi-nhan-phi, chuyen-nhuong-hv-nhan-chuyen-nhuong: không có trường riêngstringKhông—fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:203-224

4c. Session bulk product ​

Entity / bảngFieldTypeBắt buộcMặc định / enumBằng chứng
SessionsessionKeystring (UUID do server sinh)—randomUUID()be/libs/modules/src/lib/sapp/common.service.ts:2619
Sessionstepnumber—1 / 2 / 3be/libs/modules/src/lib/sapp/common.service.ts:241-243; be/libs/interface/src/lib/dto/sapp/sapp-instance.dto.ts:260-261
Sessioncategories {name,id}[], subjects {code,id}[]array—subjects = [] ở bước 1be/libs/modules/src/lib/sapp/common.service.ts:244-245, :2621-2622
SessionmissingCategoryNamesstring[]—tính ở bước 1be/libs/modules/src/lib/sapp/common.service.ts:247, :2623
SessioncategoryResults {created[{name,categoryId}], failed[{name,reason}]}object—sau bước 1.5be/libs/modules/src/lib/sapp/common.service.ts:217-233, :2785
SessionmissingSubjectCodes {code,category}[]array—tính ở bước 2be/libs/modules/src/lib/sapp/common.service.ts:192-195, :2713
SessionsubjectResults {created[{code,subjectId,name}], failed[{code,category,reason}]}object—sau bước 2.5be/libs/modules/src/lib/sapp/common.service.ts:197-215, :2876
Sessionresults {created[{name,productId}], skipped[…], failed[…]}object—sau bước 3be/libs/modules/src/lib/sapp/common.service.ts:153-185, :2988
SessioncreatedAtISO string—lúc bắt đầube/libs/modules/src/lib/sapp/common.service.ts:2624
Body bước 1.5categoryNamesstring[]Không[] = tạo tất cảbe/libs/interface/src/lib/dto/sapp/sapp-instance.dto.ts:247-254
Body bước 2.5subjectCodesstring[]Không[] = tạo tất cảbe/libs/interface/src/lib/dto/sapp/sapp-instance.dto.ts:214-221
Danh sách product cứng102 dòng {category, subjectCode, constructionMode, price}: ACCA 49 · CFA 10 · CMA 12 · IFRS 10 · Short courses 18 · CGMA 3const—constructionMode ∈ OFFLINE / ONLINE / BLENDED / HYBRID / LIVE_ONLINE / OTHER; price 3.000.000 … 9.500.000be/libs/constants/src/lib/sapp/sapp-24395-products.constants.ts:14-19, :23-137 (mục :24, :75, :87, :101, :113, :133); enum be/libs/constants/src/lib/sapp/sapp.constants.ts:41-48
Product tạo trên SAPP Opsname = [SAPP-24395][AUTO] {category} {subjectCode} {constructionMode}, category_id, subject_id, construction_mode, price, status = ACTIVE———be/libs/modules/src/lib/sapp/common.service.ts:2928, :2961-2968; be/libs/constants/src/lib/sapp/sapp.constants.ts:51-54

4d. Bảng deal case — giá trị cố định server gắn vào deal ​

Nhãn case: be/libs/constants/src/lib/sapp/sapp.constants.ts:292-314. Bảng cấu hình: be/apps/api/src/sapp/sapp.controller.ts:1739-2032 (prod :1743-1828, staging :1832-1931, dev :1932-2031). Mọi case, mọi môi trường đều có tai_khoan_nhan_phi_dich_vu = ACCA - Kể từ 01/01/2026.

:dealCaseNhãn (xuất hiện trong tên deal)prod & staging: pipeline / dealstagedev: pipeline / dealstageloai_phi_dich_vu — staging & dev (prod: không gửi)Bằng chứng (prod / staging / dev)
lostDeal Lost877604025 / 1316240409836815496 / 1244260910'' (client được ghi đè):1744 / :1833 / :1933
cbeDeal CBE877604025 / 1316240409836815496 / 1244260910Phí đăng ký thi CBE:1750 / :1840 / :1940
certDeal CERT877604025 / 1316240409836815496 / 1244260910Phí tài khoản Cert:1756 / :1847 / :1947
beckerDeal BECKER877604025 / 1316240409836815496 / 1244260910Phí tài khoản Becker:1762 / :1854 / :1954
gia-hanDeal Gia hạn877604025 / 1316240409836815496 / 1244260910Phí gia hạn:1768 / :1861 / :1961
bao-luuDeal Bảo lưu877604025 / 1316240409836815496 / 1244260910Phí bảo lưu:1774 / :1868 / :1968
chuyen-doi-ghi-nhan-doanh-thuDeal Chuyển đổi - Ghi nhận doanh thu882511134 / 1325314701878176910 / 1317215384Chuyển đổi:1780 / :1875 / :1975
chuyen-nhuong-hv-chuyen-nhuongDeal Chuyển nhượng - HV Chuyển nhượng877604025 / 1316240409878343020 / 1317287583Chuyển nhượng:1786 / :1882 / :1982
chuyen-doi-khong-ghi-nhan-phiDeal Chuyển đổi - Không ghi nhận phí882511134 / 1325314701878176910 / 1317215384Không ghi nhận phí:1792 / :1889 / :1989
chuyen-nhuong-hv-nhan-chuyen-nhuongDeal Chuyển nhượng - HV Nhận Chuyển nhượng877604025 / 1316240409878343020 / 1317287583Không ghi nhận phí:1798 / :1896 / :1996
tu-van-khoa-hocDeal Tư vấn khóa học877604025 / 1316240409836815496 / 1244260910Tư vấn khóa học:1804 / :1903 / :2003
chuyen-doi-dieu-chinh-giam-originalOriginal Deal dành cho Chuyển đổi điều chỉnh giảm882511134 / 1325314701878176910 / 1317215384Chuyển đổi:1810 / :1910 / :2010
chuyen-nhuong-hv-nhan-chuyen-nhuong-truDeal trừ dành cho Chuyển nhượng HV nhận chuyển nhượng877604025 / 1316240409878343020 / 1317287583Chuyển nhượng:1816 / :1917 / :2017
chuyen-doi-tang-doanh-thu-deal-truDeal trừ dành cho Deal Chuyển đổi ghi nhận doanh thu882511134 / 1325314701878176910 / 1317215384Chuyển đổi:1822 / :1924 / :2024

Chú thích trong code: pipeline 877604025 = "Pipeline test UAT environment" (:1775), 882511134 = "IT test đóng tiền chuyển đổi học phí" (:1781). Ý nghĩa nghiệp vụ từng case: code chỉ có nhãn — xem Q-01.

5. Rule & validation tìm thấy ​

5a. Contact / Deal ​

IDRule (ngôn ngữ nghiệp vụ)LoạiÁp dụng ởBằng chứngNghi là bug?
R-01Họ tên contact là bắt buộc (FE chặn khi trống; BE validate string bắt buộc)validationA-03fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:277-281; be/libs/interface/src/lib/dto/sapp/sapp-instance.dto.ts:13-14Không
R-02Chỉ gửi sang HubSpot các trường contact có giá trị; FE bỏ trường rỗng sau khi trimđiều kiệnA-03fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:283-288; be/apps/api/src/sapp/sapp.controller.ts:2100-2106Không
R-03CCCD/Hộ chiếu không nằm trên contact mà được ghi lên deal (cccd_ho_chieu)điều kiệnA-06, A-07be/apps/api/src/sapp/sapp.controller.ts:2084-2086; be/libs/interface/src/lib/dto/sapp/sapp-instance.dto.ts:46-50Không
R-04Nếu email contact đã tồn tại trên HubSpot: không báo lỗi mà lấy contact cũ và cập nhật nó bằng dữ liệu vừa nhậpđiều kiệnA-04be/libs/modules/src/lib/hubspot/common.service.ts:636-660⚠️ Observed — ghi đè contact có thật (Q-05)
R-05Danh sách contact/deal của tool chỉ lưu id + tên (không lưu email/SĐT)giới hạnA-02be/libs/modules/src/lib/sapp/common.service.ts:1557-1569, :1642-1650Không
R-06Danh sách contact/deal tách riêng theo từng môi trường (prod / staging / dev), kể cả khi staging và prod dùng chung portalđiều kiệnA-02be/libs/constants/src/lib/sapp/sapp.constants.ts:231-240Không
R-07Deal case không thuộc 14 giá trị → lỗi SAPP_24395_INVALID_DEAL_CASE (13011)validationA-07be/apps/api/src/sapp/sapp.controller.ts:2034-2046; be/libs/constants/src/lib/error-codes/error-codes.constants.ts:594-598Không
R-08Tên deal do server sinh: [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); client không đặt được têncông thứcA-07be/apps/api/src/sapp/sapp.controller.ts:2325-2327; be/libs/modules/src/lib/sapp/common.service.ts:1629-1634Không
R-09Bộ đếm tên deal đọc-rồi-ghi danh sách Redis không khoá: hai lệnh tạo đồng thời có thể trùng số thứ tự và mất một mục trong danh sáchcông thứcA-07be/libs/modules/src/lib/sapp/common.service.ts:1624-1650⚠️ Observed (Q-06)
R-10Thứ tự ưu tiên thuộc tính deal (thấp → cao): số tiền đợt mặc định 0 (chỉ Deal Lost) → giá trị cố định được phép ghi đè (chỉ loai_phi_dich_vu của Deal Lost) → properties client gửi → giá trị cố định được bảo vệ (pipeline, dealstage, …) → taiKhoanNhanPhiDichVu → cccd_passportcông thứcA-07be/apps/api/src/sapp/sapp.controller.ts:2048-2088; be/libs/constants/src/lib/sapp/sapp.constants.ts:253-267Không
R-11Deal Lost: 5 trường số tiền các đợt mặc định 0 nếu client không gửicông thứcA-07be/apps/api/src/sapp/sapp.controller.ts:2068-2073; be/libs/constants/src/lib/sapp/sapp.constants.ts:253-259Không
R-12properties client gửi không có whitelist: mọi tên thuộc tính deal (trừ các khoá cố định của case) đều được chuyển thẳng sang HubSpotgiới hạnA-07be/apps/api/src/sapp/sapp.controller.ts:2074-2079; so sánh tool 26878 có whitelist :2596-2622⚠️ Observed (Q-07)
R-13Pipeline / dealstage / loại phí được server gắn cố định theo (môi trường, case) — xem bảng 4d; 4 case "Chuyển đổi" dùng pipeline riêng; ở dev 3 case "Chuyển nhượng" cũng dùng pipeline riêngđiều kiệnA-07be/apps/api/src/sapp/sapp.controller.ts:1739-2032Không
R-14Ở prod không có loai_phi_dich_vu cố định cho case nào, trong khi staging (cùng portal prod) và dev có — cùng một case trên cùng portal cho ra deal khác nhau tuỳ chọn "prod" hay "staging"; ở prod client còn tự ghi loai_phi_dich_vu được cho mọi caseđiều kiệnA-07be/apps/api/src/sapp/sapp.controller.ts:1744-1827 so với :1833-1930⚠️ Observed (Q-03)
R-15"Tài khoản nhận phí dịch vụ" mặc định ACCA - Kể từ 01/01/2026; FE lấy danh sách lựa chọn từ HubSpot, nếu giá trị đang chọn không còn thì quay về mặc định hoặc lựa chọn đầu tiên; FE luôn gửi trường nàyđiều kiệnA-06fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:95-98, :447-457, :517-523; be/libs/constants/src/lib/sapp/sapp.constants.ts:247Không
R-16Deal Lost: người dùng chọn một loại thanh toán — "Học phí" tối đa 3 đợt hoặc "Phí dịch vụ" tối đa 2 đợt (+ Loại phí dịch vụ); chỉ gửi trường của loại đang chọn và có giá trịđiều kiệnA-06fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:148-194, :501-516Không
R-17Đổi deal case thì xoá các trường riêng đã nhập; CCCD và tài khoản nhận phí được giữđiều kiệnA-06fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:413-432Không
R-18Deal có thể tạo mà không gắn contact nàođiều kiệnA-07fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:598-601; be/libs/modules/src/lib/hubspot/common.service.ts:542-557Không
R-19"staging" không có portal HubSpot riêng — dùng đúng credential prod, tức ghi vào portal HubSpot productionđiều kiệnA-03, A-07be/libs/constants/src/lib/hubspot/hubspot.constants.ts:19-26; be/apps/api/src/sapp/sapp.controller.ts:1829-1831⚠️ Observed (Q-02)
R-20Tab Prod bị tắt trên FE, nhưng route prod phía BE vẫn mở (@Public())giới hạnA-01fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:52-53; be/apps/api/src/sapp/sapp.controller.ts:2190-2191, :2297-2298⚠️ Observed (Q-02)
R-21Danh sách contact / deal trong Redis không bao giờ hết hạn và không có API xoá — bộ đếm tên deal tăng mãigiới hạnA-02, A-07be/libs/modules/src/lib/sapp/common.service.ts:1569, :1650 (không ttl); be/libs/services/src/lib/redis/redis.module.ts:18-20⚠️ Observed (Q-08)
R-22Contact có thể trả name = null; FE tìm deal bằng dealname.toLowerCase() không chặn nullvalidationA-08be/libs/interface/src/lib/dto/sapp/sapp-instance.dto.ts:89-90; fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:839⚠️ Observed (Q-11)

5b. Bulk product creation ​

IDRule (ngôn ngữ nghiệp vụ)LoạiÁp dụng ởBằng chứngNghi là bug?
R-23Tool bulk product không chia môi trường: một cặp base URL + token duy nhất; môi trường thực tế là nơi SAPP_BASE_API_URL đang trỏ tớiđiều kiệnA-10…A-14be/libs/modules/src/lib/sapp/common.service.ts:278-302; be/libs/constants/src/lib/sapp/sapp.constants.ts:16-25⚠️ Observed (Q-04)
R-24Token SAPP Ops là JWT tĩnh trong env_systems, phải thay tay khi hết hạn; thiếu URL hoặc token → SAPP_API_NOT_CONFIGURED (13012). Không dùng auto-login → nền tảngđiều kiệnA-10…A-14be/libs/modules/src/lib/sapp/common.service.ts:283-302; be/libs/constants/src/lib/error-codes/error-codes.constants.ts:599-603Không
R-25Session sống 6 giờ, tính lại từ lần ghi gần nhất (mỗi bước ghi đều đặt lại TTL); hết hạn → SAPP_24395_PRODUCT_SESSION_NOT_FOUND (13017, HTTP 404)trạng tháiA-09…A-14be/libs/modules/src/lib/sapp/common.service.ts:2585-2608; be/libs/constants/src/lib/sapp/sapp.constants.ts:61; be/libs/constants/src/lib/error-codes/error-codes.constants.ts:624-628Không
R-26Nạp category / subject / product theo trang 100 dòng cho tới khi trang cuối < 100 dònggiới hạnA-10, A-12, A-14be/libs/modules/src/lib/sapp/common.service.ts:2496-2518, :2527-2548, :2562-2581Không
R-27Category / subject "thiếu" = tên category / mã subject trong danh sách cứng không khớp (không phân biệt hoa thường, bỏ khoảng trắng đầu cuối) với dữ liệu SAPP Opscông thứcA-10, A-12be/libs/modules/src/lib/sapp/common.service.ts:2640-2696Không
R-28Tạo category / subject thiếu: gửi danh sách rỗng = tạo tất cả; tên / mã không nằm trong danh sách thiếu bị bỏ qua; lỗi từng mục được báo, không dừng cả lượtđiều kiệnA-11, A-13be/libs/modules/src/lib/sapp/common.service.ts:2746-2776, :2823-2867Không
R-29Subject mới được tạo với tên = mã, dưới category tra theo tên từ session; không tìm thấy category → lỗi "Category not found" cho mục đóđiều kiệnA-13be/libs/modules/src/lib/sapp/common.service.ts:2838-2853Không
R-30Tạo subject thiếu (2.5) và tạo product (3) yêu cầu session đã qua bước 2; bước 3 còn yêu cầu session có ít nhất 1 subject; nếu không → SAPP_24395_PRODUCT_SESSION_SUBJECTS_NOT_LOADED (13018, HTTP 409). Tạo category thiếu (1.5) không kiểm tra bướctrạng tháiA-11, A-13, A-14be/libs/modules/src/lib/sapp/common.service.ts:2816-2821, :2905-2910, :2739-2745; be/libs/constants/src/lib/error-codes/error-codes.constants.ts:629-633Không
R-31Bước 3: product có tên trùng (không phân biệt hoa thường) với product đang có trên SAPP Ops mang tiền tố [SAPP-24395][AUTO] → đưa vào "skipped" ("Product already exists"); thiếu category và/hoặc subject → "failed" với lý do tương ứng; lỗi API → "failed"; còn lại → "created". Chạy lại bước 3 không tạo trùngđiều kiệnA-14be/libs/modules/src/lib/sapp/common.service.ts:2921-2985Không
R-32Nếu SAPP Ops trả thành công nhưng không kèm id, mục vẫn được coi là "created" với id rỗng (category / subject / product)validationA-11, A-13, A-14be/libs/modules/src/lib/sapp/common.service.ts:2773-2775, :2864-2866, :2981-2984⚠️ Observed (Q-12)
R-33FE coi kết quả bước 3 là một session: ghi đè state session bằng báo cáo {created, skipped, failed}, lưu sessionKey không xác định vào trình duyệt, đọc data.results (không có) → thông báo "Tạo thành công 0, lỗi 0" và màn bước 3 không hiện kết quảtrạng tháiA-14fe/src/data/services/sapp/sapp-24395-products.service.ts:61-71; fe/src/ui/components/works/sapp/sapp-24395-products-tool.tsx:183-196, :323-343, :821-822; BE trả results be/apps/api/src/sapp/sapp.controller.ts:2558-2563, be/libs/modules/src/lib/sapp/common.service.ts:2987-2989⚠️ Observed — suy từ source, chưa chạy (Q-09)
R-34FE nhận diện "session hết hạn" bằng cách so mã lỗi với chuỗi "SAPP_24395_PRODUCT_SESSION_NOT_FOUND", trong khi BE trả mã "13017" → rất có thể không bao giờ khớp; người dùng chỉ thấy lỗi chung, key cũ không bị xoávalidationA-09, A-17fe/src/ui/components/works/sapp/sapp-24395-products-tool.tsx:45, :145, :230; be/libs/constants/src/lib/error-codes/error-codes.constants.ts:624-628; FE lấy nguyên body lỗi fe/src/data/services/api-service.ts:257-266⚠️ Observed — suy từ source (Q-10)
R-35FE không hiển thị danh sách "skipped" và không hiển thị missingCategoryNames / nút tạo category thiếugiới hạnA-10, A-14fe/src/data/models/sapp-24395-products.interface.ts:35-61 (không có skipped, missingCategoryNames); fe/src/ui/components/works/sapp/sapp-24395-products-tool.tsx:856-912⚠️ Observed (Q-13)
R-36Bước 3 tạo tuần tự, có thể chạy 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útgiới hạnA-14be/apps/api/src/main.ts:104-109; be/libs/constants/src/lib/sapp/sapp.constants.ts:34-38; be/libs/services/src/lib/sapp/sapp.service.ts:45Không
R-37Giá product được tính sẵn trong danh sách cứng: trong cùng category, level cao hơn giá cao hơn, từ 3.000.000 bước 500.000; level không rõ coi như level 1 (theo chú thích code)công thứcA-14be/libs/constants/src/lib/sapp/sapp-24395-products.constants.ts:3-12Không
R-38Màn bulk product cảnh báo "API gốc chặn CORS", chỉ chạy được khi chạy local / expose qua ngrok và sửa SAPP_BASE_API_URLgiới hạnA-10fe/src/ui/components/works/sapp/sapp-24395-products-tool.tsx:384-408⚠️ Observed — BE gọi SAPP Ops server-to-server (be/libs/services/src/lib/sapp/sapp.service.ts:36-45), CORS không áp dụng (Q-14)

Trạng thái & chuyển trạng thái (session bulk product):

text
[Chưa có] --POST sessions (nạp categories, tính missingCategoryNames)--> [step 1]
[step 1|2|3] --categories/create (không kiểm bước; thêm category, step giữ nguyên)--> [step giữ nguyên]
[step 1|2|3] --subjects (nạp lại toàn bộ subjects, tính missingSubjectCodes)--> [step 2]   (giữ results cũ nếu có)
[step ≥2] --subjects/create (thêm subject, step giữ nguyên)--> [step giữ nguyên]
[step ≥2 và subjects ≠ rỗng] --create (tạo products, lưu results)--> [step 3]
[bất kỳ] --6 giờ không ghi--> [Hết hạn → 13017]

Trạng thái hiển thị FE: completedStep = session.step; bước n xem được khi completedStep ≥ n-1 (fe/src/ui/components/works/sapp/sapp-24395-products-tool.tsx:250-255).

6. Quyền, tích hợp, thông báo, job &ZeroWidthSpace;

LoạiChi tiếtBằng chứng
QuyềnCả 18 route đều @Public() → gate thực tế (secret / TOOL_CODES sapp.006, sapp.007) thuộc nền tảngbe/apps/api/src/sapp/sapp.controller.ts:2191, :2211, :2231, :2247, :2262, :2282, :2298, :2338, :2378, :2390, :2402, :2439, :2461, :2479, :2504, :2526, :2551, :2571; fe/src/data/constants/tool-codes.ts:37-38
Tích hợp ngoài — HubSpot, ghiTạo / cập nhật contact, tạo deal (+ liên kết deal→contact). dev → portal dev (SAPP_DEV_HUBSPOT_*); prod và staging → portal HubSpot production (SAPP_PROD_HUBSPOT_*)be/libs/modules/src/lib/hubspot/common.service.ts:47-58, :542-557, :622-661; be/libs/constants/src/lib/hubspot/hubspot.constants.ts:10-30
Tích hợp ngoài — HubSpot, đọcĐịnh nghĩa thuộc tính contact / deal để dựng widget và danh sách "Tài khoản nhận phí" (route của tool Property → nền tảng/tool khác)fe/src/data/services/sapp/sapp-24395.service.ts:82-95; fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:315-327, :692-700
Tích hợp ngoài — SAPP Ops REST, ghiPOST /api/v1/course_categories, POST /api/v1/subjects, POST /api/v1/payment-products trên base URL SAPP_BASE_API_URL (môi trường không xác định từ code — tuỳ giá trị cấu hình; có thể là prod)be/libs/constants/src/lib/sapp/sapp.constants.ts:28-32; be/libs/services/src/lib/sapp/sapp.service.ts:114-150; be/libs/modules/src/lib/sapp/common.service.ts:2759, :2849, :2961
Tích hợp ngoài — SAPP Ops REST, đọcGET course_categories, GET subjects, GET payment-products?name=[SAPP-24395][AUTO]be/libs/services/src/lib/sapp/sapp.service.ts:72-112; be/libs/modules/src/lib/sapp/common.service.ts:2499, :2530, :2565-2569
Cấu hìnhenv_systems: SAPP_BASE_API_URL, SAPP_API_TOKEN, SAPP_{PROD,DEV}_HUBSPOT_ACCESS_TOKEN → đọc qua nền tảngbe/libs/constants/src/lib/env-system/env-system.constants.ts:10-18; be/libs/constants/src/lib/sapp/sapp.constants.ts:22-25
Lưu trạng tháiRedis (danh sách contact/deal không TTL; session 6 giờ) + localStorage (sessionKey)xem §4a
Thông báo (mail / push / MQTT / Discord)Không có. Chỉ popup trong màn (showSuccess / showError)fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:265-271; fe/src/ui/components/works/sapp/sapp-24395-products-tool.tsx:147-160
Job / cronKhông cóGrep 24395 trong be/apps/schedule — không kết quả
Ghi logLỗi mỗi handler được log theo tên handlerví dụ be/apps/api/src/sapp/sapp.controller.ts:2126, :2473

7. Drift — tài liệu nói khác code &ZeroWidthSpace;

IDTài liệu (file + section)Tài liệu nóiCode đang làmBằng chứng
DR-01shared/api-docs/sapp.md:797 §POST …/deals/:dealCase"The per-case property sets within an environment are currently identical"; prod/staging và dev "currently differ only in their pipeline / dealstage ids"Trong cùng môi trường, 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òn có loai_phi_dich_vu khác nhau theo casebe/apps/api/src/sapp/sapp.controller.ts:1780-1826, :1843-1927, :1975-2027
DR-02shared/api-docs/sapp.md:722, :797 §stagingStaging dùng "the same fixed per-case deal properties as prod"Staging có loai_phi_dich_vu theo case; prod không cóbe/apps/api/src/sapp/sapp.controller.ts:1743-1828 so với :1832-1931
DR-03shared/api-docs/sapp.md:832 §Request body propertiesloai_phi_dich_vu là thuộc tính cố định "win over … cannot be overridden"Với Deal Lost client ghi đè được (doc :879 lại nói đúng điều này — mâu thuẫn nội bộ); ở prod không cố định cho case nào nên client ghi đượcbe/libs/constants/src/lib/sapp/sapp.constants.ts:267; be/apps/api/src/sapp/sapp.controller.ts:2058-2067
DR-04shared/api-docs/sapp.md:879 §Deal Lostloai_phi_dich_vu "defaults to empty when omitted"Chỉ đúng ở staging/dev; ở prod không gửi thuộc tính nàybe/apps/api/src/sapp/sapp.controller.ts:1744-1749 vs :1833-1839
DR-05shared/api-docs/sapp.md:745, :771-775 §POST …/contactsResponse { id, name }; không nhắc trường hợp email trùngEmail trùng → cập nhật contact cũ, response có thêm reusedbe/libs/modules/src/lib/hubspot/common.service.ts:622-661; be/libs/interface/src/lib/dto/sapp/sapp-instance.dto.ts:66-70
DR-06shared/api-docs/sapp.md:1153"The session lives in Redis for 6 hours"6 giờ tính từ lần ghi gần nhất (TTL đặt lại mỗi bước)be/libs/modules/src/lib/sapp/common.service.ts:2600-2608
DR-07shared/api-docs/sapp.md:1133-1148 §"The flow the FE should implement"FE nên hiển thị missingCategoryNames và cho tạo category thiếu (bước 1.5) trước khi tạo subjectFE không có URL, service, type hay UI cho bước 1.5fe/src/data/constants/api.ts:439-449; fe/src/data/services/sapp/sapp-24395-products.service.ts:1-82; fe/src/data/models/sapp-24395-products.interface.ts:47-61
DR-08shared/api-docs/sapp.md:1337-1353 §Step 3Response bước 3 là báo cáo {created, skipped, failed}FE khai báo và dùng như session snapshotfe/src/data/services/sapp/sapp-24395-products.service.ts:61-71; fe/src/ui/components/works/sapp/sapp-24395-products-tool.tsx:329-331
DR-09Chú thích code be/apps/api/src/sapp/sapp.controller.ts:1724-1728"These endpoints take no request body… separate prod / dev route"Contact và deal đều nhận body; có thêm route stagingbe/apps/api/src/sapp/sapp.controller.ts:2198-2200, :2261
DR-10Chú thích code be/libs/modules/src/lib/sapp/common.service.ts:236-237Session lưu dưới sessionKey "client-supplied"sessionKey do server sinh (UUID)be/libs/modules/src/lib/sapp/common.service.ts:2619
DR-11Swagger be/apps/api/src/sapp/sapp.controller.ts:2302, :2342, :2406"resolved from the … table (currently identical per case)"; staging "the same fixed per-case property set"Như DR-01 / DR-02như DR-01
DR-12Chú thích FE fe/src/data/services/sapp/sapp-24395.service.ts:17-18Mỗi thao tác nhắm portal prod / devCó 3 môi trường, staging dùng portal prodfe/src/data/constants/api.ts:222-227

8. Câu hỏi cho BA (code không trả lời được) &ZeroWidthSpace;

IDCâu hỏiVì sao cầnChặn bước sau?
Q-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 và pipeline/dealstageViết mục đích / BR cho từng case trong FSCó
Q-02Chọn "Staging" trên màn thực chất ghi contact/deal vào portal HubSpot production (R-19); tab Prod bị tắt ở FE nhưng route prod BE vẫn mở (R-20). Đây là chủ đích (dùng pipeline test trong portal prod) hay rủi ro cần chặn?Quyết định ghi BR hay OQ/rủi ro; cảnh báo cho người dùngCó
Q-03Vì sao prod không gắn loai_phi_dich_vu trong khi staging (cùng portal) và dev có (R-14)? Cố ý hay thiếu sót?Quyết định rule đúng cho prodCó
Q-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)? Có từng chạy vào prod không?Ghi rõ phạm vi ảnh hưởng dữ liệuCó
Q-05Khi email đã tồn tại, tool cập nhật đè contact HubSpot có sẵn (R-04) — kể cả trên portal prod. Có chấp nhận được với contact học viên thật không?Rủi ro dữ liệu khách hàngCó
Q-06Tạo deal đồng thời có thể trùng số thứ tự trong tên và mất mục trong danh sách (R-09). Có cần đảm bảo tên duy nhất không?Cố ý hay bug?Không
Q-07properties không có whitelist (R-12) — người gọi API có thể ghi bất kỳ thuộc tính deal nào. Cố ý (linh hoạt cho tester) hay cần giới hạn như tool 26878?Cố ý hay bug?Không
Q-08Danh sách contact/deal của tool không hết hạn, không có chức năng xoá/reset (R-21). Có cần không?Phạm vi tính năngKhông
Q-09Bước 3 trên FE có hiển thị đúng kết quả không (R-33)? Cần BA/QA chạy thử để xác nhận — nếu đúng như đọc code thì màn luôn báo "Tạo thành công 0, lỗi 0" và mất sessionCố ý hay bug? Ảnh hưởng mô tả hành vi as-builtCó
Q-10Hết hạn session có hiện popup "Session đã hết hạn" không (R-34)? Cần chạy thử xác nhậnCố ý hay bug?Không
Q-11Deal/contact có tên null có làm hỏng ô tìm kiếm lịch sử không (R-22)?Cố ý hay bug?Không
Q-12SAPP Ops có trường hợp trả thành công mà không có id không (R-32)?Cố ý hay bug?Không
Q-13Bước 1.5 (tạo category thiếu) và danh sách "skipped" không có trên FE (R-35, DR-07). Là chủ đích (chưa làm) hay thiếu? Nếu category thiếu thì người dùng xử lý thế nào?Phạm vi FS as-builtCó
Q-14Cảnh báo CORS / ngrok trên màn bulk product (R-38) còn đúng không, vì BE gọi SAPP Ops phía server?Nội dung hướng dẫn sử dụngKhông
Q-15Danh sách 102 product cứng được lấy từ CSV "Đồng bộ Hubspot ↔ Order" — ai là owner, bao giờ cần cập nhật, và quy tắc giá là của nghiệp vụ hay chỉ là dữ liệu test?Viết BR nguồn dữ liệuKhông
Q-16Ai được dùng 2 tool này (role)? Code không phân quyền riêng (→ nền tảng)Mục Actor trong FSKhông
Q-17Mục đích của tên deal có tiền tố [IT TEST] và product [SAPP-24395][AUTO]: để nhận diện/dọn dữ liệu test sau này? Có quy trình dọn không?Vận hànhKhông

9. Nhật ký nguồn đã đọc &ZeroWidthSpace;

File / sectionMục đích
ba/_workflow/templates/feature-inventory/Template.mdTemplate
ba/system-profile.md §3–§6Công thức truy vết, ranh giới ghi
fe/app/works/sapp/tools/sapp-24395/page.tsx, …/sapp-24395-products/page.tsxRoute màn
fe/src/ui/pages/works/sapp/tools/registry.ts:1-110Nhóm / nhãn tool
fe/src/data/constants/tool-codes.ts:30-40Mã tool sapp.006 / sapp.007
fe/src/data/constants/api.ts:221-227, :439-449URL FE
fe/src/data/constants/local-storage.ts:6Khoá localStorage
fe/src/data/services/sapp/sapp-24395.service.ts (toàn bộ)Service FE contact/deal
fe/src/data/services/sapp/sapp-24395-products.service.ts (toàn bộ)Service FE bulk product
fe/src/data/models/sapp-24395-products.interface.ts:1-67Type FE session
fe/src/data/services/api-service.ts:250-268Cách FE nhận body lỗi
fe/src/data/interfaces/response-api.ts:16-24Kiểu lỗi FE
fe/src/ui/components/works/sapp/sapp-24395-tool.tsx:40-1042Màn contact/deal
fe/src/ui/components/works/sapp/sapp-24395-products-tool.tsx:100-580, grep phần còn lạiMàn bulk product
be/apps/api/src/sapp/sapp.controller.ts:1-160, :1720-2690Route, bảng deal case, build properties
be/apps/api/src/main.ts:98-112Timeout server
be/libs/modules/src/lib/sapp/common.service.ts:115-302, :1535-1684, :2489-3008Service contact/deal/session/product
be/libs/modules/src/lib/hubspot/common.service.ts:40-70, :530-700Token theo env, createDeal, createOrReuseContact
be/libs/constants/src/lib/hubspot/hubspot.constants.ts:10-30Staging dùng credential prod
be/libs/constants/src/lib/sapp/sapp.constants.ts:14-61, :220-315Khoá Redis, TTL, enum deal case, nhãn, hằng số
be/libs/constants/src/lib/sapp/sapp-24395-products.constants.ts (toàn bộ, đếm bằng grep)Danh sách 102 product
be/libs/constants/src/lib/env-system/env-system.constants.ts:10-24Khoá env_systems
be/libs/constants/src/lib/error-codes/error-codes.constants.ts:574-648Mã lỗi 13007–13021
be/libs/interface/src/lib/dto/sapp/sapp-instance.dto.ts:1-303DTO
be/libs/services/src/lib/sapp/sapp.service.ts (grep các hàm, :36-45)Client SAPP Ops, timeout
be/libs/services/src/lib/sapp-ops/sapp-ops.service.ts:96-109Xác nhận tool 24395 dùng SappService cũ, không dùng auto-login
be/libs/services/src/lib/redis/redis.module.ts:1-29Store Redis, không TTL mặc định
be/libs/modules/src/lib/cache/cache.service.ts (grep)Hàm set cache
shared/api-docs/sapp.md:1-12, :716-1372, grep reused / TTLĐối chiếu Drift
Grep 24395 toàn repo (trừ ba/); grep ExceptionFilter trong be/Định vị điểm vào; xác nhận không có filter đổi shape lỗi
be/.agents/maps/modules/ (liệt kê)Không có map riêng cho sapp chứa 24395