Appearance
Handoff — Tab Chu kỳ khách ghé không mua
Version: 2.8
Date: 11/05/2026
Canonical Inputs: SOURCE_OF_TRUTH.md, EVIDENCE_PACK.md, prd.md.
v2.8 — 11/05/2026
| Thay đổi | Section | Ảnh hưởng |
|---|---|---|
| Thêm 8 implementation step (10-17) cho clarity tweak | 3) Implementation order | All |
| Thêm timeline row +1-2 days dev + 1 day QA | 4) Timeline | PM, TL |
| Thêm 5 blocker mới (sub-text fit, column rename scope, tooltip coverage) | 5) Blockers | All |
| Thêm 8 DoD v2.8 (DEC-027..030, TC-020..024, mobile, no regression) | 6) Definition of done | All |
File này là index giao team: ai làm gì, thứ tự nào, blocker nào. Scope/timeline trong file này thắng các timeline tóm tắt rải rác nếu có.
1) Delivery package
| File | Owner đọc chính | Status |
|---|---|---|
decision-brief.md | PO/TL/Sếp | Ready |
EVIDENCE_PACK.md | PO/BA/TL | Ready |
SOURCE_OF_TRUTH.md | All | Ready |
prd.md | PO/BA/TL | Ready |
ui-spec.md | UI/FE/QA | Ready |
dev-spec.md | BE/FE/TL | Ready |
qa-test-plan.md | QA | Ready |
_consistency-matrix.md | PO/BA/TL | Ready |
2) RACI
| Workstream | Responsible | Accountable | Consulted |
|---|---|---|---|
| Business sign-off | PO/BA | Product Lead | Marketing, CSKH |
| BE actions/metadata | BE Dev | Tech Lead | QA |
| FE tab/matrix/popup | FE Dev | Tech Lead | UI/UX, QA |
| QA seed/regression | QA | QA Lead | BE, FE |
| UAT | PO/BA | Product Lead | Marketing, CSKH |
3) Implementation order
| Step | Task | Owner | Exit condition |
|---|---|---|---|
| 0 | Implement resolveBranchScope helper (DEC-016 — review C-01: KHÔNG dùng IsAdmin()) | BE | Unit test pass cả 6 case verification matrix; explicit test case Manager Q1 với Hasura role user không bypass |
| 1 | Add Hasura action types/metadata | BE | Metadata validates |
| 2 | Implement reportVisitCycleNoPurchase (call resolveBranchScope first; CTE exclude converted) | BE | Aggregate seed test pass + TC-010/TC-012 |
| 3 | Implement reportVisitCycleNoPurchaseDetail (resolveBranchScope + branch_ids input DEC-026 + customer_ids intersect + visit_source normalize) | BE | Detail seed test pass + TC-013 + TC-019 cross-branch consistency |
| 4 | Add FE GraphQL queries/codegen | FE | Generated types compile |
| 5 | Add tab key/panel + fix DEC-015 tab persistence | FE | Tab visible and survives refresh; tab Chu kỳ khách hàng cũng survive (regression) |
| 6 | Build overview/matrix | FE | Data renders with empty/loading/error |
| 7 | Build popup + utility formatVisitSource (DEC-017) | FE | Search/open customer works; multi-source render đúng |
| 8 | QA P0 (TC-001..006, 008, 010, 012, 013, TC-019 cross-branch popup drift) + regression purchase tab + tab persistence regression | QA | All P0 pass |
| 8b | QA P1 (TC-007 by_month bucket DEC-018, TC-009 error state, TC-011 same-day order, TC-014 copy/core tooltip, TC-015 click guard, TC-016 performance benchmark, TC-017 responsive tab label, TC-018 filter validation) | QA + BE | TC-016 pass mới được merge GA. Fail TC-016 → BE switch SQL fallback và re-test. Tooltip ngoài core là backlog, không block GA. |
| 9 | UAT with Marketing/CSKH | PO/BA | Sign-off |
| 10 | Build component VisitNoPurchaseInfoStrip.tsx (FR-007, DEC-028) + integrate vào tab panel | FE | Strip visible permanent above filter bar, không có dismiss; TC-020 pass |
| 11 | Build component reusable LabelWithSubText.tsx (DEC-029) | FE | Component compile + render với label + subtext + tooltip props |
| 12 | Integrate <LabelWithSubText> vào 3 cards overview + matrix headers + 2 matrix rows (DEC-029) | FE | Sub-text visible đúng copy theo B6; TC-021 pass |
| 13 | Add q-icon info + tooltip cho 6 popup column headers (DEC-029, DEC-030) | FE | 6 ℹ️ icon visible inline, hover hiện tooltip; TC-023 pass |
| 14 | Rename matrix column cuối Tỷ lệ → % trên tổng (DEC-029 rename T6); regression tab purchase | FE | Cột mới hiển thị % trên tổng ở tab mới; tab Chu kỳ mua hàng KHÔNG đổi; TC-022 pass |
| 15 | Add 9 i18n keys mới (xem UI B6) | FE | i18n keys available và hiển thị đúng tiếng Việt |
| 16 | QA v2.8: TC-020 → TC-024 + regression TC-001 → TC-019 | QA | 5 TC mới pass + 19 TC cũ regression pass; 19 tooltip 100% coverage |
| 17 | UAT v2.8 với PO/Marketing/CSKH | PO/BA | Sign-off; verify "mờ hồ" feedback resolved |
4) Timeline estimate
| Phase | Duration | Notes |
|---|---|---|
| BE contract + implementation | 3-4 days | Aggregate/detail action + resolveBranchScope + buildBuckets riêng |
| FE implementation | 2-3 days | Reuse shell but new copy/data + core tooltip set + click guard |
| QA + regression + benchmark | 2-3 days | Needs seed 100k + 500k cho TC-016 |
| Performance fallback (nếu fail TC-016) | +2 days | BE rewrite sang PostgreSQL function/CTE; QA re-test |
| UAT + fixes | 1 day | Focus copy/semantics + core tooltip readability |
| Clarity tweak v2.8 (info strip + sub-text + popup tooltip + column rename) | +1-2 ngày dev + 1 ngày QA | Mostly static components + i18n keys, low risk; designer pair review wireframe trước khi commit |
5) Blockers / watch items
| Item | Severity | Action |
|---|---|---|
| Branch scope enforcement in BE action (DEC-016 — review C-01 footgun) | Cao | Implement helper resolveBranchScope(ctx, requested) BE-000. TUYỆT ĐỐI KHÔNG dùng Actor.IsAdmin() vì returns true cho cả RoleUser → bypass toàn bộ Manager/Staff. Dùng pattern empty user.branches = no restriction. Verify với TC-012 expanded. |
| Detail action branch_ids (DEC-026 — review C-03) | Cao | Detail input phải có branch_ids; BE re-apply resolveBranchScope; QA TC-019 cross-branch drift. |
| Order canonical enum (review C-02) | Cao | Mọi SQL/code dùng 'order_canceled'/'prepaid_canceled' (KHÔNG dùng 'canceled') — pkg/store/order.go:174,191. Sweep rg "canceled" trước commit. |
| Formula 002+ filter target_customers (review M-01) | Trung bình | PRD/Dev đã update; aggregate Go phải filter customer_id IN target_customers cho mọi formula sau FORMULA-001. Verify TC-010 expected count khớp. |
| Empty payload vs error | Cao | Add unit/integration test |
| Exclude converted customers (DEC-014) phải đúng từ aggregate, không re-compute ở detail | Cao | Aggregate trả customer_ids đã exclude → detail nhận và query trực tiếp; verify matrix tổng = popup tổng cho mỗi bucket |
CustomerCycleReport.tsx tab persistence inconsistency (DEC-015) | Cao | Fix to: CUSTOMER_CYCLE_CUSTOMER + whitelist 4 key đang render trong cùng PR; QA TC-001 regression tab Chu kỳ khách hàng |
visit_source ordering (DEC-017) | Trung bình | BE normalize trước return; FE utility formatVisitSource defense in depth; QA TC-013 |
| Performance NFR (DEC-020) | Cao | Block GA nếu benchmark fail target P95 < 3s @ 100k AND < 5s @ 500k. Fail → switch sang SQL aggregation (xem dev-spec C9 fallback). QA TC-016. |
| Bucket label divergence với purchase tab (DEC-018) | Thấp | Tab mới dùng ≤ 3 tháng / 4-6 / 7-9 / > 9 (mới); tab cũ giữ quirk hiện tại. PR mô tả rõ. QA TC-007 verify. |
| Cell click guard (DEC-019) | Thấp | Component matrix conditional click handler theo cell value; QA TC-015. |
| Tab label responsive (DEC-022) | Thấp | Quasar $q.screen.lt.md chọn i18n key; QA TC-017. |
| Date range max + clamp (DEC-023) | Thấp | FE validate onChange + toast; BE defense in depth; QA TC-018. |
| Bước chu kỳ validation (DEC-024) | Thấp | FE inline error theo type_cycle; BE validate; QA TC-018. |
| Popup title format (DEC-021) | Thấp | Component popup nhận rowLabel + columnLabel riêng để dễ test. |
| Export request from stakeholder during build | Trung bình | Treat as phase 2 decision, not quick add |
| Info strip placement không break responsive (DEC-028) | Thấp | QA TC-020 mobile verify; designer pair review |
| Sub-text dưới donut chart fit (Chart.js doughnut + label plugin — DEC-029) | Trung bình | Designer pair review wireframe trước implementation; FE có thể trim sub-text donut nếu thấy clutter với chart label |
Column rename T6 phải scope nghiêm tab mới — không break tab Chu kỳ mua hàng (DEC-029) | Trung bình | TC-022 explicit regression; review code change phải chỉ touch component tab mới |
| 19 tooltip required coverage có thể miss item nếu B9 rewrite không cẩn thận (DEC-030) | Trung bình | TC-024 enumerate đủ 19 vị trí; QA checklist explicit |
| Sub-text "Trên tổng {total} KH" có thể trùng giá trị Card 1 → user thấy duplicate | Thấp | Design review: nếu redundant, có thể trim donut subtext xuống chỉ ghi Trên tổng |
6) Definition of done
- Tab mới visible to authorized report users.
- Qualified visit rule matches
is_zero_order=trueand sourceconsultant/do_service. - DEC-014 exclude converted: khách có order hợp lệ tạo sau
last_qualified_visit_datekhông xuất hiện ở matrix lẫn popup. - DEC-015 tab persistence: 4 tab đang render đều persist đúng sau refresh;
tomapping đúng. - DEC-016 branch scope: Manager attempt qua DevTools với branch ngoài scope → empty payload, không leak data.
- DEC-017
Loại ghéformat: multi-source luônTư vấn + Làm dịch vụthứ tự cố định. - DEC-018 bucket by_month: tab mới render
≤ 3 tháng,4 - 6 tháng,7 - 9 tháng,> N tháng; tab cũ unchanged. - DEC-019: matrix cell value
0không có cursor pointer + không mở popup. - DEC-020: benchmark report đính kèm PR; P95 đạt target hoặc đã switch SQL fallback và re-pass.
- DEC-021: popup title format
{Row} • {Column}(không phải(Chu kỳ: ...)). - DEC-022: tab label responsive — đã verify cả desktop ≥768px và mobile <768px.
- DEC-023: date range max 365 ngày — clamp + toast warning hoạt động đúng.
- DEC-024: bước chu kỳ validation — FE inline error + BE reject
invalid_durationđều test pass. - Matrix total equals popup detail source counts for clicked bucket.
- Popup has no export and no purchase-oriented columns.
- Purchase tab regression pass.
- DEC-026: detail action có
branch_idsinput + popup count khớp matrix bucket cho mọi filter scope. - Order canonical enum: SQL/code dùng
'order_canceled'/'prepaid_canceled'(verify qua sweep + TC-010 CUST-I không bị wrongly excluded). - QA P0 pass (TC-001 → TC-006, TC-008, TC-010, TC-012, TC-013, TC-019) + P1 pass (TC-007, TC-009, TC-011, TC-014 core-only, TC-015, TC-016, TC-017, TC-018) và PO/CSKH UAT sign-off. Tooltip mở rộng ngoài UI B9 core không thuộc DoD phase 1.
- V2.8 (clarity tweak) DoD:
- DEC-027: v2.8 clarity umbrella shipped — 3 layer (strip + sub-text + tooltip) tất cả visible.
- DEC-028: Info strip permanent visible mọi data state, không có dismiss, không có localStorage.
- DEC-029: 8 sub-text + 6 popup column tooltip + column rename T6 đúng copy theo B6.
- DEC-030: 19 tooltip required 100% coverage, không còn classification "Optional"/"Backlog".
- TC-020 (P0), TC-022 (P0), TC-021/023/024 (P1) all pass.
- Mobile responsive: info strip wrap + sub-text wrap + tooltip not cut tất cả verified.
- Tab
Chu kỳ mua hàngKHÔNG có regression copy (cột cuối vẫnTỷ lệ). - UAT PO/Marketing/CSKH confirm "mờ hồ" feedback (11/05/2026) resolved.