Appearance
Handoff Package — Prepaid Card Analytics Tab
Date: 2026-05-04 · Phase: 1 (MVP) · Version: 3.6 Hand off from: PO/BA → Tech Lead + Team Status: 🛑 IMPLEMENTATION HOLD — chờ confirm 13 verification points (V1-V13), trong đó V9-V13 là wallet semantics blocker (Review L8). Spec hiện tại chỉ dùng cho review/discussion, KHÔNG bắt đầu BE migration / FE feature build / QA execution. Cho phép parallel: scaffold FE read-only shell + BE verification spike (xem F4.3).
v3.15 — 14/05/2026
| Thay đổi | Section | Ảnh hưởng |
|---|---|---|
V5 blocker mở rộng: ngoài source name/cross-schema, BE phải confirm exact fields cho Dư ví DIVA và Dư ví KM | F4.2 Internal blockers | BE |
F1. Delivery Index
F1.1 Documents
| File | Audience | Purpose |
|---|---|---|
| index.md | All | Tổng quan, navigation entry point |
| prd.md | PO, Tech Lead | Bối cảnh, US/AC, phân quyền, Phase split, Decision Log |
| dev-spec.md | BE Dev | Kiến trúc, Schema Mapping (Section 0), SQL MVs, Hasura, performance |
| ui-spec.md | FE Dev, Designer | Layout, wireframe ASCII, component tree, interactions, tooltips |
| plan.md | Dev (FE+BE) | 23 task chi tiết — đã update phase tag + skip steps cho deferred MVs |
| qa-test-plan.md | QA Lead | Coverage matrix, US→TC mapping, seed data, exit criteria |
| go-live-checklist.md | DevOps, Tech Lead, PO | Pre-deploy, Day-0, Day-1, rollback runbook |
| This file | All | RACI, contact, timeline, escalation |
F1.2 Phase 1 scope tóm tắt (v3.1)
✅ Build:
- 4 sub-tab read-only: Tổng quan · Giao dịch · Khách hàng · Tài chính
- Shared filter 3-element (Chi nhánh · Khoảng thời gian · Tìm kiếm) — KHÔNG có Compare Mode toggle
- 4 MVs P1:
mv_prepaid_order_daily⭐ ·mv_prepaid_card_daily⭐ ·mv_prepaid_customer_stats·mv_prepaid_finance_daily(đã tách order/card-level để fix double count + bỏ field gây double count) - 1 function P1:
compute_prepaid_alerts - Export Excel server-side với label đồng bộ tiếng Việt (
Xuất Excel/Xuất {Tên báo cáo}) - Feature flag
FEATURE_PREPAID_ANALYTICS_V2 - RBAC v2 fine-grained 3 actions:
view+export+view_full_phone(PII compliance) - Charts time-series chỉ theo ngày (KHÔNG toggle Tuần/Tháng — DEC-U08)
❌ Defer / Out of scope:
- Phase 2: Global Search xuyên sub-tab (
search_prepaid_globalfunction +pg_trgm) - Phase 3+: Sub-tab Marketing + Sub-tab Nhân viên + 2 MVs (
staff_stats,campaign_stats) - OUT OF SCOPE Phase 1+ (kể cả P1.x): Bulk SMS/ZNS/Gán NV, Xác nhận thanh toán write actions, Multi-select KH — dùng module Marketing/CRM riêng
F2. RACI Matrix
| Hạng mục | Responsible | Accountable | Consulted | Informed |
|---|---|---|---|---|
| Spec finalization | PO/BA | PO | Tech Lead, BE Lead, FE Lead | All team |
| Verification (13 V points — V1-V13 đều BLOCKER, V9-V13 = wallet semantics critical path) | BE Lead + Security Lead + DBA + PO + Kế toán | Tech Lead | DevOps | PO |
| Backend implementation (MVs, indexes, functions, export-api) | BE Dev (2 người) | BE Lead | DBA, DevOps | PO, FE Lead |
| Frontend implementation (4 sub-tab + shared filter) | FE Dev (2 người) | FE Lead | Designer | PO, BE Lead |
| Hasura permissions + Dynamic Permission v2 integration | BE Dev | BE Lead | Security | PO |
| QA testing | QA Engineer | QA Lead | Kế toán đại diện | PO, Tech Lead |
| Performance test | BE Dev + DevOps | DevOps | DBA | Tech Lead |
| Reconciliation (số liệu MV vs báo cáo cũ) | BE Dev + Kế toán | Kế toán trưởng | BE Lead | PO |
| Go-live decision | Tech Lead + PO | PO | All leads | Org |
| Day-1 monitoring | DevOps + on-call | DevOps Lead | Tech Lead | PO |
| Hotfix nếu có | Dev (FE/BE tùy bug) | Tech Lead | QA Lead | PO |
F3. Timeline ước tính
Estimate dựa trên team 2 BE + 2 FE + 1 QA + 1 DevOps. Sprint length 2 tuần.
| Phase | Duration | Output |
|---|---|---|
| W1: Schema verify + foundation | 1 tuần | BE Lead chạy verification spike (5 spike — F4.3) cover V1-V13 (13 V points). Cover wallet semantics critical path V9-V13 (Spike 1-5). Migration setup + Hasura metadata + feature flag chỉ scaffold (KHÔNG enable PROVISIONAL block đến khi V9-V13 unlock) |
| W2-3: Backend MVs + GraphQL queries | 2 tuần | 4 MVs P1 (mv_prepaid_order_daily · mv_prepaid_card_daily · mv_prepaid_customer_stats · mv_prepaid_finance_daily) + indexes + export-api + 1 SQL function compute_prepaid_alerts. Defer P2/3+: mv_prepaid_staff_stats, mv_prepaid_campaign_stats, search_prepaid_global |
| W2-4: Frontend foundation + Tổng quan + Giao dịch | 3 tuần (parallel) | Shared filter · Tổng quan sub-tab · Giao dịch sub-tab |
| W4-5: Khách hàng + Tài chính | 2 tuần | Khách hàng segment + behavior bar read-only (DEC-U09 — KHÔNG bulk SMS/ZNS/Gán NV) · Tài chính 4 tab con + 5 export |
| W6: Integration + perf test | 1 tuần | E2E flows · perf benchmark · permission tests |
| W7: QA + reconciliation | 1 tuần | qa-test-plan execute · reconciliation với báo cáo cũ |
| W8: UAT + go-live | 1 tuần | Stakeholder UAT · Go-live deploy · Day-1 monitor |
Total: ~8 tuần (2 sprints) — khớp với prd.md Phase 1 estimate.
Mốc quan trọng
- W1 end: Schema verification done → unblock SQL implementation
- W4 end: 50% sub-tab demoed cho PO
- W6 end: Code complete (G1)
- W7 end: QA sign-off (G2)
- W8 end: Go-live (G3-G7)
F4. Dependencies & Blockers
F4.1 External dependencies
| Dependency | Owner | Status | Risk if not ready |
|---|---|---|---|
region_branch schema (table + branch.region_id) | DBA | ✅ Có sẵn (migration 1678865967129) | — |
region_branch data 70 CN | DBA + Ops | 🛑 V7 BLOCKER — verify query 70 CN có region_id | Filter khu vực không hoạt động |
| Dynamic Permission v2 module registry | Security team | 🛑 V6 BLOCKER — module API + helper + seed migration tooling | RBAC không enforce, PII leak |
pg_trgm extension | DBA | ⏳ Phase 2 only | Phase 1 không cần |
| Redis cluster ổn định | DevOps | ✅ Có sẵn | Wallet balance lookup chậm |
| MinIO/GCS storage | DevOps | ✅ Có sẵn | Export file không lưu được |
| — | ❌ N/A (Phase 1 không có bulk SMS/ZNS — DEC-U09) | — |
F4.2 Internal blockers — TẤT CẢ V1-V13 ĐỀU BLOCKER (xem SOURCE_OF_TRUTH.md Section 4)
| ID | Blocker | Owner | Deadline | Status |
|---|---|---|---|---|
| V1 | Customer filter rule — account_type chưa có trong codebase, dùng INNER JOIN với prepaid orders. BE confirm rule đúng | BE Lead | W1 | ⏳ Open |
| V2 | Ví Diva / Ví KM split: schema có field riêng hay derive? (legacy — superseded by V9-V10) | BE Lead | W1 | ⏳ Open |
| V3 | NV thu ngân field source (cột 9 bảng GD dòng 2) | BE Lead | W1 | ⏳ Open |
| V4 | prepaid_card_view columns (id, name, flexible exist?) | BE Lead | W1 | ⏳ Open |
| V5 | Wallet balance source name + cross-schema access + fields cho Dư ví DIVA/Dư ví KM | BE Lead | W1 | ⏳ Open |
| V6 | RBAC v2 module API ready + helper name confirm + seed migration tooling | Security Lead | W1 | ⏳ Open |
| V7 | Query xác nhận 70 CN có đủ region_id (kèm evidence) | DBA + Ops | W1 | ⏳ Open |
| V8 | parent_id IS NULL rule cho mọi invoice query (parent + sub double count) — codebase evidence | BE Lead | W1 | ⏳ Open |
| V9 | 🆕 Ví Diva NẠP = parent_invoice.reference_amount? (xem PRD A10.0 hàng #2) — code path usePrepaidOrderItem.getValueIntoWallet → payment_order.go → invoice_insert_update.go | BE Lead | W1 | ⏳ Open |
| V10 | 🆕 Ví KM NẠP = parent_invoice.wallet_promotion_amount? (PRD A10.0 hàng #3) — verify có cần filter payment_method_id không | BE Lead | W1 | ⏳ Open |
| V11 | 🆕 DT ghi nhận semantics — DEC-B06 PROVISIONAL: "DT chỉ ví chính" có conflict với baseline search_report_service đang split 2 bucket. PO + Kế toán reconcile + ký nhận chênh lệch chấp nhận được (≤0.5% hoặc lý do nghiệp vụ) | PO + Kế toán + BE Lead | W1-W2 | ⏳ Open |
| V12 | 🆕 Ví KM ĐÃ DÙNG mapping: invoice.reference_amount filter payment_method_id='wallet_promotion' (PRD A10.0 hàng #5). CẢNH BÁO: mapping cũ "wallet_promotion_amount = ví KM dùng" đã được Review L8 chứng minh SAI | BE Lead | W1 | ⏳ Open |
| V13 | 🆕 Finance MV refactor — bỏ cột promo_amount từ wallet_promotion_amount cũ, thay bằng split rõ theo payment_method_id. Reconciliation với baseline finance report 5 ngày sample | BE Lead + Kế toán | W2 | ⏳ Open |
🛑 HOLD POLICY: Implementation HOLD đến khi cả 13 V đều đổi sang ✅ Confirmed kèm evidence (link metadata / query result / API doc / reconciliation report). Cho phép parallel: scaffold FE read-only shell + spec cleanup + verification spike (BE chạy SQL probe codebase để fill V9-V13 evidence). KHÔNG được start: BE migration / Hasura metadata / export endpoint / FE feature build / QA test execution.
V9-V13 critical path: Sub-group V9-V13 (wallet semantics — Review L8) là blocker lớn nhất. Theo PRD A10.0 Canonical Wallet Table, BE phải confirm 5 hàng (Tiền thu / Ví Diva nạp / Ví KM nạp / Ví Diva dùng / Ví KM dùng) với codebase evidence (file:line) + reconciliation với baseline. Nếu chưa unlock V9-V13 → KHÔNG được build feature dù V1-V8 đã clear.
F4.3 BE Actionable Checklist — V9-V13 verification spike
Mục đích: Hướng dẫn BE Lead + Kế toán thực hiện verification spike để unblock V9-V13. Mỗi mục có input cần chạy + output expected + ai sign-off. Estimated total effort: 3-5 ngày BE + 1 ngày Kế toán.
Spike 1 — V9 Ví Diva NẠP (BE Lead, ~0.5 ngày)
□ 1.1 — Find code path:
rg "getValueIntoWallet|prepaid_card_base_value" diva-admin/src/ diva-backend/
Paste 3 file:line vào EVIDENCE_PACK.md E7.1 table
□ 1.2 — Run verification SQL (E7.1 sample) trên 5 đơn prepaid khác nhau:
- 1 đơn giá bán = base value (no discount)
- 1 đơn giá bán < base value (discount)
- 1 đơn giá bán > base value (phụ thu — nếu có)
- 2 đơn quantity > 1
Paste result vào E7.1.
□ 1.3 — Verify acceptance: pi.reference_amount khớp công thức confirmed
✅ Update SOT V9 → Confirmed + paste evidence link
❌ Nếu không khớp → discuss với PO ngay, mở ticketOutput → PRD A10.0 hàng #2: Đổi từ ⏳ PROVISIONAL → ✅ LOCKED + fill cột Evidence với file:line.
Spike 2 — V10 Ví KM NẠP (BE Lead, ~0.5 ngày)
□ 2.1 — Find code path:
rg "wallet_promotion_amount" diva-backend/services/ecommerce-api/ --type go
Trace flow: campaign apply → invoice write
Paste vào EVIDENCE_PACK.md E7.2
□ 2.2 — Run verification SQL trên 10 đơn:
- 5 đơn có KM (campaign apply)
- 5 đơn không KM
Paste result.
□ 2.3 — Edge case check: đơn không KM → wallet_promotion_amount = 0 hay NULL?
Verify SQL behavior: COALESCE() / IS NULL filter
□ 2.4 — Verify acceptance:
✅ Update SOT V10 → Confirmed
Decide: có cần thêm filter payment_method_id ở SQL không?
Document quyết định trong EVIDENCE_PACK E7.2.Output → PRD A10.0 hàng #3: ⏳ → ✅ + Evidence file:line + filter rule (có hay không cần payment_method_id filter).
Spike 3 — V11 DT semantics reconcile (PO + Kế toán + BE, ~1.5 ngày)
□ 3.1 — BE: Run baseline report cũ (search_report_service) cho 5 ngày sample.
Output 2 số tách bạch:
- dt_wallet (payment_method='wallet')
- dt_wallet_promotion (payment_method='wallet_promotion')
□ 3.2 — BE: Run canonical query mới (DEC-B06 — chỉ wallet) cùng 5 ngày.
Output: dt_canonical = dt_wallet only.
□ 3.3 — Tính delta: dt_baseline_total = dt_wallet + dt_wallet_promotion
delta_pct = (dt_baseline_total - dt_canonical) / dt_baseline_total × 100%
□ 3.4 — PO + Kế toán họp 30 phút:
- Nếu delta < 0.5% → ✅ chấp nhận, KHÓA DEC-B06 = "chỉ ví chính"
- Nếu delta ≥ 0.5%:
(a) Kế toán chấp nhận giảm DT? Báo Giám đốc TC sign-off
(b) HOẶC đổi DEC-B06 = "split 2 bucket như cũ" (semantic không break)
Quyết định → ký biên bản → upload vào EVIDENCE_PACK E7.3
□ 3.5 — Update SOT V11 → Confirmed + biên bản link
Update DEC-B06 status: PROVISIONAL → LOCKED (final decision)
Cascade: PRD A10 FORMULA-005 wording theo quyết địnhOutput → DEC-B06 final + PRD A10.0 hàng #4 ⏳ → ✅.
Spike 4 — V12 Ví KM ĐÃ DÙNG mapping (BE Lead, ~0.5 ngày)
□ 4.1 — Run verification SQL E7.4: kiểm tra 10 invoice có
payment_method_id='wallet_promotion' (service order, không phải prepaid)
□ 4.2 — Verify acceptance:
- reference_amount > 0 cho mọi row (= số tiền ví KM dùng)
- wallet_promotion_amount = 0/NULL cho service order
□ 4.3 — Edge case:
rg "wallet_promotion_amount" diva-backend/ --type go
Tìm code path nào có thể write vào field này cho non-prepaid order
→ Nếu có → mapping V12 phức tạp hơn → discuss với PO
□ 4.4 — Update SOT V12 → Confirmed + paste 10-row sampleOutput → PRD A10.0 hàng #5 ⏳ → ✅ (KHÔNG dùng wallet_promotion_amount cho phần đã dùng).
Spike 5 — V13 Finance MV refactor + 5-day reconciliation (BE Lead + Kế toán, ~1 ngày)
□ 5.1 — Sau khi V11+V12 confirmed → refactor mv_prepaid_finance_daily SQL
- Bỏ cột promo_amount = SUM(wallet_promotion_amount) cũ
- Giữ wallet_amount = SUM(reference_amount) (đã đúng)
- Verify GROUP BY payment_method_id split 2 bucket rõ
□ 5.2 — Deploy MV mới ở staging
□ 5.3 — Run reconciliation E7.5 table (5 ngày):
Cột | Tiền thu | Ví Diva nạp | Ví KM nạp | Ví Diva dùng | Ví KM dùng | Baseline match | Delta
Fill bảng cho 5 ngày sample.
□ 5.4 — Acceptance gate:
- Tổng delta ≤ 0.5% → ✅
- Nếu vượt → Kế toán + PO ký nhận lý do nghiệp vụ chấp nhận
□ 5.5 — Update SOT V13 → Confirmed + reconciliation table linkOutput → mv_prepaid_finance_daily migration finalized + PRD A10.0 hàng #1+#4+#5 LOCKED.
Master timeline V9-V13
Day 1 (BE Lead): Spike 1 (V9) + Spike 2 (V10) → 2 V unlocked
Day 2 (BE Lead): Spike 4 (V12) + start Spike 3.1-3.3 (V11 SQL)
Day 3 (PO+Kế toán): Spike 3.4 meeting → V11 unlocked
Day 4-5 (BE+Kế toán): Spike 5 (V13) → V13 unlocked
→ All V9-V13 ✅ → Implementation unlockedSign-off matrix:
| V | Owner sign-off | PO ack | Tech Lead ack |
|---|---|---|---|
| V9, V10, V12 | BE Lead | ✓ | ✓ |
| V11 | PO + Kế toán + (Giám đốc TC nếu delta > 0.5%) | (chính) | ✓ |
| V13 | BE Lead + Kế toán | ✓ | ✓ |
Khi cả 5 spike done → cập nhật:
SOURCE_OF_TRUTH.mdSection 4: V9-V13 đổi ✅ ConfirmedPRD A10.0 Canonical Wallet Table: 5 hàng đổi ⏳ → ✅ LOCKED + Evidence column fillEVIDENCE_PACK.md E7.1-E7.5: paste full evidencedev-spec.md: bỏ tất cả🔒 PROVISIONAL — DO NOT IMPLEMENTblock (đã verified)plan.md Task 9: enable 4 GraphQL aliases (bỏ TBD)qa-test-plan.md D5 Entry: V9-V13 checkbox đổi sang ✅- Increment version PRD/handoff/index → v4.0 (semantic break từ HOLD → IMPLEMENT)
F5. Contact List
| Role | Name | Channel | Escalation level |
|---|---|---|---|
| Product Owner | _______________ | Slack: @po | L1 |
| BA / Spec author | _______________ | Slack: @ba | L1 |
| Tech Lead | _______________ | Slack: @techlead | L2 |
| BE Lead | _______________ | Slack: @be-lead | L2 |
| FE Lead | _______________ | Slack: @fe-lead | L2 |
| QA Lead | _______________ | Slack: @qa-lead | L2 |
| DevOps Lead | _______________ | Slack: @devops | L2 |
| DBA | _______________ | Slack: @dba | L2 |
| Security | _______________ | Slack: @security | L3 |
| Kế toán đại diện | _______________ | L3 | |
| CTO / Engineering Manager | _______________ | Phone | L4 (P0 incidents) |
F6. Escalation flow
P3 / P2 issue → BE/FE Dev → BE/FE Lead → resolve trong sprint
P1 issue → Tech Lead + QA Lead → resolve trong 24h
P0 issue → Tech Lead + DevOps → hotfix trong 4h → escalate CTO nếu vượt SLA
Production incident → DevOps on-call → page Tech Lead + CTOF7. Knowledge transfer checklist
F7.1 Trước khi start
- [ ] Team đã đọc
prd.md(toàn bộ) — quiz nhanh 5 phút - [ ] Team đã đọc
dev-spec.mdSection 0 (Schema Mapping) — bắt buộc - [ ] Team đã đọc
dev-spec.mdSection 5.1 (Phân khúc) + Section 9.2 (MV SQL) - [ ] FE Dev đã đọc
ui-spec.mdtoàn bộ + thử navigate sample wireframes trong head - [ ] QA đã đọc
qa-test-plan.md+ understand exit criteria - [ ] DevOps đã đọc
go-live-checklist.md+ ack rollback runbook
F7.2 Brownfield context (CRITICAL)
- [ ] Team đã đọc và hiểu existing baseline bugs (PRD Risks):
PrepaidCardReportFilter.tsx:180-185offset bug → build mới export, KHÔNG copyPrepaidCardReportCard.tsx:37exclude flexible → build mới include cả 2 loại
- [ ] Team đã review codebase
diva-admin/src/modules/report/components/prepaid-card/để hiểu pattern hiện có (tham khảo, không reuse logic) - [ ] BE đã review
region_branchmigration cũ (1678865967129_region_branch/up.sql) để hiểu schema có sẵn
F7.3 Decision Log review
- [ ] DEC-B01..B05, DEC-U01..U07 trong prd.md Z1-Z2 đã được team understand
- [ ] Đặc biệt: DEC-B05 (Phase split), DEC-U04 (bỏ Compare Mode), DEC-U06 (rename Tài chính)
F8. Definition of Done — Phase 1
Phase 1 được coi là DONE khi:
- [ ] Tất cả gate criteria G1-G7 (go-live-checklist E1) pass
- [ ] Tab mới live trên production cho ≥ 1 tuần KHÔNG có P0/P1 bug ngoài plan
- [ ] ≥ 70% kế toán đã chuyển sang dùng tab mới (đo qua analytics)
- [ ] Reconciliation Day-7 chênh lệch ≤ 0.1%
- [ ] Tab cũ vẫn còn (chỉ ẩn qua flag) — chưa xóa code
- [ ] Documentation updated (any deviation từ spec ban đầu được note vào index.md changelog)
F9. Phase 2 / Phase 3+ ưu tiên lại sau Phase 1
Phase 1 done KHÔNG đồng nghĩa với Phase 2/3+ tự động khởi động. Cần re-prioritize dựa trên:
- Phản hồi user thực tế từ Phase 1
- Roadmap business của org
- Resource availability
Trigger để khởi động Phase 2 (Global Search):
- User feedback "cần search xuyên sub-tab" lặp lại ≥ 5 lần / tháng
- Hoặc Marketing/Kế toán explicit request
Trigger để khởi động Phase 3+ (Marketing + Staff sub-tab):
- Marketing team yêu cầu báo cáo CD chuyên sâu vượt quá Sub-tab Khách hàng
- Quản lý vùng cần coaching data-driven cho NV
Cả 2 phase này sẽ có handoff package riêng khi ramp up.
Reference:
- Spec details: prd.md · dev-spec.md · ui-spec.md
- Implementation: plan.md
- Testing: qa-test-plan.md
- Operations: go-live-checklist.md