Skip to content

SAPP-23954 Ticket Owner (Query & Refresh tickets · Check snapshot) - 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-T0x-<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: mô tả hành vi code tại commit e77c47a, dựng từ feature-inventory-23954-20260930.md (đã qua Gate R1). Chưa gọi thử API hay chạy màn nào — mọi hành vi là đọc từ source.

FieldValue
Doc IDFS-SAPP-23954
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 BRD../../brd/brd-as-built-v0.1-20260930.md
Related Impact MatrixN/A — Mode B (as-built), không có Impact Analysis

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

Nhóm tool SAPP-23954 "Ticket Owner" gồm 2 sub-tool dưới /works/sapp/tools: sapp.008 "Query & Refresh tickets" (truy vấn ticket HubSpot, "làm mới" hàng loạt thuộc tính cap_nhat_owner bằng cách ghi rỗng rồi ghi lại giá trị cũ, tự kiểm tra thay đổi sau 15 giây, xem lịch sử làm mới) và sapp.009 "Check snapshot" (chạy thử chỉ-đọc chuỗi điều kiện gán owner cho 1 ticket tại mọi mốc cap_nhat_owner đổi giá trị). Cả hai chạy trên portal HubSpot Dev hoặc Prod.

1.1 Bối cảnh &ZeroWidthSpace;

[Assumption — OQ-T-01] Chú thích code và mô tả trên màn tool nói việc "reset + khôi phục" cap_nhat_owner nhằm kích hoạt lại automation HubSpot bắt sự kiện đổi giá trị thuộc tính này, và snapshot mô phỏng logic gán ticket owner theo class owner ở repo gốc sapp-platform-lms-be. Vấn đề nghiệp vụ cụ thể (ticket nào bị kẹt không có owner, vì sao, ai phát hiện) chưa được BA xác nhận (inventory Q-01, Gate R1 G-05). Không có tài liệu gốc trong shared/external/sapp/** cho ticket này.

1.2 Mục tiêu &ZeroWidthSpace;

[Assumption — OQ-T-01] Chưa có câu trả lời của BA về mục tiêu / KPI. Giả định làm việc: giúp người vận hành gán lại owner cho ticket HubSpot bằng cách chạy lại automation mà không phải sửa tay từng ticket, và chẩn đoán vì sao logic gán owner dừng với một ticket cụ thể.

1.3 In Scope &ZeroWidthSpace;

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

  • Màn /works/sapp/tools/sapp-23954 (sapp.008): truy vấn ticket (subtool 1), làm mới cap_nhat_owner hàng loạt (subtool 2), tự kiểm tra thay đổi sau 15 giây (subtool 3), lịch sử làm mới + "Tải lại" từng dòng.
  • Màn /works/sapp/tools/sapp-23954-snapshot (sapp.009): check snapshot (subtool 4).
  • 12 route API /api/v1/sapp/{prod|dev}/sapp-23954/tickets/* (6 chức năng × 2 portal).
  • Dữ liệu: thuộc tính ticket / contact HubSpot được đọc/ghi; danh sách lịch sử làm mới trên Redis.

1.4 Out Of Scope &ZeroWidthSpace;

  • Cổng truy cập tool (ẩn / khoá / mã bí mật theo code sapp.008 / sapp.009) → FS nền tảng US-P02.
  • Cơ chế @Public() / guard toàn cục → FS nền tảng NFR-P-01.
  • Lấy access token HubSpot theo portal từ env_systems → FS nền tảng US-P04.
  • Hai lookup dùng lại của nhóm HubSpot: danh sách pipeline ticket và tuỳ chọn của property cap_nhat_owner → FS HubSpot US-H04, US-H01.
  • Automation phía HubSpot được "kích hoạt lại" và logic gốc gán owner theo class owner ở repo sapp-platform-lms-be — ngoài repo, không truy vết được.
  • Ứng dụng mobile (app/): không có màn nào cho nhóm này.

1.5 Roles And Permissions &ZeroWidthSpace;

Role IDRole NameDescriptionPermission Summary
R1Người dùng toolAssumption (OQ về G-01) — người được mở sub-tool sapp.008 / sapp.009 trong workspace SAPP. Chưa xác nhận là đội nào (inventory Q-02)Màn: theo cổng ẩn/khoá của nền tảng (US-P02). API: không cần đăng nhập — xem NFR-T-01
R2Hệ thống (FE / BE)Hành động tự động: tải lookup khi mở panel, ghi lịch sử sau làm mới, đếm ngược 15 giây rồi tự kiểm traKhông áp dụng

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

text
[Workspace SAPP › menu "SAPP 23954 - Ticket Owner"]  (cổng tool: US-P02)
  ├─ "Query & Refresh tickets" (sapp.008)
  │     ↓ chọn tab Dev / Prod (mặc định Dev)
  │   [US-T01 Truy vấn ticket] ── chọn ticket ──→ [US-T02 Làm mới cap_nhat_owner] (ghi HubSpot, cả PROD)
  │     │                                              ├─ BE ghi 1 dòng lịch sử / ticket thành công ──→ [US-T04]
  │     │                                              └─ ≥1 ticket thành công ──→ đếm ngược 15s ──→ [US-T03 Kiểm tra thay đổi]
  │     └─ nút "Lịch sử làm mới" ──→ [US-T04 Lịch sử làm mới + "Tải lại"]
  └─ "Check snapshot" (sapp.009)
        ↓ chọn tab Dev / Prod, nhập Ticket ID
      [US-T05 Check snapshot] (chỉ đọc)

Link flow nếu có:

  • N/A — không có Mermaid / Figma flow; sơ đồ trạng thái chi tiết ở inventory §5.

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ở toolUS-P01Affects-US-T01, US-T05 — điểm vào mànMenu "SAPP 23954 - Ticket Owner" và 2 mục sapp.008 / sapp.009 do hub nền tảng hiển thị
REL-02Nền tảng — Khoá toolUS-P02Affects-Toàn bộ màn của FS nàyTool sapp.008 / sapp.009 đang ẩn / khoá thì người dùng không vào được màn (chỉ chặn ở giao diện)
REL-03Nền tảng — Cấu hình env_systemsUS-P04Affects-Mọi action gọi HubSpotToken HubSpot của portal prod / dev lấy từ env_systems; thiếu token → lỗi (cách lỗi hiện ra khác nhau theo action, xem DR-T-03, DR-T-04)
REL-04HubSpot — Xem pipelineUS-H04Affects-US-T01.M1 — bộ lọc "Pipeline"Danh sách checkbox Pipeline lấy từ lookup pipeline ticket của nhóm HubSpot
REL-05HubSpot — Get propertyUS-H01Affects-US-T01.M1 — bộ lọc "Cập nhật owner"; nhãn cap_nhat_owner ở US-T03, US-T04Tuỳ chọn và nhãn hiển thị của cap_nhat_owner lấy từ lookup property ticket của nhóm HubSpot (bỏ tuỳ chọn ẩn)
REL-06Automation HubSpot bắt sự kiện đổi cap_nhat_owner (ngoài hệ thống)N/A — ngoài repoBe AffectedAutomation phía HubSpotUS-T02.M1 — action "Làm mới"; US-T03 kết quảLàm mới tạo cặp thay đổi rỗng → giá trị cũ để automation chạy lại; kết quả automation được US-T03 đo sau 15 giây
REL-07Logic gốc gán owner theo class owner (repo sapp-platform-lms-be)N/A — ngoài repoAffects-US-T05 — mọi bước kiểm traHằng số pipeline / enum / điều kiện được sao chép cứng từ repo gốc; repo gốc đổi mà bản sao không đổi → snapshot sai (OQ-T-12, OQ-T-13)

Mã REL-XX được tham chiếu ở phần Cross-feature AC của từng file US bằng trường Maps to.

4. User Story Index &ZeroWidthSpace;

US IDTên User StoryFileRolePriorityStatus
US-T01Truy vấn ticket theo pipeline / cap_nhat_owner / owner / ngàyUS-T01-truy-van-ticket.mdR1, R2N/A — as-builtDraft
US-T02Làm mới cap_nhat_owner hàng loạtUS-T02-lam-moi-owner.mdR1, R2N/A — as-builtDraft
US-T03Tự kiểm tra thay đổi owner sau khi làm mớiUS-T03-kiem-tra-thay-doi.mdR2 (kết quả cho R1)N/A — as-builtDraft
US-T04Xem và tải lại lịch sử làm mớiUS-T04-lich-su-lam-moi.mdR1N/A — as-builtDraft
US-T05Check snapshot một ticketUS-T05-check-snapshot.mdR1N/A — as-builtDraft

Status Draft = as-built chờ Gate R2. Độ phủ hành động inventory: A-01…A-05 → US-T01; A-06, A-07 → US-T02; A-08 → US-T03; A-09, A-10 → US-T04; A-11, A-12 → US-T05.

5. Non-functional Requirements &ZeroWidthSpace;

IDRequirementApplies To (US/màn/API)Acceptance Criteria
NFR-T-01Quyền API: cả 12 route /api/v1/sapp/{prod|dev}/sapp-23954/tickets/* không yêu cầu đăng nhập / permission, kể cả route ghi hàng loạt lên HubSpot prod. Chi tiết và rủi ro: NFR-P-01 của FS nền tảng (không lặp lại ở đây). Nguồn: be/apps/api/src/sapp/sapp.controller.ts:268, :286, :322, :340, :374, :392, :420, :435, :464, :481, :516, :534US-T01…US-T05, mọi APIGọi từng route không kèm token → không bị từ chối vì thiếu xác thực. Ý đồ: OQ-T-02
NFR-T-02Môi trường: chỉ có 2 portal prod và dev (chọn qua đoạn path); không có route staging cho nhóm này. Mặc định tab trên màn là Dev. Nguồn: be/apps/api/src/sapp/sapp.controller.ts:267-534; fe/src/ui/components/works/sapp/sapp-23954-tool.tsx:58-61, :913US-T01…US-T05Mở màn → tab Dev đang chọn; chỉ có 2 tab Dev / Prod
NFR-T-03⚠️ Observed Khối lượng một lượt làm mới: không giới hạn số ticket; BE xử lý tuần tự từng ticket, mỗi ticket 1 lần đọc + 2 lần ghi HubSpot, tất cả trong một request HTTP; không chia batch, không giới hạn tần suất. Rủi ro timeout / rate-limit HubSpot với lượt lớn. Nguồn: be/libs/interface/src/lib/dto/sapp/sapp-23954-ticket.dto.ts:114-120; be/libs/modules/src/lib/sapp/common.service.ts:925-987US-T02 (API refresh), US-T03 (API verify cũng tuần tự)Hiện trạng — chưa có ngưỡng. Cố ý hay thiếu sót: OQ-T-08
NFR-T-04Kích thước trang truy vấn: mặc định 100 ticket / trang, tối đa 200 (giới hạn của HubSpot Search); màn luôn xin 100. Nguồn: be/libs/constants/src/lib/sapp/sapp-23954.constants.ts:27-31; fe/src/ui/components/works/sapp/sapp-23954-tool.tsx:66US-T01Truy vấn trên màn trả ≤ 100 dòng / lần; gọi API với limit > 200 bị từ chối bởi validate
NFR-T-05Lưu trữ lịch sử làm mới: trên Redis, key riêng mỗi portal, hạn 7 ngày tính cho cả danh sách và được gia hạn lại mỗi lần ghi (làm mới hoặc "Tải lại"); không có bảng DB, không giới hạn số dòng. Nguồn: be/libs/constants/src/lib/sapp/sapp-23954.constants.ts:38-42; be/libs/modules/src/lib/sapp/common.service.ts:1062-1066, :1261-1265US-T02, US-T04Sau 7 ngày không có lần ghi nào → danh sách của portal đó trống. Ý đồ: OQ-T-11
NFR-T-06Dữ liệu nhạy cảm: email / số điện thoại contact trong snapshot chỉ hiển thị trên màn, không có chức năng xuất file / sao chép; màn ghi rõ "không được xuất ra file (theo quy định bảo mật)". Nguồn: be/libs/interface/src/lib/dto/sapp/sapp-23954-ticket.dto.ts:340-348; fe/src/ui/components/works/sapp/sapp-23954-snapshot-tool.tsx:287-301US-T05Màn snapshot không có nút xuất / tải file. Tối thiểu hoá dữ liệu: OQ-T-17
NFR-T-07Logging: lỗi từng ticket (làm mới, kiểm tra), lỗi ghi lịch sử, lỗi đọc lịch sử thuộc tính trong snapshot được ghi log BE; không có audit ai đã chạy làm mới. Không có thông báo mail / push / MQTT. Nguồn: be/libs/modules/src/lib/sapp/common.service.ts:961-963, :979-981, :991-993, :1068-1070, :775-777US-T02, US-T03, US-T04, US-T05Log BE có dòng tổng processed=… skipped=… failed=… mỗi lượt làm mới

6. Open Questions &ZeroWidthSpace;

IDQuestionOwnerDue DateStatusBlocks (US)
OQ-T-01Mục đích nghiệp vụ của SAPP-23954: vấn đề gì khiến cần "reset + khôi phục" cap_nhat_owner? Automation HubSpot nào được kích hoạt lại, kỳ vọng kết quả (gán owner theo class owner)? (inventory Q-01, G-05)BATrước Gate R2OpenUS-T01…US-T05 (US Statement "So that")
OQ-T-02Ai được dùng 2 tool này? API không cần đăng nhập ("temporary") kể cả route ghi hàng loạt lên HubSpot prod — cố ý hay rủi ro cần chặn? (inventory Q-02, G-01, G-02)BATrước Gate R2OpenUS-T01…US-T05 (Role)
OQ-T-03Chạy làm mới trên prod là mục đích chính hay chỉ để thử trên dev? Có cần bước xác nhận riêng / mạnh hơn cho prod (hiện chỉ 1 hộp xác nhận chung có ghi tên portal)? (inventory Q-03, G-03)BATrước Gate R2OpenUS-T02
OQ-T-04FS tách theo sub-tool màn hay subtool nghiệp vụ? (inventory Q-04)BA—Closed — R2 chốt tách theo subtool nghiệp vụ (5 US)—
OQ-T-05Bộ lọc owner: giá trị "noOwner = true" lại nghĩa là "có owner" — cố ý (giữ tương thích) hay bug đặt tên? (inventory Q-05, R-02)BA + BETrước Gate R2OpenUS-T01
OQ-T-06Lọc ngày tạo tính trọn ngày theo UTC — lệch 7 giờ so với giờ VN (ticket tạo 00:00–06:59 giờ VN bị tính vào ngày trước). Cố ý hay bug? (inventory Q-06, R-03)BA + FETrước Gate R2OpenUS-T01
OQ-T-07Giá trị cap_nhat_owner nào hợp lệ để làm mới? Hiện làm mới bất kỳ giá trị khác rỗng (kể cả "Cập nhật thành công" / "Cập nhật thất bại") — có cần giới hạn? (inventory Q-07)BA—OpenUS-T02 (không chặn)
OQ-T-08Có cần giới hạn số ticket mỗi lượt làm mới? Hiện không giới hạn, tuần tự trong 1 request. Lượt lớn nhất từng chạy? Có từng timeout / bị HubSpot rate-limit? (inventory Q-08, NFR-T-03)BA + BETrước Gate R2OpenUS-T02
OQ-T-09Khi bước ghi lại thất bại, ticket bị bỏ rỗng cap_nhat_owner trên HubSpot (kể cả prod), không thử lại / hoàn tác. Đã từng xảy ra? Ai xử lý? Cố ý hay thiếu sót? (inventory Q-09, R-12)BA + BETrước Gate R2OpenUS-T02
OQ-T-10Kiểm tra thay đổi không xác định được "có thay đổi" cho ticket chưa có owner lúc làm mới mà sau đó được gán owner (màn gửi baseline owner = "không có" → kết quả "không xác định"). Đây có phải chính ca nghiệp vụ cần đo? Cố ý hay bug? (inventory Q-10, R-21, G-06)BA + FETrước Gate R2OpenUS-T03
OQ-T-11Lịch sử làm mới giữ bao lâu là đúng ý đồ: 7 ngày kể từ lần ghi cuối của cả danh sách (hiện tại) hay 7 ngày mỗi dòng? Có cần giới hạn số dòng / lưu bền (DB)? (inventory Q-11, R-17)BA—OpenUS-T04 (không chặn)
OQ-T-12Điều kiện rule "(cond1 hoặc cond2) hoặc cond3 hoặc (cond1 và có mã lớp HV)" sao chép từ repo gốc: vế cuối thừa (mã lớp không ảnh hưởng kết quả). Logic gốc có đúng như vậy, hay bản sao sai (vd gốc là "cond2 và mã lớp")? (inventory Q-12, R-26)BA + BETrước Gate R2OpenUS-T05
OQ-T-13Danh sách pipeline, giá trị cap_nhat_owner, 36 giá trị phân loại dịch vụ cứng trong code, sao chép nguyên văn từ sapp-platform-lms-be. Ai đồng bộ khi repo gốc đổi? Bản sao còn khớp không (ngày sao chép)? (inventory Q-13, R-23)BA + BETrước Gate R2OpenUS-T05
OQ-T-14Snapshot giả định contact gắn ticket không đổi theo thời gian và luôn lấy contact đầu tiên — chấp nhận được khi ticket có nhiều contact? (inventory Q-14, R-27)BA—OpenUS-T05 (không chặn)
OQ-T-15Đổi tab Dev / Prod làm mất toàn bộ trạng thái (bộ lọc, kết quả, lựa chọn, đếm ngược kiểm tra đang chạy) trong khi chú thích code nói "mỗi tab giữ riêng" — cố ý hay bug? (inventory Q-15, R-33, DR-09)BA + FE—OpenUS-T01, US-T03, US-T05 (không chặn)
OQ-T-16Đọc lịch sử lỗi trả mã 13022 ("Failed to query SAPP-23954 tickets" — mã của truy vấn) thay vì mã riêng — cố ý hay sót? (inventory Q-16)BE—OpenUS-T04 (không chặn)
OQ-T-17Snapshot có cần hiển thị email / SĐT contact không — có đủ tối thiểu hoá dữ liệu? (inventory Q-17, NFR-T-06)BA—OpenUS-T05 (không chặn)
OQ-T-18Mới ở R3 (không có trong inventory, suy từ code): ở mốc lịch sử của snapshot, id pipeline là id tại thời điểm đó nhưng tên pipeline luôn tra theo pipeline hiện tại → khối Ticket có thể hiện tên không khớp id (việc đánh giá dùng id nên không sai kết luận). Cố ý (tên chỉ để hiển thị) hay bug? Nguồn: be/libs/modules/src/lib/sapp/common.service.ts:747-761, :448-452BE—OpenUS-T05 (không chặn)

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

IDTài liệu nóiCode đang làm (bằng chứng file:dòng)Ảnh hưởngOwner quyết
DR-T-01shared/api-docs/sapp.md:395, :425, :472, :508-509, :579 (ví dụ): giá trị cap_nhat_owner là "Đã cập nhật" / "Chưa cập nhật" (inventory DR-01)Hằng số code có 5 giá trị khác hẳn: "Xử lý ticket thông thường", "Xử lý ticket chào mừng", "Cập nhật thành công", "Cập nhật thất bại", "Rotate Ticket Owner" — be/libs/constants/src/lib/sapp/sapp-23954.constants.ts:88-94Người đọc doc hiểu sai giá trị thật; US-T01, US-T02, US-T05BE (sửa shared/api-docs/)
DR-T-02shared/api-docs/sapp.md:692 (ví dụ snapshot): mốc "now" với "Xử lý ticket chào mừng", pipeline 877604025 → sẽ chạy (inventory DR-02)Pipeline "chào mừng" hợp lệ ở prod chỉ có 898314365; với 877604025 code dừng ở bước pipeline — be/libs/constants/src/lib/sapp/sapp-23954.constants.ts:118-127; be/libs/modules/src/lib/sapp/common.service.ts:512-524Ví dụ doc mâu thuẫn rule; US-T05BE
DR-T-03shared/api-docs/sapp.md:485, :614: thiếu token ở refresh / verify ném lỗi HUBSPOT_ENV_NOT_CONFIGURED (12001) — "systemic failure (e.g. missing token)" (inventory DR-03)Thiếu token làm lỗi từng ticket và bị bắt trong vòng lặp → trả 201 với mọi ticket vào "lỗi" (refresh) hoặc "không đọc được" (verify); tra tên owner lỗi cũng bị nuốt — be/libs/modules/src/lib/sapp/common.service.ts:923, :926-986, :1305-1319, :1346-1393; be/libs/modules/src/lib/hubspot/common.service.ts:47-58Người gọi API không phân biệt được "portal chưa cấu hình" với "từng ticket lỗi"; US-T02, US-T03BE
DR-T-04shared/api-docs/sapp.md:714: thiếu token ở check-snapshot ném HUBSPOT_ENV_NOT_CONFIGURED (12001) (inventory DR-04)Lời gọi đầu tiên (đọc ticket) bắt mọi lỗi → trả 201 với 1 mốc "Lấy chi tiết ticket" trạng thái "Lỗi", không ném 12001 — be/libs/modules/src/lib/sapp/common.service.ts:697-741US-T05 hiển thị "Sẽ không chạy" thay vì hộp lỗi cấu hìnhBE
DR-T-05Swagger be/apps/api/src/sapp/sapp.controller.ts:466-467 (reload): chỉ ghi lại tên ticket và cap_nhat_owner (inventory DR-05)Code còn ghi đè owner "sau" (doc sapp.md:529 thì đúng) — be/libs/modules/src/lib/sapp/common.service.ts:1254-1257US-T04BE
DR-T-06Swagger be/apps/api/src/sapp/sapp.controller.ts:423-424 (refresh-history): mỗi dòng có ticketId, ticketName, prevCapNhatOwner, latestCapNhatOwner (inventory DR-06)Còn có id, owner trước / sau, refreshedAt — be/libs/interface/src/lib/dto/sapp/sapp-23954-ticket.dto.ts:173-213US-T04BE
DR-T-07shared/api-docs/sapp.md:491: "TTL 7 days" không nói phạm vi (inventory DR-07)TTL áp cho cả danh sách, gia hạn lại mỗi lần ghi; từng dòng không có hạn riêng — be/libs/modules/src/lib/sapp/common.service.ts:1062-1066, :1261-1265US-T04, NFR-T-05BE
DR-T-08FE type fe/src/data/models/sapp-23954.interface.ts:15, :19, :210; fe/src/data/models/sapp-hubspot.interface.ts:11; fe/src/data/constants/api.ts:452-466: tên ticket / cap_nhat_owner là chuỗi bắt buộc; môi trường gồm cả staging (inventory DR-08)BE trả được null; BE không có route staging cho 23954. UI hiện không có tab staging nên chưa gây lỗi — be/libs/interface/src/lib/dto/sapp/sapp-23954-ticket.dto.ts:74-84; be/apps/api/src/sapp/sapp.controller.ts:267-534Rủi ro tiềm ẩn nếu thêm tab staging; US-T01FE
DR-T-09Chú thích fe/src/ui/components/works/sapp/sapp-23954-tool.tsx:955: "mỗi tab giữ riêng bộ lọc, kết quả, lựa chọn" (inventory DR-09)Panel dựng lại khi đổi tab → trạng thái tab cũ bị huỷ — fe/src/ui/components/works/sapp/sapp-23954-tool.tsx:957; fe/src/ui/components/works/sapp/sapp-23954-snapshot-tool.tsx:662US-T01, US-T03, US-T05 (OQ-T-15)FE

7. References &ZeroWidthSpace;

  • BRD: ../../brd/brd-as-built-v0.1-20260930.md
  • Impact Matrix: N/A — Mode B
  • Solution Decision: N/A — Mode B
  • Figma: N/A — as-built, không có Figma
  • API Spec: shared/api-docs/sapp.md § "SAPP-23954 tool" (dòng 361–717) — có Drift, xem §6b
  • Code đã đọc (Mode B/C) @ e77c47a:
    • fe/src/ui/components/works/sapp/sapp-23954-tool.tsx, fe/src/ui/components/works/sapp/sapp-23954-snapshot-tool.tsx
    • fe/src/data/services/sapp/sapp-23954.service.ts, fe/src/data/constants/api.ts:451-466
    • be/apps/api/src/sapp/sapp.controller.ts:252-548
    • be/libs/modules/src/lib/sapp/common.service.ts:300-1407 (phần 23954)
    • be/libs/interface/src/lib/dto/sapp/sapp-23954-ticket.dto.ts, be/libs/constants/src/lib/sapp/sapp-23954.constants.ts
    • be/libs/constants/src/lib/error-codes/error-codes.constants.ts:649-682
    • Chi tiết: feature-inventory-23954-20260930.md §9
  • Meeting Notes / Q&A: gate-r1-summary-20260930.md · project-decisions.md

Template Conformance Check &ZeroWidthSpace;

Quét mục lục từng file US so với ba/_workflow/templates/fs/User-Story.md (2026-09-30): Metadata (US ID · Role · Phase · Priority · Status · NFR liên quan · OQ liên quan) · 1. US Statement · 2. Dependencies & DoR · 3. Business Rules (có cột "Đã cover bởi (AC)" và "Nguồn code") · 4. Design (a. flow; b. mỗi màn: Figma frame · UI States · Fields · Filter/Search/Sort · Actions · Acceptance Criteria G/W/T · Negative AC / Edge Cases) · 5. Cross-feature AC (Maps to REL-xx).

US fileSection thiếuTrạng thái
US-T01(đủ) — 1 màn M1 là màn List, có bảng Filter/Search/Sort; 11 BR / 10 AC / 8 EC; Priority = N/A (as-built)✅
US-T02(đủ) — M1, M2; Filter/Search/Sort ghi N/A (không phải màn List); 12 BR / 10 AC / 11 EC✅
US-T03(đủ) — M1; Filter/Search/Sort ghi N/A; 9 BR / 6 AC / 5 EC✅
US-T04(đủ) — M1 (modal List, có bảng Filter/Search/Sort); 8 BR / 4 AC / 6 EC✅
US-T05(đủ) — M1 (có bảng Filter/Search/Sort), M2 (N/A); 15 BR / 12 AC / 11 EC✅

Kiểm thêm: mọi BR có ≥ 1 AC / EC / NFR ở cột "Đã cover bởi"; mọi BR có "Nguồn code"; ⚠️ Observed chỉ nằm ở AC/EC, không thành BR, và đều có OQ ở §6; mọi action ghi dữ liệu nêu hệ thống + môi trường, US-T02 có dòng ⚠️ Ghi PROD; Dependencies & DoR = N/A — đã triển khai; mọi A-01…A-12 của inventory có trong ≥ 1 US (§4).