Skip to content

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 đổiSectionẢnh hưởng
V5 blocker mở rộng: ngoài source name/cross-schema, BE phải confirm exact fields cho Dư ví DIVADư ví KMF4.2 Internal blockersBE

F1. Delivery Index

F1.1 Documents

FileAudiencePurpose
index.mdAllTổng quan, navigation entry point
prd.mdPO, Tech LeadBối cảnh, US/AC, phân quyền, Phase split, Decision Log
dev-spec.mdBE DevKiến trúc, Schema Mapping (Section 0), SQL MVs, Hasura, performance
ui-spec.mdFE Dev, DesignerLayout, wireframe ASCII, component tree, interactions, tooltips
plan.mdDev (FE+BE)23 task chi tiết — đã update phase tag + skip steps cho deferred MVs
qa-test-plan.mdQA LeadCoverage matrix, US→TC mapping, seed data, exit criteria
go-live-checklist.mdDevOps, Tech Lead, POPre-deploy, Day-0, Day-1, rollback runbook
This fileAllRACI, 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_global function + 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ụcResponsibleAccountableConsultedInformed
Spec finalizationPO/BAPOTech Lead, BE Lead, FE LeadAll team
Verification (13 V points — V1-V13 đều BLOCKER, V9-V13 = wallet semantics critical path)BE Lead + Security Lead + DBA + PO + Kế toánTech LeadDevOpsPO
Backend implementation (MVs, indexes, functions, export-api)BE Dev (2 người)BE LeadDBA, DevOpsPO, FE Lead
Frontend implementation (4 sub-tab + shared filter)FE Dev (2 người)FE LeadDesignerPO, BE Lead
Hasura permissions + Dynamic Permission v2 integrationBE DevBE LeadSecurityPO
QA testingQA EngineerQA LeadKế toán đại diệnPO, Tech Lead
Performance testBE Dev + DevOpsDevOpsDBATech Lead
Reconciliation (số liệu MV vs báo cáo cũ)BE Dev + Kế toánKế toán trưởngBE LeadPO
Go-live decisionTech Lead + POPOAll leadsOrg
Day-1 monitoringDevOps + on-callDevOps LeadTech LeadPO
Hotfix nếu cóDev (FE/BE tùy bug)Tech LeadQA LeadPO

F3. Timeline ước tính

Estimate dựa trên team 2 BE + 2 FE + 1 QA + 1 DevOps. Sprint length 2 tuần.

PhaseDurationOutput
W1: Schema verify + foundation1 tuầnBE 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 queries2 tuần4 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ịch3 tuần (parallel)Shared filter · Tổng quan sub-tab · Giao dịch sub-tab
W4-5: Khách hàng + Tài chính2 tuầnKhá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 test1 tuầnE2E flows · perf benchmark · permission tests
W7: QA + reconciliation1 tuầnqa-test-plan execute · reconciliation với báo cáo cũ
W8: UAT + go-live1 tuầnStakeholder 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

DependencyOwnerStatusRisk if not ready
region_branch schema (table + branch.region_id)DBA✅ Có sẵn (migration 1678865967129)
region_branch data 70 CNDBA + Ops🛑 V7 BLOCKER — verify query 70 CN có region_idFilter khu vực không hoạt động
Dynamic Permission v2 module registrySecurity team🛑 V6 BLOCKER — module API + helper + seed migration toolingRBAC không enforce, PII leak
pg_trgm extensionDBA⏳ Phase 2 onlyPhase 1 không cần
Redis cluster ổn địnhDevOps✅ Có sẵnWallet balance lookup chậm
MinIO/GCS storageDevOps✅ Có sẵnExport file không lưu được
notification-api ZNS template❌ 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)

IDBlockerOwnerDeadlineStatus
V1Customer filter rule — account_type chưa có trong codebase, dùng INNER JOIN với prepaid orders. BE confirm rule đúngBE LeadW1⏳ Open
V2Ví Diva / Ví KM split: schema có field riêng hay derive? (legacy — superseded by V9-V10)BE LeadW1⏳ Open
V3NV thu ngân field source (cột 9 bảng GD dòng 2)BE LeadW1⏳ Open
V4prepaid_card_view columns (id, name, flexible exist?)BE LeadW1⏳ Open
V5Wallet balance source name + cross-schema access + fields cho Dư ví DIVA/Dư ví KMBE LeadW1⏳ Open
V6RBAC v2 module API ready + helper name confirm + seed migration toolingSecurity LeadW1⏳ Open
V7Query xác nhận 70 CN có đủ region_id (kèm evidence)DBA + OpsW1⏳ Open
V8parent_id IS NULL rule cho mọi invoice query (parent + sub double count) — codebase evidenceBE LeadW1⏳ 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.goBE LeadW1⏳ 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ôngBE LeadW1⏳ 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 LeadW1-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 SAIBE LeadW1⏳ 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 sampleBE Lead + Kế toánW2⏳ 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ở ticket

Output → 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 định

Output → 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 sample

Output → 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 link

Output → 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 unlocked

Sign-off matrix:

VOwner sign-offPO ackTech Lead ack
V9, V10, V12BE Lead
V11PO + Kế toán + (Giám đốc TC nếu delta > 0.5%)(chính)
V13BE Lead + Kế toán

Khi cả 5 spike done → cập nhật:

  • SOURCE_OF_TRUTH.md Section 4: V9-V13 đổi ✅ Confirmed
  • PRD A10.0 Canonical Wallet Table: 5 hàng đổi ⏳ → ✅ LOCKED + Evidence column fill
  • EVIDENCE_PACK.md E7.1-E7.5: paste full evidence
  • dev-spec.md: bỏ tất cả 🔒 PROVISIONAL — DO NOT IMPLEMENT block (đã 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

RoleNameChannelEscalation level
Product Owner_______________Slack: @poL1
BA / Spec author_______________Slack: @baL1
Tech Lead_______________Slack: @techleadL2
BE Lead_______________Slack: @be-leadL2
FE Lead_______________Slack: @fe-leadL2
QA Lead_______________Slack: @qa-leadL2
DevOps Lead_______________Slack: @devopsL2
DBA_______________Slack: @dbaL2
Security_______________Slack: @securityL3
Kế toán đại diện_______________EmailL3
CTO / Engineering Manager_______________PhoneL4 (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 + CTO

F7. 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.md Section 0 (Schema Mapping) — bắt buộc
  • [ ] Team đã đọc dev-spec.md Section 5.1 (Phân khúc) + Section 9.2 (MV SQL)
  • [ ] FE Dev đã đọc ui-spec.md toà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-185 offset bug → build mới export, KHÔNG copy
    • PrepaidCardReportCard.tsx:37 exclude 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_branch migration 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:

  1. Phản hồi user thực tế từ Phase 1
  2. Roadmap business của org
  3. 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: