Skip to content

US-E04: Xem timeline luồng eContract của một deal ​

Thuộc FS: 00-overview.md — SAPP-20603 eContract (Retry · Check luồng · Thống kê lỗi) 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.

Chỉ đọc. Màn này chỉ chạy truy vấn đọc (SELECT) trên DB econtract PRODUCTION — không ghi hệ thống nào, ngoài cache Redis của mind_keep cho mốc job trace cũ nhất.

FieldValue
US IDUS-E04
Role thực hiệnR1 - Người dùng tool (Assumption (OQ về G-01) — OQ-E-04)
PhaseĐã triển khai (as-built @ e77c47a) — sub-tool sapp.012 Check luồng econtract
PriorityN/A — as-built
StatusDraft
NFR liên quanNFR-E-01, NFR-E-02, NFR-E-03, NFR-E-04, NFR-E-05, NFR-E-07 — xem Overview §5
OQ liên quanOQ-E-04, OQ-E-12 — xem Overview §6

1. US Statement ​

text
As a Người dùng tool  [Assumption (OQ về G-01)]
I want nhập HubSpot deal id để xem lại toàn bộ dòng thời gian xử lý hợp đồng điện tử của deal
       (job trace, flow process, hợp đồng, webhook EFY/FPT), checklist các mốc luồng chuẩn và các bước FAIL
So that tôi đối chiếu được thứ tự sự kiện (kể cả với log app) khi điều tra một deal lỗi
       — nguồn: "tester đối chiếu với log app" (2026-09-25-mind-sapp-20603-cau-hoi.md:81-82),
       "cần để đối chiếu khi điều tra" (2026-09-25-sapp-20603-tra-loi.md:230-232)

2. Dependencies & Definition Of Ready ​

N/A — đã triển khai. Dependency runtime:

#Cần sẵn sàngAi cung cấpTrạng thái
D1Khoá SAPP_PROD_ECONTRACT_DB_* trong env_systems — US-P04Admin CMSRuntime
D2User DB có quyền đọc 4 bảng (thiếu bảng / thiếu quyền → cảnh báo, NFR-E-04). Đo 2026-09-25: đọc được cả 4 (2026-09-25-mind-sapp-20603-ket-qua.md)SAPPRuntime
D3Tool sapp.012 truy cập được — US-P02Admin CMSRuntime

3. Business Rules ​

IDRuleÁp dụng ởĐã cover bởi (AC)Nguồn code (Mode B/C)
BR-01Phải nhập deal id (bỏ khoảng trắng); trống → "Thiếu deal id" / "Nhập HubSpot deal id cần kiểm tra."M1 - action A1AC-M1.2fe/src/ui/components/works/sapp/econtract-timeline-tool.tsx:650-659
BR-02Bấm Check ghi deal id lên URL (?dealId=) để tải lại / gửi người khác nguyên trạngM1 - action A1AC-M1.3econtract-timeline-tool.tsx:660-664
BR-03Mở màn với ?dealId= → điền ô và tự tra cứu 1 lầnM1 - triggerAC-M1.3econtract-timeline-tool.tsx:636-648
BR-04Tra cứu chỉ đọc, gộp 4 nguồn của DB econtract PROD: job trace, flow process, hợp đồng (theo deal id) và webhook EFY/FPT (nối qua contract id FPT/EFY lấy từ 3 nguồn trên); không đọc thông tin hợp đồng chi tiếtM1 - action A1AC-M1.1be/libs/modules/src/lib/sapp/common.service.ts:1733-1895 · :1783-1788 · be/apps/api/src/sapp/sapp.controller.ts:212-230
BR-05Mỗi nguồn lấy tối đa 500 dòng mới nhất; chạm trần → cảnh báo "Chạm giới hạn 500 dòng — chỉ hiện các dòng mới nhất"M1 - cảnh báoAC-M1.5be/libs/constants/src/lib/sapp/sapp.constants.ts:157-161 · common.service.ts:1750-1759 · econtract-timeline-tool.tsx:179-188
BR-06Bảng chưa tồn tại / user DB không có quyền đọc → nguồn đó rỗng + cảnh báo, các nguồn khác vẫn hiệnM1 - cảnh báoAC-M1.5common.service.ts:2209-2232 · :1761-1766
BR-07Deal không có contract id FPT/EFY → cảnh báo NO_CONTRACT_ID ("Deal chưa có fpt/efy contract id nên không kéo được webhook…"); truy vấn webhook vẫn chạyM1 - cảnh báoAC-M1.6common.service.ts:1798-1822
BR-08Deal không có job trace và dòng cũ nhất của deal sớm hơn job trace cũ nhất toàn bảng → cảnh báo PREDATES_TRACE ("…không có JOB_TRACE / WEBHOOK là bình thường, không phải mất dữ liệu.")M1 - cảnh báoAC-M1.6common.service.ts:1824-1841 · nguồn ý đồ: 2026-09-25-mind-sapp-20603-cau-hoi.md:39-41
BR-09Timeline sắp mới nhất trước, chỉ theo thời điểm tạo; mọi mốc giờ gắn offset đồng hồ DB; hiển thị theo giờ máy người xem, kèm tên múi giờ DB và mốc job trace cũ nhấtM1 - timelineAC-M1.4common.service.ts:2313-2392 · :2234-2250 · econtract-timeline-tool.tsx:794-805
BR-10request/response của step lấy access token EFY/FPT bị che thành [hidden] ngay ở backend (theo tên step)M1 - chi tiết JOB_TRACEAC-M1.7sapp.constants.ts:169-177 · common.service.ts:2284-2297 · nguồn: 2026-09-25-sapp-20603-tra-loi.md:182-212
BR-11Dữ liệu chi tiết (steps, error, context, payload webhook, link_file_pdf) chỉ hiện dạng text JSON, không link bấm được, không có chức năng xuất fileM1 - chi tiếtAC-M1.7econtract-timeline-tool.tsx:194-200 · :351-390 · nguồn: 2026-09-25-sapp-20603-tra-loi.md:223-231
BR-12Checklist "Các mốc của luồng chuẩn" 6 mốc: (1) flow process CREATE_CONTRACT — SUCCESS = Đạt, NEW / không có = Chưa tới, khác = Lỗi; (2) job CREATE_CONTRACT có ≥ 1 lần SUCCESS (có job nhưng chưa SUCCESS = Lỗi); (3) có bản ghi hợp đồng; (4) webhook ký (EFY DA_KY / FPT completed) — có webhook huỷ (EFY HUY, TU_CHOI / FPT rejected, voided, overdue) mà chưa ký = Lỗi; (5) job hoàn tất (EFY_CONTRACT_COMPLETED / CONTRACT_COMPLETED) có SUCCESS; (6) hợp đồng COMPLETEDM1 - checklistAC-M1.8econtract-timeline-tool.tsx:44-120
BR-13Deal có job huỷ hợp đồng (CANCEL_CONTRACT / EFY_CANCEL_CONTRACT) → dòng nhắc "Deal này có job huỷ hợp đồng — xem timeline bên dưới."M1 - checklistAC-M1.8econtract-timeline-tool.tsx:45 · :853-856
BR-14Cả 4 nguồn đều rỗng → "Không tìm thấy dữ liệu econtract nào cho deal <id>." (cảnh báo nếu có vẫn hiện)M1 - emptyAC-M1.9econtract-timeline-tool.tsx:689-694 · :752-759
BR-15Tóm tắt 5 ô đếm: Job trace, Flow process, Hợp đồng, Webhook, Step FAIL (Step FAIL > 0 tô đỏ); dòng contract id nếu cóM1 - tóm tắtAC-M1.1econtract-timeline-tool.tsx:763-790 · :808-821
BR-16Bảng "Step FAIL (N)" liệt kê mọi step FAIL: job lúc, flow, step, provider, errorM1 - bảng Step FAILAC-M1.8econtract-timeline-tool.tsx:394-430 · :858
BR-17Timeline lọc bật / tắt theo từng nguồn (JOB_TRACE, FLOW_PROCESS, CONTRACT, WEBHOOK_EFY / WEBHOOK_FPT); tiêu đề hiện số dòng đang hiện / tổngM1 - bộ lọcAC-M1.4econtract-timeline-tool.tsx:670-684 · :862-884 · common.service.ts:2333-2382

4. Design &ZeroWidthSpace;

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

text
[Hub → Check luồng econtract]  ·  [US-E03 link, US-E06 tab mới, link chia sẻ: ?dealId= → tự tra cứu]
  ↓ nhập deal id, bấm Check / Enter
[M1: Check luồng econtract]
  ├─ có dữ liệu → cảnh báo (nếu có) · tóm tắt · checklist 6 mốc · Step FAIL · Timeline (lọc theo nguồn, mở chi tiết)
  ├─ 4 nguồn rỗng → "Không tìm thấy dữ liệu econtract nào cho deal …"
  └─ lỗi API → hộp lỗi "Không tải được timeline econtract"

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

Màn M1 - Check luồng econtract &ZeroWidthSpace;

FieldValue
Figma frameN/A
Trigger vào mànHub → "Check luồng econtract" (/works/sapp/tools/econtract-timeline), hoặc link ?dealId=
Mô tả ngắn"Dựng lại dòng thời gian xử lý hợp đồng của một deal: job trace, flow process, hợp đồng và webhook EFY/FPT, sắp từ mới đến cũ. Chỉ đọc, không thay đổi dữ liệu."
UI States &ZeroWidthSpace;
StateKhi nàoHiển thịFigma frame
DefaultVừa vào màn (không có ?dealId=)Ô "HubSpot deal id" + nút "Check"N/A
LoadingĐang tra cứuNút "Đang kiểm tra…", ô nhập bị khoá; kết quả cũ bị xoáN/A
Has dataCó ≥ 1 dòng ở 1 nguồnCảnh báo (nếu có) → 5 ô đếm → dòng múi giờ / job trace cũ nhất → contract id → checklist 6 mốc → Step FAIL (nếu có) → TimelineN/A
Empty4 nguồn rỗng"Không tìm thấy dữ liệu econtract nào cho deal <id>."N/A
ErrorAPI lỗiHộp lỗi "Không tải được timeline econtract" + thông điệp (mã) (vd 13060, 13001)N/A
DisabledĐang tra cứuÔ nhập và nút Check bị khoáN/A
Fields &ZeroWidthSpace;
FieldRequiredTypeDefaultFormatValidationError MessageVisibilityDepends On
HubSpot deal idYesText (bàn phím số trên mobile)Trống, hoặc ?dealId=Tự doBỏ khoảng trắng, không rỗng (BR-01); BE cũng bỏ khoảng trắng"Thiếu deal id" / "Nhập HubSpot deal id cần kiểm tra."Always; khoá khi đang tra cứu-
(hiển thị) Timeline — at-Datetime-YYYY-MM-DD HH:mm:ss giờ máy--Mỗi dòngBR-09
(hiển thị) source · event · status · detail-Text-source: JOB_TRACE / FLOW_PROCESS / CONTRACT / WEBHOOK_<provider>--Mỗi dòng-
(hiển thị) Chi tiết dòng-JSON textĐóngJOB_TRACE: steps (at, kind, provider, step, status, message / error, request / response), error, context; webhook: payload--Khi mở dòngBR-10, BR-11
Filter / Search / Sort (chỉ màn List/Report — xóa nếu không phải) &ZeroWidthSpace;
LoạiTheo fieldKiểuDefaultNotes
FiltersourceNút bật / tắt từng nguồn (multi)Tất cả bậtTắt nguồn → nút gạch ngang; đặt lại khi Check deal mới (BR-17)
Search---N/A — không có ô tìm
Sortcreated_atCố địnhMới nhất trướcKhông đổi được (BR-09)
Pagination---N/A — tối đa 500 dòng / nguồn (BR-05)
Actions &ZeroWidthSpace;
A1 - Check &ZeroWidthSpace;
ItemDescription
TriggerBấm "Check", Enter, hoặc mở link ?dealId=
BehaviorKiểm tra BR-01 → ghi deal id lên URL (BR-02) → gọi GET /api/v1/sapp/prod/econtract/deals/<dealId>/timeline. Chỉ đọc DB econtract PRODUCTION (4 SELECT, BR-04); ghi duy nhất là cache Redis mind_keep cho mốc job trace cũ nhất (TTL 1 ngày, NFR-E-03)
Success ResultHiển thị theo UI State Has data / Empty

Error cases:

CaseExpected Handling
Ô trốngHộp lỗi "Thiếu deal id", không gọi API
Thiếu cấu hình DBHộp lỗi "Không tải được timeline econtract" … (13001)
Lỗi dựng timelineHộp lỗi Failed to build econtract timeline for this deal (13060)
Một bảng thiếu / không quyềnKhông lỗi — cảnh báo theo bảng (BR-06)
A2 - Lọc theo nguồn &ZeroWidthSpace;
ItemDescription
TriggerBấm nút nguồn cạnh tiêu đề Timeline
BehaviorẨn / hiện dòng của nguồn đó (FE, không gọi API)
Success ResultTiêu đề "Timeline (hiện/tổng) — mới nhất ở trên" cập nhật

Error cases:

CaseExpected Handling
N/A-
A3 - Mở chi tiết dòng / step &ZeroWidthSpace;
ItemDescription
TriggerBấm một dòng timeline; trong JOB_TRACE bấm "Xem request/response" của step
BehaviorMở / đóng khối JSON text (FE, không gọi API); step token hiện [hidden]
Success ResultChi tiết hiện ngay dưới dòng

Error cases:

CaseExpected Handling
Step không có request / responseKhông có nút mở chi tiết cho step đó
Acceptance Criteria của màn M1 &ZeroWidthSpace;
AC-M1.1 - Tra cứu chỉ đọc và tóm tắt &ZeroWidthSpace;
gherkin
Given deal D có dữ liệu ở job trace, flow process và hợp đồng trên DB econtract prod
When người dùng nhập D và bấm "Check"
Then hệ thống chỉ chạy truy vấn đọc, không đổi dữ liệu prod
And hiện 5 ô đếm Job trace, Flow process, Hợp đồng, Webhook, Step FAIL đúng số dòng mỗi nguồn
And hiện contract id của deal nếu có

Maps to:

  • Business Rule: BR-04, BR-15
  • Field/Action: A1
AC-M1.2 - Thiếu deal id &ZeroWidthSpace;
gherkin
Given ô deal id trống
When người dùng bấm "Check"
Then hiện hộp lỗi "Thiếu deal id" — "Nhập HubSpot deal id cần kiểm tra."
And không có lời gọi API

Maps to:

  • Business Rule: BR-01
AC-M1.3 - Deal id trên URL &ZeroWidthSpace;
gherkin
Given người dùng tra cứu deal 123 bằng nút "Check"
When lượt tra cứu bắt đầu
Then URL có ?dealId=123
And mở lại / gửi URL đó cho người khác thì màn tự điền 123 và tự tra cứu một lần

Maps to:

  • Business Rule: BR-02, BR-03
AC-M1.4 - Thứ tự, múi giờ và lọc nguồn &ZeroWidthSpace;
gherkin
Given timeline của deal D có dòng ở nhiều nguồn
When kết quả hiện ra
Then dòng mới nhất ở trên, theo thời điểm tạo
And giờ hiển thị theo máy người xem, kèm "đồng hồ DB econtract: <múi giờ>" và mốc job trace cũ nhất
When người dùng tắt nguồn FLOW_PROCESS
Then các dòng FLOW_PROCESS bị ẩn và tiêu đề đổi thành "Timeline (hiện/tổng)"

Maps to:

  • Business Rule: BR-09, BR-17
  • Field/Action: A2
AC-M1.5 - Cảnh báo giới hạn và bảng thiếu &ZeroWidthSpace;
gherkin
Given bảng econtract_webhook_logs không đọc được do thiếu quyền, và job trace của deal có đủ 500 dòng
When người dùng tra cứu
Then hiện cảnh báo "econtract_webhook_logs — User DB không có quyền SELECT trên bảng này"
And cảnh báo "econtract_job_traces — Chạm giới hạn 500 dòng — chỉ hiện các dòng mới nhất"
And các nguồn còn lại vẫn hiển thị bình thường

Maps to:

  • Business Rule: BR-05, BR-06
AC-M1.6 - Cảnh báo thiếu contract id / deal cũ hơn trace &ZeroWidthSpace;
gherkin
Given deal D chưa có contract id FPT/EFY và không có job trace, dòng cũ nhất của D sớm hơn job trace cũ nhất toàn bảng
When người dùng tra cứu D
Then hiện cảnh báo NO_CONTRACT_ID và PREDATES_TRACE với câu tiếng Việt tương ứng

Maps to:

  • Business Rule: BR-07, BR-08
AC-M1.7 - Che token và không xuất file &ZeroWidthSpace;
gherkin
Given job trace CREATE_CONTRACT có step "STEP 2 - getEfyAccessToken"
When người dùng mở chi tiết step đó
Then request và response hiện "[hidden]"
And mọi payload / steps chỉ hiện dạng text JSON, link_file_pdf không bấm được
And trên màn không có nút xuất file

Maps to:

  • Business Rule: BR-10, BR-11
  • Field/Action: A3
AC-M1.8 - Checklist mốc và Step FAIL &ZeroWidthSpace;
gherkin
Given deal D có flow process CREATE_CONTRACT SUCCESS, job CREATE_CONTRACT SUCCESS, 1 hợp đồng NEW, webhook EFY HUY và chưa có webhook DA_KY
When kết quả hiện ra
Then mốc 1, 2, 3 là Đạt; mốc 4 "Webhook ký hợp đồng" là Lỗi với ghi chú "Nhận EFY HUY"; mốc 5, 6 là Chưa tới
And nếu D có job CANCEL_CONTRACT / EFY_CANCEL_CONTRACT thì hiện "Deal này có job huỷ hợp đồng — xem timeline bên dưới."
And nếu có step FAIL thì hiện bảng "Step FAIL (N)" với job lúc, flow, step, provider, error

Maps to:

  • Business Rule: BR-12, BR-13, BR-16
AC-M1.9 - Không có dữ liệu &ZeroWidthSpace;
gherkin
Given deal D không có dòng nào ở cả 4 nguồn
When người dùng tra cứu D
Then hiện "Không tìm thấy dữ liệu econtract nào cho deal D."

Maps to:

  • Business Rule: BR-14
Negative AC / Edge Cases của màn M1 &ZeroWidthSpace;
IDTình huốngHành vi mong đợi
EC-M1.1Mất kết nối DB / lỗi truy vấn không phải thiếu bảng / thiếu quyềnHộp lỗi 13060; kết quả cũ đã bị xoá
EC-M1.2Deal có > 500 job traceChỉ 500 dòng mới nhất + cảnh báo TRUNCATED (BR-05); cảnh báo bật cả khi đúng 500 dòng
EC-M1.3Deal id có ký tự đặc biệtFE mã hoá deal id trong URL API; BE bỏ khoảng trắng; không kiểm tra định dạng — truy vấn thường ra rỗng (BR-14)
EC-M1.4Mở 2 tab / nhiều người cùng tra cứuMỗi lượt quét toàn bảng trên prod (NFR-E-03); không giới hạn tần suất
EC-M1.5Refresh trang sau khi CheckDeal id còn trên URL → màn tự tra cứu lại (BR-03)
EC-M1.6Deal có nhiều hợp đồng / cả webhook EFY và FPTMọi contract id được gom; webhook nối theo cả hai loại id

5. Cross-feature AC &ZeroWidthSpace;

AC-X.1 - Thấy kết quả của lần Retry &ZeroWidthSpace;

gherkin
Given US-E02 vừa Retry deal D và cron econtract đã chạy lại
When người dùng tra cứu D ở Check luồng
Then timeline có thêm dòng JOB_TRACE mới nhất ở trên cho lần chạy lại đó

Maps to:

  • REL-03 (Be Affected - Cron econtract-payment + EFY/FPT)

AC-X.2 - Thiếu cấu hình env_systems &ZeroWidthSpace;

gherkin
Given env_systems thiếu khoá bắt buộc SAPP_PROD_ECONTRACT_DB_*
When người dùng tra cứu
Then hộp lỗi mã 13001

Maps to:

  • REL-02 (Affects - Cấu hình env_systems)