Đồng Bộ & Hiển Thị Đúng Trạng Thái "Funded" Của Hóa Đơn
Bill thanh toán bằng credit / quỹ trả trước được Facebook gắn nhãn "Funded", nhưng hệ thống đang hiển thị "Thành công" (Paid).
Nguyên nhân: 2 nguồn dữ liệu FB (API / cookie) trả ra 2 bộ status khác nhau nhưng đang dùng chung một cột payment_status, sync API ghi đè dần nhãn cookie.
Tài liệu này tách cột để 2 path ghi độc lập, reader ưu tiên cookie.
1. Thông Tin Chung
Metadata cơ bản, scope của RFC.
| Mã tính năng (Feature ID) | FT-BILL-FUNDED-STATUS-01 |
| Người yêu cầu (Owner / PO) | CTO |
| Độ ưu tiên | P1 · High — sai trạng thái tài chính hiển thị cho người dùng + làm hỏng tính năng rủi ro Funded bills on starred. |
| Trạng thái | Draft |
| Ngày tạo | 03/06/2026 |
| Ngày cập nhật cuối | 03/06/2026 |
| Hệ thống | Dashboard thuê TKQC — module workspaces / billing / risk. Bảng chính: ad_account_bills. |
| Quy mô | Tách trạng thái crawl về thành 2 cột riêng (API FB / cookie), 2 path ghi độc lập, reader ưu tiên cột cookie. Kèm migration tách dữ liệu cột cũ. |
2. Bối Cảnh & Mục Tiêu
Hai nguồn FB cho ra 2 bộ status khác nhau, vì sao nhãn cookie đang bị xoá dần.
2.1. Bối cảnh (Context)
Bill thanh toán bằng credit / quỹ trả trước được Facebook gắn nhãn "Funded", nhưng hệ thống đang hiển thị "Thành công" (Paid). Ví dụ: bill 6ET7ZP9N52 (TKQC 1683821496292014) — billing_hub hiển thị Funded, DB lưu payment_status='Paid'.
Nguyên nhân — 2 nguồn dữ liệu FB cho ra 2 bộ status khác nhau:
Hai nguồn crawl trả 2 bộ status khác nhau
| Nguồn crawl | Trả status | Phân biệt được Funded? |
|---|---|---|
API FB (GET /act_{id}/transactions) |
COMPLETED / FAILED / PROCESSING |
Không — Funded vẫn = COMPLETED |
Cookie (crawl billing_hub.php) |
Paid / Funded / Pending / Failed + nhãn tiếng Việt |
Có |
Sync hiện tại chỉ dùng API FB, map COMPLETED → Paid / còn lại → Unpaid nên không bao giờ tạo ra Funded → re-sync vô ích vì input API không hề có thông tin Funded.
Funded 4 row, Đã thanh toán, Đang chờ, Pending, Không thành công, Failed) nằm lẫn cùng một cột payment_status với kết quả API. Mỗi lần sync API ghi đè chính cột đó → đang xoá dần nhãn cookie.
2.2. Mục tiêu (Objectives)
/dashboard/billing, /finance/bills, /admin/risk/funded-bills-on-starred.3. Luồng Nghiệp Vụ & Sơ Đồ Hoạt Động
Actor và các edge cases khi triển khai.
3.1. Các đối tượng tham gia
3.2. Xử lý các kịch bản lỗi (Edge cases)
EC-01 Cookie / token chết ▾
1683821496292014 đang disabled, token đã chết (test Graph API trực tiếp → fail). Crawl cookie phải dùng cookie + proxy của VIA còn quyền trên BM, không phụ thuộc token TKQC.
EC-02 billing_hub đổi cấu trúc HTML ▾
EC-03 Thống nhất nhãn ▾
EC-04 Lệch timezone / tiền tệ ▾
tracking_id.
4. Chi Tiết Yêu Cầu Chức Năng
User stories & business rules.
4.1. Danh sách chức năng (User Stories)
| ID | Vai trò | Muốn | Để | Ưu tiên |
|---|---|---|---|---|
US-01 |
Người dùng workspace | Bill trả bằng credit hiện đúng "Funded" | Biết đúng bản chất giao dịch | P1 |
US-02 |
Super Admin | Trang Funded bills on starred đếm / liệt kê đúng | Soát đúng rủi ro tài chính | P1 |
US-03 |
Hệ thống | Crawl API & cookie không ghi đè nhau | Không mất dữ liệu khi sync | P0 |
4.2. Quy tắc nghiệp vụ (Business Rules)
Trạng thái từ API FB và từ cookie lưu vào 2 cột riêng; mỗi path chỉ ghi cột của mình, không đụng cột còn lại.
Giá trị hiển thị = cột cookie nếu có, không thì rơi về cột API (cookie ?? api). Funded chỉ tồn tại ở cột cookie.
Hai cột dùng chung bộ giá trị (Paid, Unpaid, Funded, Pending, Failed + nhãn tiếng Việt tương ứng); không phát sinh biến thể mới.
5. Thiết Kế Kỹ Thuật Sơ Bộ
Database 2 cột, writer 2 path, reader ưu tiên cookie, tài liệu tham chiếu.
app/... nằm ở repo product (không phải repo tài liệu này); số dòng gần đúng, dev mở repo code đối chiếu.
5.1. Database — thêm 2 cột trạng thái
| Cột | Type | Mục đích |
|---|---|---|
payment_status_api | text | Kết quả map từ API FB (Paid / Unpaid). |
payment_status_cookie | text | Nhãn crawl từ billing_hub qua cookie (Funded / Paid / Pending / Failed / nhãn tiếng Việt). |
Giá trị hiển thị = COALESCE(payment_status_cookie, payment_status_api). Gợi ý: tạo cột generated / view hoặc xử lý ở query để reader đọc 1 chỗ, ưu tiên cookie. (Dev tự chọn cách tối ưu.)
Migration cột payment_status cũ (idempotent)
- Giá trị
Paid/Unpaid(do API sinh) → đổ sangpayment_status_api. - Các nhãn còn lại (
Funded,Đã thanh toán,Đang chờ,Pending,Không thành công,Failed) là crawl cookie cũ → đổ sangpayment_status_cookie.
5.2. Writer — 2 path ghi độc lập
app/api/workspaces/[workspaceId]/ad-accounts/[adAccountId]/check-bill/route.ts, ≈ dòng 240–262: đổi để ghi vào payment_status_api, không đụng payment_status_cookie. → diệt luôn bug ghi đè.
Mở https://business.facebook.com/billing_hub.php?asset_id=act_{id} bằng cookie + proxy của VIA còn quyền, parse HTML lấy nhãn theo tracking_id, ghi vào payment_status_cookie. (Nếu path này chưa có, dev dựng theo pattern các sync cookie khác — xem 5.4.)
transaction_id, còn billing_hub trả nhãn theo tracking_id → cần xác minh quan hệ tracking_id ↔ transaction_id trên ad_account_bills để ghi nhãn cookie vào đúng row.
5.3. Reader — đọc ưu tiên cookie
Các điểm sau hiện query payment_status='Funded', đổi sang đọc giá trị ưu tiên (cookie-first):
| Nơi đọc | File (trong repo product) |
|---|---|
| Funded bills aggregation & detail | risk/funded-bills-on-starred/route.ts (~90) & .../[adAccountId]/route.ts (~54) |
| Dashboard billing panel | dashboard/billing/route.ts (~163) |
| Billing page filter trạng thái | billing/route.ts (~24–27) |
| UI page risk | app/(dashboard)/w/[workspaceId]/admin/risk/funded-bills-on-starred/page.tsx |
5.4. Tài liệu tham chiếu (repo product)
docs/FORAI/facebook-credential-architecture.mddocs/FORAI/debug-guide.md6. Tiêu Chí Nghiệm Thu & Kịch Bản Kiểm Thử (UAT)
Acceptance criteria + test cases.
6.1. Tiêu chí nghiệm thu (Acceptance Criteria)
6.2. Kịch bản kiểm thử (Test Cases)
cookie=Funded, api=Paid → reader hiển thị Funded.api=Paid (chưa crawl cookie) → reader hiển thị Paid (fallback).cookie=Funded → chạy sync API → payment_status_cookie giữ nguyên, chỉ payment_status_api cập nhật.6ET7ZP9N52 → payment_status_cookie='Funded' → trang Risk hiển thị đúng.7. Quy Trình Bàn Giao & Review (CTO Handover)
Các bước chốt & deploy.
-
DecisionQuyết định cần chốt
Bill
6ET7ZP9N52— chờ crawl cookie hay update taypayment_status_cookie='Funded'để hiển thị đúng ngay. -
Bàn giaoTest Report + Demo + Approve
Sau khi xong + UAT trên staging, dev chuẩn bị Test Report kèm bằng chứng (ảnh / video:
6ET7ZP9N52hiện đúng Funded; demo sync API không làm mất nhãn cookie). Họp review trực tiếp với CTO duyệt cơ chế 2 cột + ưu tiên cookie + migration. Chỉ khi CTO Approve mới deploy Production.