Cảnh báo trên NolimitHub đang lặp đi lặp lại, thiếu ID, và làm nhiễu kênh: cùng một bill mà activity của TKQC vẫn liệt kê (nhưng gate không tìm thấy) tạo ra cảnh báo mới mỗi chu kỳ quét — che mất cảnh báo thật và bào mòn độ tin. Bài này đặc tả ba thay đổi mỏng: nhét ID bill vào cảnh báo, đánh dấu bill đã xác nhận không còn trên FB, và chống bắn lại cảnh báo cho bill đã đánh dấu — mà không phải xây lại worker quét bill.
Tài liệu được tổ chức theo trình tự PRD chuẩn: thông tin chung trước, sau đó là bối cảnh và mục tiêu, rồi mới đi vào personas, luồng nghiệp vụ, business rules, và cuối cùng là acceptance criteria + quy trình bàn giao. Phần 6 (Bàn giao) liệt kê những điểm CTO cần chốt trước khi code — đặc biệt là cơ chế đánh dấu cần thống nhất với các doc liên quan, không đẻ khái niệm "ghost bill" song song.
01 · Thông tin chung
Bốn trường meta cần đọc đầu tiên
Trước khi đọc bất kỳ phần nào khác, hãy đối chiếu bốn ô dưới đây để chắc rằng bạn đang đọc đúng phiên bản tài liệu và đúng feature. Feature ID là khoá nối tới ticket, Status cho biết tài liệu đã sẵn sàng để code hay chưa.
Hệ thống: Dashboard thuê TKQC (module billing / risk) + luồng quét bill từ activity của TKQC rồi đối chiếu sang gate (worker check bill, liên quan Service_Check_RRS_V3). Bảng dữ liệu chính: ad_account_bills. Kênh cảnh báo: NolimitHub (nội bộ kỹ thuật) + module Audit & Log có sẵn.
Quy mô: Cải thiện luồng cảnh báo cho trường hợp activity báo có bill ID nhưng gate không tìm thấy: (1) nhét ID bill vào nội dung cảnh báo để actionable; (2) thêm cơ chế đánh dấu bill đã xác nhận không còn trên FB; (3) chống gửi lại cảnh báo cho bill đã đánh dấu. KHÔNG xây lại worker quét bill, KHÔNG đổi luồng cào bill bình thường. Cơ chế đánh dấu phải thống nhất với nhãn terminal (Removed/Expired) ở cao_lai_trang_thai_bill_pending.md và bộ canonical ở dong_bo_dung_trang_thai_funded_bill.md — không đẻ hai khái niệm "ghost bill" song song.
02 · Bối cảnh
Hai nỗi đau hiện tại — và đâu là nguyên nhân gốc
Hệ thống có một luồng kiểm tra bill làm việc theo hai nguồn dữ liệu của Facebook: activity (nhật ký hoạt động/giao dịch của TKQC — hệ thống đọc và phát hiện có một bill với ID nào đó phát sinh) và gate (cổng hóa đơn — nơi fetch chi tiết bill để lấy số tiền, trạng thái, phương thức thanh toán…). Sau khi biết ID từ activity, hệ thống sang gate để lấy chi tiết bill đó.
Vấn đề: có những bill activity báo là CÓ (có ID), nhưng khi sang gate fetch lại KHÔNG tìm thấy — bill đó không còn trên gate của TKQC nữa. Phần lớn các trường hợp này là bill đã không còn tồn tại trên FB. Khi gặp lệch này, hệ thống bắn một cảnh báo về NolimitHub. Hệ quả là hai nỗi đau:
- Cảnh báo không actionable — thiếu ID bill: nội dung cảnh báo trên NolimitHub hiện không kèm ID của bill cần kiểm tra. Người trực nhận cảnh báo nhưng không biết phải mở/fetch bill nào để xác minh → phải tự dò, mất thời gian, dễ bỏ qua.
- Cảnh báo lặp vô tận — không có cơ chế đánh dấu: vì bill này vẫn còn được activity liệt kê, mỗi lần worker quét lại là lại phát hiện "có bill ID này nhưng gate không thấy" → lại bắn đúng cảnh báo đó. Cùng một bill "ghost" tạo ra cảnh báo lặp đi lặp lại, làm nhiễu kênh, che mất các cảnh báo thật sự cần xử lý và khiến người trực dần phớt lờ.
Tính năng cần bổ sung: (1) bổ sung ID bill (kèm ID TKQC/workspace) vào nội dung cảnh báo để actionable; (2) một cơ chế đánh dấu bill đã xác nhận "activity có ID nhưng gate không tìm thấy → không còn tồn tại trên FB"; (3) chống lặp: bill đã đánh dấu thì không bắn lại cảnh báo về NolimitHub ở các lần quét sau, dù activity vẫn còn liệt kê ID đó.
03 · Mục tiêu & Chỉ số
Bốn chỉ số đo lường thành công
Phạm vi & cách làm — chốt rõ để dev không làm quá tay: chỉ cải thiện nội dung cảnh báo + thêm đánh dấu/chống lặp cho đúng trường hợp bill lệch activity↔gate. KHÔNG xây lại worker quét bill, KHÔNG đổi luồng cào bill bình thường, KHÔNG xoá row bill. Cơ chế đánh dấu phải thống nhất với nhãn terminal "biến mất trên FB" đã định ở cao_lai_trang_thai_bill_pending.md.
Sau khi làm xong: mỗi cảnh báo bill lệch activity↔gate trên NolimitHub kèm đủ ID bill + TKQC để người trực mở ra kiểm tra ngay; một bill "ghost" (đã xác nhận không còn trên FB) chỉ cảnh báo một lần rồi thôi, không spam lại mỗi chu kỳ quét. Cảnh báo còn lại trên kênh đều là case cần xử lý thật. Release đầu: cảnh báo có ID; có cơ chế đánh dấu (tự động khi xác nhận gate không tìm thấy, không phải lỗi tạm thời); bill đã đánh dấu bị bỏ qua, không bắn lại cảnh báo.
04 · Personas
Ai làm gì với feature này
Feature có ba persona active + ba persona hỗ trợ. Lưu ý: kênh NolimitHub là nội bộ kỹ thuật — người nhận cảnh báo là dev/kỹ thuật, không phải end-user; cảnh báo cần đủ thông tin để mở ra fetch/đối chiếu, không cần "thân thiện".
05 · Luồng nghiệp vụ cốt lõi
Sáu bước, theo thứ tự
Luồng nghiệp vụ phân nhánh ở Bước 3: nếu fetch được thì xử lý bình thường; nếu không thì phải phân biệt nguyên nhân (Bước 4) trước khi quyết định bắn cảnh báo và đánh dấu. Lưu ý Bước 5 — chỉ bắn cảnh báo khi bill chưa được đánh dấu; nếu đã đánh dấu thì bỏ qua hoàn toàn.
Nếu Bước 4 kết luận "lỗi tạm thời / diện rộng" — vd rate limit, timeout, token-cookie chết, gate đang lỗi nhiều bill — thì không đánh dấu, không kết luận ghost; chỉ retry chu kỳ sau. Nếu là lỗi kỹ thuật thật (gate down, credential chết kéo dài) → cảnh báo NolimitHub theo kênh lỗi kỹ thuật, không trộn với cảnh báo ghost.
06 · Edge cases
Năm tình huống dev bắt buộc xử lý
FB Agency lỗi rất nhiều — bên cạnh luồng chính ở Mục 05, đây là năm tình huống biên mà cách xử lý phải được code rõ ràng, không để mặc định. Nhầm chỗ này có thể vừa đánh dấu sai, vừa che mất bill thật.
Sáu edge case phụ cần xử lý gọn: (1) Không xoá row — đánh dấu chỉ cập nhật trạng thái/cờ, không DELETE khỏi ad_account_bills (giữ lịch sử & debug). (2) Phân biệt đúng loại giao dịch trong activity — activity có nhiều loại mục, lọc đúng loại để không cảnh báo nhầm cho mục vốn dĩ không có trên gate. (3) Scope theo (TKQC + ID bill) — đánh dấu phải gắn đúng cặp; không để đánh dấu một bill làm im cảnh báo của bill khác trùng ID ở TKQC khác. (4) Idempotent — nhiều worker chạy song song chỉ một cảnh báo, một lần đánh dấu. (5) TKQC bị xoá/disabled/rời workspace — dừng quét, không cảnh báo, không văng lỗi. (6) Đánh dấu tay — cân nhắc cho người trực đánh dấu tay một bill để dừng cảnh báo ngay (chốt ở Bước 0).
07 · User stories
Bảng tham chiếu nhanh
Sáu user story định nghĩa scope chức năng của release đầu. P0 là phải có để release; P1/P2 có thể chậm hơn nhưng vẫn nằm trong cùng feature, không tách ticket.
| ID | Vai trò | Muốn / Để | Ưu tiên |
|---|---|---|---|
| US-01 | Người trực NolimitHub | Cảnh báo bill kèm ID bill + ID TKQC (và workspace, lý do) — mở ra fetch/đối chiếu đúng bill ngay, không phải tự dò. | P0 |
| US-02 | Hệ thống | Đánh dấu bill đã xác nhận gate không tìm thấy (không còn trên FB) — phân biệt "đã xử lý" với "bất thường mới", làm cơ sở chống lặp. | P0 |
| US-03 | Hệ thống | Không bắn lại cảnh báo NolimitHub cho bill đã đánh dấu — tránh spam dù activity vẫn liệt kê ID. | P0 |
| US-04 | Dev / CTO | Khi gate lỗi diện rộng (auth/gate down) vẫn được cảnh báo kỹ thuật — không bị che mất sự cố thật vì tưởng là ghost bill. | P1 |
| US-05 | Hệ thống | Bỏ đánh dấu / xử lý lại khi bill xuất hiện lại trên gate — dữ liệu phản ánh đúng khi FB hiện lại bill. | P2 |
| US-06 | Người trực | (Tuỳ chọn) Đánh dấu tay một bill là ghost để dừng cảnh báo — tự xác minh xong thì tắt nhiễu ngay, không chờ chu kỳ. | P2 |
08 · Business rules
Cấu trúc luồng quyết định cảnh báo
Trước khi đọc danh sách rule, nhìn vào sơ đồ dưới: cảnh báo không phải là "mỗi lần lệch là một event" — mà là kết quả của một chuỗi quyết định bắt đầu từ "đây có thật là ghost không" và kết thúc ở "đã đánh dấu chưa". Bảy thành phần trong sơ đồ tương ứng với cách quyết định bắn/suppress cảnh báo được tính tại thời điểm gate trả 404.
không đánh dấu
không mass-mark
fetch bình thường
chưa → bắn
+ ghi log
Chín rule dưới đây là chuẩn mực để dev đối chiếu khi viết logic và QA đối chiếu khi viết test:
- Cảnh báo phải actionable: mọi cảnh báo bill lệch activity↔gate phải kèm tối thiểu ID bill (transaction/tracking id), ID TKQC, workspace, thời điểm, lý do (gate không tìm thấy). Có link mở thẳng bill/TKQC càng tốt.
- Chỉ đánh dấu khi xác nhận "không tìm thấy" thật: chỉ khi gate trả 404 / không có bill (không phải lỗi tạm thời). Lỗi tạm thời → retry, KHÔNG đánh dấu, KHÔNG kết luận ghost.
- Phân biệt ghost lẻ vs sự cố diện rộng (P0 an toàn): nếu gate fail hàng loạt / lỗi xác thực → cảnh báo kỹ thuật NolimitHub, KHÔNG mass-mark. Chỉ đánh dấu khi gate vẫn fetch được các bill khác bình thường.
- Đánh dấu trên chính bill, không xoá: đánh dấu = cập nhật trạng thái/cờ trên row bill, scope theo (TKQC + ID bill); không DELETE. Nhãn terminal "không còn trên FB" thống nhất với cao_lai_trang_thai_bill_pending.md (Removed/Expired) và nằm trong bộ canonical ở dong_bo_dung_trang_thai_funded_bill.md — không đẻ biến thể mới.
- Chống lặp: bill đã đánh dấu → các lần quét sau bỏ qua, KHÔNG bắn lại cảnh báo NolimitHub, kể cả khi activity vẫn liệt kê ID đó. Dedupe theo bill.
- Bill quay lại: nếu bill đã đánh dấu mà sau đó gate fetch được → bỏ đánh dấu và cập nhật trạng thái thực; không kẹt vĩnh viễn.
- Idempotent: nhiều chu kỳ/nhiều worker → tối đa một cảnh báo + một lần đánh dấu cho cùng bill; không trùng, không mâu thuẫn.
- Ghi log đầy đủ: việc bắn cảnh báo, việc đánh dấu (cái gì/ai đánh dấu, khi nào, lý do) và việc suppress cảnh báo đều ghi vào nhật ký — tận dụng module Audit & Log có sẵn để truy vết.
- Một nguồn sự thật cho "bill biến mất": re-crawl Pending và check activity↔gate dùng chung cơ chế/nhãn đánh dấu, không tạo hai khái niệm ghost song song.
09 · Acceptance & Test cases
Chín tiêu chí nghiệm thu
Để feature được coi là "xong", cả chín tiêu chí dưới phải pass trên staging. Đối chiếu trực tiếp khi viết test:
- Cảnh báo bill lệch activity↔gate trên NolimitHub kèm ID bill + ID TKQC (+ workspace, lý do); người trực mở ra fetch đúng bill.
- Bill xác nhận gate không tìm thấy (404, không phải lỗi tạm thời) được đánh dấu, không bị xoá row.
- Bill đã đánh dấu → các chu kỳ quét sau không bắn lại cảnh báo NolimitHub (dù activity vẫn còn ID đó).
- Lỗi tạm thời (rate limit/timeout/token-cookie chết) → không đánh dấu, không cảnh báo "ghost"; có retry.
- Gate lỗi diện rộng / auth → vẫn cảnh báo kỹ thuật NolimitHub và KHÔNG mass-mark.
- Bill đã đánh dấu nhưng xuất hiện lại trên gate → bị bỏ đánh dấu và cập nhật trạng thái thực.
- Đánh dấu scope đúng (TKQC + ID bill); không làm im cảnh báo của bill khác.
- Nhãn terminal & xử lý thống nhất với doc cao_lai/funded; không phát sinh biến thể nhãn mới.
- Mọi cảnh báo/đánh dấu/suppress được ghi log đầy đủ.
Ma trận test case
Test case chia ba nhóm: luồng chính, edge case, và TC bổ sung do dev tự dựng. Mỗi cột dưới là một nhóm:
- → TC-01 bill X 404 → 1 cảnh báo kèm ID + đánh dấu
- → TC-02 quét lại nhiều chu kỳ → không cảnh báo mới
- → TC-03 bill Y fetch được → xử lý bình thường, không cảnh báo
- → TC-04 429/timeout → không đánh dấu, không "ghost"
- → TC-05 gate down diện rộng → cảnh báo kỹ thuật, không mass-mark
- → TC-06 bill quay lại → bỏ đánh dấu, cập nhật thực
- → TC-07 scope: A bị mark, B trùng ID ở TKQC khác vẫn cảnh báo
- → TC-08 hai worker → một cảnh báo, một lần đánh dấu
- → TC-09 token/cookie chết → xoay hoặc bỏ qua an toàn
- → TKQC bị xoá/disabled/rời workspace khi đang chờ check
- → Lọc nhầm loại mục activity (mục không phải bill)
- → Ngưỡng số lần thử/khoảng thời gian trước khi kết luận ghost
- → (Nếu làm) đánh dấu tay của người trực
10 · Quy trình bàn giao
Bước 0 — chốt sáu điểm trước khi code
Trước khi viết dòng code đầu tiên, sáu câu hỏi dưới phải có câu trả lời từ CTO. Đừng đoán — đoán sai ở Bước 0 thì refactor cả luồng cảnh báo, và còn dễ tạo nhãn terminal mâu thuẫn với các doc liên quan.
-
1
Cơ chế đánh dấuDùng trạng thái terminal thống nhất với cao_lai (Removed/Expired) hay thêm cờ riêng "đã-cảnh-báo/suppressed" (hoặc cả hai)? Đặt ở ad_account_bills thế nào để hai luồng dùng chung.
-
2
Ngưỡng kết luận ghostThử N lần trong M giờ rồi mới kết luận "không tồn tại" và đánh dấu — tránh đánh dấu non khi lỗi tạm thời.
-
3
Tiêu chí phân biệt "gate down diện rộng" vs "ghost lẻ"Dựa vào tỉ lệ not-found trong một batch / loại lỗi (auth vs 404) — chốt mức cụ thể.
-
4
Nội dung cảnh báoNgoài ID bill + TKQC + workspace + lý do, có cần thêm link mở thẳng / mức độ nghiêm trọng không.
-
5
Bill quay lại — auto bỏ đánh dấuTự bỏ đánh dấu khi gate fetch được lại — xác nhận hành vi mong muốn.
-
6
Đánh dấu tay (US-06)Có làm kênh cho người trực đánh dấu tay 1 bill để tắt nhiễu ngay không?
Phụ thuộc bắt buộc & deploy gate
Thống nhất cơ chế/nhãn "bill biến mất trên FB" với cao_lai_trang_thai_bill_pending.md và bộ canonical ở dong_bo_dung_trang_thai_funded_bill.md — nên làm/đồng bộ cùng đợt. Sau khi xong + UAT trên staging, dev chuẩn bị Test Report kèm bằng chứng thực tế: (1) ảnh/log một cảnh báo NolimitHub có ID bill + TKQC mở ra fetch đúng; (2) demo chạy lại worker nhiều chu kỳ ⇒ bill ghost không cảnh báo lại; (3) demo gate lỗi diện rộng vẫn cảnh báo kỹ thuật (không bị chống-lặp che mất); (4) demo bill quay lại được bỏ đánh dấu. Họp demo/review trực tiếp với CTO duyệt nội dung cảnh báo, cơ chế đánh dấu/chống lặp, ranh giới ghost-lẻ vs sự cố-diện-rộng và độ ổn định.
CHỈ KHI CTO APPROVE mới deploy Production. Không có shortcut, không có ngoại lệ. Luồng cảnh báo đụng tới kênh tin cậy duy nhất của đội kỹ thuật — sai chống-lặp một bước là che mất sự cố thật hàng loạt.
Đó là toàn bộ đặc tả của FT-BILL-GHOST-ALERT-01. Tài liệu được sắp xếp theo trình tự PRD chuẩn — nếu sau khi đọc xong bạn vẫn lăn tăn ở một mục nào, hãy quay lại đúng mục đó thay vì dò lại từ đầu. Mười mục, mười câu hỏi: bạn đang vướng câu nào?
— Last reviewed: 04/06/2026. Phản hồi gửi về owaf.fakku@gmail.com.