Skip to content

Go-Live Checklist — Prepaid Card Analytics Tab

Date: 2026-05-04 · Phase: 1 (MVP — 4 sub-tab) Parent: prd.md · dev-spec.md · qa-test-plan.md


E1. Tiêu chí cổng (Gate Criteria)

GateOwnerPass condition
G1 — Code completeTech LeadAll P0 tasks per plan.md merged to main
G2 — QA sign-offQA Leadqa-test-plan Exit criteria đạt 100% P0 + ≥95% P1
G3 — ReconciliationKế toán + BESố liệu MV match báo cáo cũ ± 0.1% trên 3 tháng
G4 — Security reviewDevOps + SecurityRBAC v2 fine-grained 3 actions (view · export · view_full_phone) hoạt động · SDT masked theo permission · Export audit log per-export-type · BE enforce (không chỉ trust FE)
G5 — PerformanceBE + DevOpsTổng quan < 500ms · Export 50K < 60s · MV refresh < 30s/MV
G6 — Rollback drillDevOpsFeature flag toggle off ≤ 1 phút khôi phục tab cũ
G7 — Stakeholder sign-offPOPO + Tech Lead + Kế toán đại diện approve

E2. Checklist trước deploy (Day −1)

E2.1 Cơ sở dữ liệu (Database)

  • [ ] Verify region_branch data:

    sql
    SELECT COUNT(*) FROM region_branch;        -- expect ≥ 4
    SELECT COUNT(*) FROM branch
     WHERE region_id IS NULL AND deleted_at IS NULL;  -- expect 0

    Nếu có CN missing region_id → seed thủ công trước deploy.

  • [ ] Verify schema fields đã match Section 0:

    • order_item.prepaid_value_into_wallet exists
    • order_item.product_id exists, JOIN prepaid_card_view
    • order.total (KHÔNG total_amount)
    • paid_amount, paid_at derive trạng thái
  • [ ] 4 P1 MVs đã deploy on staging (v3 topology — đã tách order/card-level để fix double count):

    • mv_prepaid_order_daily ⭐ (order-level KPIs)
    • mv_prepaid_card_daily ⭐ (card-level chart)
    • mv_prepaid_customer_stats (KH segment + behavior)
    • mv_prepaid_finance_daily (PTTT split — đã bỏ total_wallet_topup để tránh double count)
  • [ ] Indexes (Section 9.3) deployed:

    • idx_order_prepaid_report (composite)
    • idx_order_prepaid_debt (partial — dùng paid_amount < total, không paid_status enum)
    • idx_invoice_order_paid
    • idx_invoice_wallet_usage
    • idx_txreq_commission_order (wallet schema)
  • [ ] Functions deployed:

    • compute_prepaid_alerts(...) (alert function — filter balance > 0, query wallet_balance_result)
    • set_current_timestamp_updated_at() (existing helper)
  • [ ] export_job table created (audit + progress tracking)

  • [ ] Dynamic Permission v2 seeded:

    • Module report.prepaid_analytics registered
    • 3 actions: view, export, view_full_phone
    • Default grants per role (Section 5.3 prd.md matrix)

E2.2 Dịch vụ Backend

  • [ ] export-api running + endpoint /actions/export-prepaid-report ready
  • [ ] scripts service có cron MV refresh (4 MVs P1):
    cron
    */15 * * * * REFRESH MATERIALIZED VIEW CONCURRENTLY mv_prepaid_order_daily
    */15 * * * * REFRESH MATERIALIZED VIEW CONCURRENTLY mv_prepaid_card_daily
    */15 * * * * REFRESH MATERIALIZED VIEW CONCURRENTLY mv_prepaid_finance_daily
    */30 * * * * REFRESH MATERIALIZED VIEW CONCURRENTLY mv_prepaid_customer_stats
  • [ ] Redis running cho wallet_balance_result cache (TTL 10 phút)
  • [ ] MinIO/GCS sẵn sàng nhận file export
  • [ ] ⚠️ notification-api KHÔNG cần cho Sub-tab Khách hàng — bulk SMS/ZNS đã bỏ khỏi tab Analytics (review L5)

E2.3 Backfill MV (chạy 1 lần)

  • [ ] Backfill script chạy cho dữ liệu lịch sử (4 MVs P1):
    bash
    # Refresh đầy đủ (NOT CONCURRENT lần đầu để build full dataset)
    psql -c "REFRESH MATERIALIZED VIEW mv_prepaid_order_daily;"
    psql -c "REFRESH MATERIALIZED VIEW mv_prepaid_card_daily;"
    psql -c "REFRESH MATERIALIZED VIEW mv_prepaid_customer_stats;"
    psql -c "REFRESH MATERIALIZED VIEW mv_prepaid_finance_daily;"
  • [ ] Verify row counts: order_daily ~150K rows · card_daily ~500K · customer_stats ~100K · finance_daily ~500K
  • [ ] First refresh time logged trong backfill report

E2.4 Frontend (FE)

  • [ ] Build artifact test trên staging (admin variant) — không có error console
  • [ ] Feature flag FEATURE_PREPAID_ANALYTICS_V2 = true trên staging
  • [ ] Routes registered đúng (4 routes P1):
    • /r/reports/prepaid-card-analytics/overview
    • /r/reports/prepaid-card-analytics/transactions
    • /r/reports/prepaid-card-analytics/customers
    • /r/reports/prepaid-card-analytics/finance
  • [ ] Routes /marketing/staff KHÔNG có (defer P3+)

E2.5 Permissions (RBAC v2 fine-grained — 3 actions)

  • [ ] Module report.prepaid_analytics đã add vào Dynamic Permission v2 registry
  • [ ] 3 actions seeded: view, export, view_full_phone
  • [ ] Default grants per role (theo prd.md Section 5.3 matrix):
    • admin: [view, export, view_full_phone] (branch_mode=all)
    • area_manager: [view, export] (branch_mode=scoped)
    • branch_manager: [view, export] (branch_mode=self)
    • accountant: [view, export, view_full_phone] (cần xem SDT đầy đủ để gọi nợ)
    • marketing: [view] only (KHÔNG export bulk, KHÔNG SDT)
    • staff: [] (tab ẩn)
  • [ ] Test với từng role trên staging:
    • view action → tab visible/hidden đúng
    • export action → 5 nút "Xuất {Tên báo cáo}" + 1 nút "Xuất Excel" hide/show đúng (tất cả cùng 1 permission — DEC-U10)
    • view_full_phone action → SDT mask/unmask đúng trong UI table + export file
  • [ ] BE enforce — KHÔNG chỉ trust FE: thử bypass FE check bằng curl trực tiếp endpoint export → phải trả 403
  • [ ] Audit log working — mỗi export ghi vào export_job với phone_unmask flag

E2.6 Đối soát (Reconciliation)

  • [ ] Run reconciliation script: so sánh số liệu MV vs báo cáo cũ trên 3 tháng gần nhất
  • [ ] Acceptable delta: ≤ 0.1% (do tab cũ có bug skip 1000 rows export + exclude flexible)
  • [ ] Document delta trong reconciliation report

E3. Triển khai ngày 0 (Day-0)

E3.1 Deployment sequence (ưu tiên thứ tự)

  1. 17:00 — DB migrations (low traffic)
    • [ ] Apply migrations P1 (KHÔNG branch_region — đã có; 4 MVs + indexes + 1 function compute_prepaid_alerts + export_job table)
    • [ ] Verify 4 MVs P1 created
  2. 17:30 — Backfill MV (background, ~10-15 phút)
    • [ ] Run REFRESH non-CONCURRENT lần đầu cho 4 MVs P1
  3. 18:00 — Cron MV refresh (enable)
    • [ ] Add cron entries cho 4 MVs P1
    • [ ] Verify first auto-refresh hoạt động
  4. 18:30 — Backend services deploy
    • [ ] export-api restart với endpoint mới
    • [ ] Hasura metadata reload — track 4 MVs P1 + 1 function + permissions theo 3 actions + export_job table. KHÔNG track search_prepaid_global / mv_prepaid_staff_stats / mv_prepaid_campaign_stats
    • [ ] Action handler prepaid_top_staff_p1 nếu cần (Top NV Overview compute trực tiếp)
  5. 19:00 — Frontend deploy
    • [ ] Deploy build với feature flag = true
    • [ ] CDN cache invalidate
  6. 19:15 — Smoke test
    • [ ] Login admin → vào tab → 4 sub-tab P1 (Tổng quan / Giao dịch / Khách hàng / Tài chính) load < 1s
    • [ ] Routes /marketing/staff KHÔNG accessible (404 hoặc redirect)
    • [ ] Test 1 export → file download được, audit log ghi đúng
    • [ ] Test SDT mask theo role
    • [ ] Verify cron refresh chạy đúng cho 4 MVs

E3.2 Truyền thông

  • [ ] T-1 day: Notify Kế toán + Marketing + Quản lý "Tab Analytics ra mắt mai 19:00"
  • [ ] T-0 19:30: Send announcement với link onboarding video / quick start
  • [ ] T+1 day: Monitor user feedback channel (Slack/Telegram)

E4. Theo dõi ngày 1 (24h sau deploy)

E4.1 Metrics theo dõi

MetricTargetAlert thresholdChannel
Tab load time (P95)< 500ms> 1000msDataDog
MV refresh success rate100%< 95%Cron logs
Export success rate> 98%< 90%export-api logs
Error rate FE< 0.5%> 2%Sentry
User adoption (DAU)≥ 30% kế toánAnalytics

E4.2 Reconciliation check (Day-1 morning)

  • [ ] So sánh KPI hôm trước trên tab mới vs tab cũ
  • [ ] Nếu chênh lệch > 0.5% → escalate Tech Lead + BE

E4.3 Sẵn sàng hotfix

  • [ ] DevOps on-call 24h sau deploy
  • [ ] Hotfix branch hotfix/prepaid-analytics-day1 ready
  • [ ] Rollback plan documented (Section E6)

E5. Ký duyệt (Sign-off)

RoleNameSign-off dateNotes
Product Owner_________________________
Tech Lead_________________________
QA Lead_________________________
BE Lead_________________________
FE Lead_________________________
DevOps_________________________
Kế toán đại diện_________________________

E6. Runbook rollback

Scenario 1: Critical bug — sai số liệu tài chính

Trigger: Kế toán report số liệu sai > 1% so với báo cáo cũ.

Steps:

  1. Immediate (< 5 phút): Toggle feature flag FEATURE_PREPAID_ANALYTICS_V2 = false → user quay lại tab cũ
  2. Investigate root cause (BE log + MV state)
  3. Fix → deploy hotfix → re-enable flag

Scenario 2: MV refresh fail liên tiếp

Trigger: Cron log "REFRESH ... FAILED" 3 lần liên tiếp.

Steps:

  1. Check DB load → nếu cao → throttle other queries
  2. Check MV size + index health
  3. Manual REFRESH non-CONCURRENT (chấp nhận lock ngắn)
  4. Nếu vẫn fail → drop MV + recreate (có thể mất data ngắn)

Scenario 3: Export crash (OOM hoặc timeout)

Trigger: export-api OOM, file không generate.

Steps:

  1. Reduce chunk size từ 1000 → 500 rows
  2. Restart export-api với memory tăng tạm thời
  3. User retry → nếu vẫn fail → manual SQL extract gửi qua email

Scenario 4: MV refresh gây tải DB cao

Trigger: DB CPU > 80% trong refresh window.

Steps:

  1. Tăng interval cron: 15 phút → 30 phút (summary, finance) · 30 → 60 phút (customer)
  2. Move refresh sang off-peak hours (2-4 AM)
  3. Nếu vẫn cao → drop indexes phụ tạm thời, profile query

Scenario 5: Schema field mismatch (chưa verify hết)

Trigger: Migration apply fail, hoặc query return 0 rows.

Steps:

  1. Toggle feature flag OFF
  2. Verify schema vs dev-spec Section 0 — find mismatched field
  3. Update SQL trong MV definition
  4. Re-deploy migration → re-enable flag

E7. Phase 2 / Phase 3+ readiness

Trigger: ≥ 1 tháng Phase 1 stable, có user feedback "cần search xuyên sub-tab".

Action:

  • [ ] Run migration create_search_prepaid_global (Phase 2)
  • [ ] Add pg_trgm GIN index
  • [ ] Build component PrepaidAnalyticsGlobalSearch.tsx
  • [ ] Integrate vào shared filter bar

Khi nào enable Phase 3+ (Marketing + Nhân viên sub-tab)?

Trigger: Org có nhu cầu rõ ràng (Marketing yêu cầu báo cáo CD chuyên sâu / Quản lý vùng cần coaching data).

Action:

  • [ ] Run migrations create_mv_prepaid_staff_stats, create_mv_prepaid_campaign_stats
  • [ ] Build 9 components Phase 3+ (Marketing 6 + Staff 4)
  • [ ] Enable routes /marketing, /staff
  • [ ] Update navigation tooltip → enable click
  • [ ] QA test cycle riêng cho Phase 3+

Reference: