Appearance
SOURCE OF TRUTH — LTV Phase 1
Version: 1.2
Date: 21/04/2026
Author: PO/BA
Purpose: Canonical truth trước khi sinh PRD/UI/Dev/QA
File này dùng để làm gì: khóa canonical truth trước khi sinh PRD/UI/Dev/QA, tránh mỗi file tự phát minh rule riêng. Nên đọc trước:
Current-Code Facts→Solution Lock Snapshot→Day-1 Simplifications.
Changelog
| Version | Date | Author | Thay đổi |
|---|---|---|---|
| 1.2 | 21/04/2026 | PO/BA | Khóa implementation defaults cho report-role, seed raw source v1, confidence model và refresh strategy hybrid |
| 1.1 | 21/04/2026 | PO/BA | Đồng bộ lại canonical decision IDs với PRD, khóa lifecycle cho mapping/backfill, bổ sung fact về customer_cycle_report_group |
| 1.0 | 20/04/2026 | PO/BA | Initial từ design đã chốt |
1) Canonical Decisions
| ID | Decision | Certainty | Source | Notes |
|---|---|---|---|---|
| DEC-001 | LTV chuẩn = actual revenue hợp lệ đã thanh toán, sau khi trừ giao dịch đảo chiều | Confirmed | Stakeholder + design doc | Không dùng order total / cash-in gross |
| DEC-002 | Mốc chuẩn dùng invoice.paid_at | Confirmed | Stakeholder + code | Không dùng order.created_at |
| DEC-003 | Không tính top-up / prepaid / mua gói ở thời điểm nạp | Confirmed | Stakeholder | Chỉ tính khi đi vào payment hợp lệ |
| DEC-004 | Ví chính được tính khi thực trả cho invoice hợp lệ; ví khuyến mãi không tính | Confirmed | Stakeholder + code review | Khóa rule wallet semantics |
| DEC-005 | LTV chuẩn là all-time và toàn hệ thống | Confirmed | Stakeholder | Không khóa theo kỳ hay một chi nhánh |
| DEC-006 | Doanh thu referral downstream không cộng vào LTV gốc của khách giới thiệu | Confirmed | Stakeholder | Tránh double count |
| DEC-007 | 1 khách = 1 LTV = 1 Nguồn gốc LTV chuẩn = 1 Kênh nguồn chi tiết | Confirmed | Stakeholder | Không có nhiều canonical attribution |
| DEC-008 | Tách Nguồn khách gốc khỏi Nhóm nguồn LTV chuẩn | Confirmed | Stakeholder + design doc | Raw source vẫn động, normalized source là lớp quản trị |
| DEC-009 | Mapping raw source -> normalized source phải có versioning | Confirmed | Design doc | Không overwrite lịch sử |
| DEC-010 | Khách cũ được backfill tối đa theo first paid, nhưng không suy diễn quá mức | Confirmed | Stakeholder + design doc | Ưu tiên evidence lịch sử / khó sửa |
| DEC-011 | Không đủ chắc chắn thì vào Chưa xác định | Confirmed | Stakeholder + design doc | Unknown là output hợp lệ |
| DEC-012 | Bộ lọc thời gian phase 1 áp vào cohort first paid | Confirmed | Design doc review | Không cắt revenue all-time |
| DEC-013 | LTV theo chi nhánh phase 1 = theo chi nhánh first paid | Confirmed | Design doc review | Không phân bổ đa chi nhánh |
| DEC-014 | LTV theo nhóm dịch vụ phase 1 = theo nhóm dịch vụ khởi đầu | Confirmed | Design doc review | Không phân bổ đa nhóm dịch vụ |
| DEC-015 | Phase 1 chỉ làm metric + bảng phân tích | Confirmed | Stakeholder | Scope guard |
| DEC-016 | Ma trận mapping raw source được cấu hình trên hệ thống bởi role Admin/IT | Confirmed | Stakeholder + design doc | Role thao tác hệ thống |
| DEC-017 | Màn report LTV Phase 1 đặt trong customer_cycle_report_group | Confirmed | Stakeholder + codebase review | Nhóm báo cáo Chu kỳ khách hàng |
| DEC-018 | Report role seed v1 của customer_cycle_ltv_report reuse đúng role set đang có của nhóm customer_cycle_report_group: bod, hr_leader, it_leader | Confirmed | Codebase review | Mở rộng role khác là phase sau / config sau UAT |
| DEC-019 | Mapping version đầu tiên phải freeze toàn bộ master_data(type = customer_source) đang active tại thời điểm cutover vào snapshot rule v1 | Confirmed | FE master data query + DB pattern | Không đọc live master data trực tiếp để suy luận lịch sử |
| DEC-020 | Confidence model v1 chốt 3 mức: high, medium, unknown theo rubric explicit | Confirmed | Stakeholder + design doc + implementation need | Không để BE/QA tự đoán |
| DEC-021 | Refresh strategy phase 1 dùng hybrid: event-driven incremental refresh cho case phát sinh mới + scheduled reconcile định kỳ + manual backfill explicit | Confirmed | Codebase review | Không chọn chỉ cron hoặc chỉ event-driven |
2) Business Truths
| Topic | Canonical truth | Certainty | Confirmed by | Notes |
|---|---|---|---|---|
| Core question | Business cần biết 1 khách hàng đáng giá bao nhiêu tiền cho DIVA | Confirmed | Stakeholder | Nền cho CAC/LTV, retention, branch quality |
| Accounting meaning | LTV ở phase 1 phản ánh giá trị thương mại đã thu, không phản ánh tiêu dùng đã sử dụng hết | Confirmed | Stakeholder | Khác với consumption accounting |
| Referral | Doanh thu của người được giới thiệu không cộng vào LTV gốc của khách giới thiệu | Confirmed | Stakeholder | Có thể là chỉ số mở rộng phase sau |
| Unknown attribution | Chưa xác định là kết quả hợp lệ, không phải lỗi | Confirmed | Stakeholder + design doc | KPI chất lượng dữ liệu |
| Scope guard | Phase 1 không hứa attribution đa chạm hay ROI causal theo campaign | Confirmed | Stakeholder | Tránh overpromise |
3) Current-Code Facts
| Area | Current behavior | File / code ref | Keep / Replace / Migrate |
|---|---|---|---|
| Revenue storage | Có customer_revenue theo customer và action type payment/refund | diva-backend/pkg/store/customer_revenue.go | Keep + Extend |
| Revenue aggregate | Có materialized view customer_revenue_stats theo customer_id | 1706669141375_customer_revenue_stats/up.sql | Keep + Extend |
| First paid | Có helper dựa trên invoice.paid_at | diva-backend/pkg/store/kpi_metric.go | Keep |
| Raw source storage | customer_source nằm trên ecommerce_user, dạng mảng | diva-backend/pkg/store/ecommerce_user.go | Keep as raw |
| Source dashboard | Report nguồn hiện đọc raw source hiện tại | 1695093908449_run_sql_migration/up.sql | Keep for ops only |
| Source history | Chưa có bằng chứng có lịch sử source theo thời gian | Discovery | Must respect as gap |
| Report route | FE route group hiện dùng customer_cycle_report_group | diva-admin/src/modules/report/types.ts | Keep |
| Report seed | Migration mới nhất seed group_id = customer_cycle_report_group; migration cũ dùng customer_cycle_report | 1752227264000_add_report_table/up.sql, 1750736860000_create_function/up.sql | Follow newer normalized pattern |
| Report role pattern | Nhóm customer_cycle_report_group hiện seed role bod, hr_leader, it_leader | 1752227264000_add_report_table/up.sql | Reuse for v1 |
| Raw source master data | FE đang load danh sách nguồn khách từ master_data(where: {type = customer_source}) | useMasterDataCustomer.ts | Use as v1 seed source |
| Invoice/event infrastructure | invoice đã có Hasura event trigger insert/update; hệ thống cũng có cron schedulers qua /schedulers | public_invoice.yaml, cron_triggers.yaml | Supports hybrid refresh |
| Revenue trigger pattern | Có bằng chứng DB trigger customer_revenue_after_insert được dùng trong data maintenance/tests | customer_revenue_test.go | Supports event-driven incremental update |
4) Solution Lock Snapshot
| Business ask | Existing code / screen / DB fact | Locked approach | Reuse strategy |
|---|---|---|---|
| Chuẩn hóa LTV | Đã có nền customer revenue | Tạo lớp LTV chuẩn dựa trên actual revenue hợp lệ + reverse adjustments | 🔧 Extend |
| Gắn nguồn gốc cho LTV | Raw source đang động và không đủ tin để làm canonical | Tạo snapshot Nguồn gốc LTV chuẩn theo khách tại first paid | 🆕 Build mới |
| Giữ lịch sử ổn định khi mapping thay đổi | Chưa có versioning | Tạo mapping version + effective date + snapshot lưu version | 🆕 Build mới |
| Lifecycle cho mapping version | Chưa có flow cấu hình chuyên biệt | Khóa lifecycle draft -> published -> archived; version published là read-only, chỉnh sửa tiếp theo phải clone sang draft mới | 🆕 Build mới |
| Phân tích business ở phase 1 | Chưa có màn/report LTV riêng | Tạo report theo customer-level metric + bảng tổng hợp quản trị trong customer_cycle_report_group | 🔧 Extend |
| Backfill khách cũ | Chưa có source history rõ ràng | Backfill tối đa theo bằng chứng tốt nhất; không đủ chắc chắn thì Chưa xác định | 🔧 Extend |
| Vận hành backfill | Chưa có backfill job flow riêng cho LTV | Dùng job explicit có trạng thái queued -> running -> done/failed; publish version mới không auto rerun lịch sử | 🆕 Build mới |
| Seed raw source v1 | Raw source hiện đang là master data động | Freeze snapshot toàn bộ customer_source active tại thời điểm cutover thành version v1; rule mới về sau đi qua draft mới | 🔧 Extend |
| Confidence model | Chưa có rubric thống nhất cho source inference | Chốt rubric high/medium/unknown ở mức implementation contract để BE/QA dùng chung | 🆕 Build mới |
| Refresh runtime | Đã có event + scheduler infra | Dùng hybrid: event-driven cho payment/refund/override và cron reconcile để tự hàn lệch | 🔧 Extend |
5) Master Data / Config Fit Check
| Classification | Existing pattern | Locked storage / admin pattern | Impacted business screens |
|---|---|---|---|
master data raw source | customer_source trên ecommerce_user + master data | Giữ nguyên cho vận hành | Customer profile, CRM, report/filter hiện tại |
normalized mapping | Chưa có | Bảng mapping riêng có versioning | Report LTV, backfill job, manual override flow |
business entity snapshot | Chưa có | Bảng snapshot nguồn gốc LTV theo khách | Customer-level LTV analytics |
seed source catalog | master_data(type = customer_source) đang là nguồn options hiện hành | Freeze tại cutover thành version v1, lưu raw_source_id + raw_source_name_snapshot | Mapping drawer, audit compare, backfill explainability |
6) Day-1 Simplifications
| Item | Temporary Day-1 simplification | Why | Phase sau |
|---|---|---|---|
| Attribution | Chỉ first-touch canonical, không làm last-touch/multi-touch | Giảm tranh cãi và complexity | Phase 2+ |
| Time semantics | Chỉ hỗ trợ filter theo cohort first paid | Giữ đúng nghĩa all-time LTV | Phase 2+ có thể thêm LTV phát sinh trong kỳ |
| Branch semantics | Chỉ dùng chi nhánh first paid | Tránh phân bổ đa chi nhánh ngay từ đầu | Phase 2+ |
| Service semantics | Chỉ dùng nhóm dịch vụ khởi đầu | Tránh phân bổ đa nhóm dịch vụ | Phase 2+ |
| Backfill confidence | Không cố gán đủ 100% khách cũ | Dữ liệu lịch sử nguồn không đủ chắc | Phase 2+ nếu có thêm evidence |
| Role rollout | V1 chỉ seed report role theo pattern nhóm hiện có (bod, hr_leader, it_leader) | Giảm ceremony và bám pattern code hiện tại | Sau UAT có thể mở rộng thêm role bằng config |
7) Explicit Non-Goals / Deferred
| Item | Status | Why |
|---|---|---|
| Multi-touch attribution | Deferred | Không phù hợp phase 1 |
| Last-touch canonical source | Deferred | Không phải lớp quản trị chuẩn |
| LTV forecast / predictive model | Deferred | Cần nền data ổn định trước |
| Dashboard chiến lược trọn 6 bài toán | Deferred | Phase 1 chỉ làm metric + bảng phân tích |
| Extended customer value gồm referral downstream | Deferred | Chưa phải canonical LTV gốc |
8) Open Questions
| Question | Blocking? | Temporary default |
|---|---|---|
| Không còn open question blocking ở phase 1 | No | Canonical decisions đã khóa trong PRD v1.2 |
9) Propagation Notes
| If this changes | Must update |
|---|---|
Định nghĩa LTV chuẩn | PRD, UI Spec, Dev Spec, QA, HTML brief |
| Semantics time/branch/service | PRD, UI Spec, Dev Spec, QA |
| Mapping version strategy | PRD, UI Spec, Dev Spec, backfill logic, QA |
| Mapping lifecycle / publish safety | PRD lifecycle, UI SCR-02, Dev state transitions, QA TC |
| Report role seed / rollout | SOURCE_OF_TRUTH, PRD, UI permission matrix, Dev Spec RBAC, handoff |
| Raw source v1 seed strategy | SOURCE_OF_TRUTH, PRD, Dev Spec migration, QA seed data, handoff |
| Confidence rubric | PRD, Dev Spec resolver logic, QA test cases, handoff |
| Backfill confidence model | PRD, Dev Spec, QA, handoff |
| Backfill job states / rerun rule | PRD lifecycle, UI SCR-01 data quality, Dev state transitions, QA TC, handoff |
| Refresh strategy hybrid | PRD, Dev Spec scheduler/event, QA, handoff |
| Report placement / Admin actions | HTML brief, UI Spec, Dev Spec, handoff |