Appearance
v1.3 — 23/03/2026
| Thay đổi | Section | Ảnh hưởng |
|---|---|---|
| Thêm FR-009 vào scope + TC-FR-009 (tab container + redirect) | D1, TC-FR-009 | QA |
QA Test Plan — Báo cáo doanh số cá nhân
Ref: PRD v1.3 | Date: 2026-03-23
D1) Test Scope
| FR | Mô tả | Priority |
|---|---|---|
| FR-001 | Pivot table hiển thị đúng | Must |
| FR-002 | Filter chi nhánh + chức vụ + tháng | Must |
| FR-003 | Dropdown loại doanh số | Must |
| FR-004 | Export Excel | Must |
| FR-005 | SQL function commission | Must |
| FR-006 | SQL function tour | Must |
| FR-007 | SQL function truy thu commission (wallet) | Must |
| FR-008 | Drill-down popup chi tiết ngày | Must |
| FR-009 | Hub tab container + redirect route cũ | Must |
D2) Test Cases
TC-FR-001: Pivot table hiển thị đúng
| TC | Mô tả | Input | Expected | Priority |
|---|---|---|---|---|
| TC-001-01 | Hiển thị data commission tháng 03/2026 | Chọn tháng 03/2026, loại Commission | Bảng pivot: hàng = NV, cột = 31 ngày, giá trị = commission/ngày, cột Tổng = sum | P0 |
| TC-001-02 | NV không có commission trong tháng | NV DV999999 không có data | Không hiển thị row NV đó (chỉ hiển thị NV có data) | P0 |
| TC-001-03 | Ô không có data | NV có commission ngày 1 nhưng không ngày 2 | Ngày 2 hiển thị 0 | P0 |
| TC-001-04 | Format số VND | Commission = 3700000 | Hiển thị 3.700.000 | P1 |
| TC-001-05 | Sort mặc định | Mở page | Sắp xếp theo Mã NV ASC | P1 |
| TC-001-06 | Tháng 2 (28 ngày) | Chọn 02/2026 | Bảng có 28 cột ngày | P1 |
| TC-001-07 | Tháng 2 nhuận (29 ngày) | Chọn 02/2028 | Bảng có 29 cột ngày | P2 |
| TC-001-08 | Scroll horizontal | > 15 cột ngày visible | Sticky: Mã NV + Họ tên (trái), Tổng (phải) | P1 |
TC-FR-002: Filter
| TC | Mô tả | Input | Expected | Priority |
|---|---|---|---|---|
| TC-002-01 | Filter chi nhánh | Chọn branch A | Chỉ hiển thị NV thuộc branch A | P0 |
| TC-002-02 | Filter chức vụ | Chọn job position "KTV" | Chỉ hiển thị NV có chức vụ KTV | P0 |
| TC-002-03 | Filter tháng | Chọn 02/2026 | Data thay đổi sang tháng 2, cột = 28 ngày | P0 |
| TC-002-04 | Prev/next tháng | Click ▶ từ 03/2026 | Chuyển sang 04/2026, fetch lại data | P0 |
| TC-002-05 | Multi-select chi nhánh | Chọn branch A + B | Hiển thị NV thuộc branch A hoặc B | P1 |
| TC-002-06 | Clear filter | Bỏ hết filter chi nhánh | Hiển thị tất cả NV | P1 |
| TC-002-07 | Thay đổi filter → auto fetch | Thay đổi chi nhánh | Table loading → data mới | P0 |
TC-FR-003: Dropdown loại doanh số
| TC | Mô tả | Input | Expected | Priority |
|---|---|---|---|---|
| TC-003-01 | Default là Commission | Mở page | Dropdown hiện "Commission tư vấn", data = commission | P0 |
| TC-003-02 | Switch sang Tour | Chọn "Tiền tour" | Data thay đổi sang tour income | P0 |
| TC-003-03 | Switch giữ filter | Đang filter branch A, switch Tour | Vẫn filter branch A, data = tour | P0 |
| TC-003-04 | Switch đang loading | Switch nhanh Commission → Tour → Commission | Cancel request cũ, hiển thị data cuối cùng | P1 |
| TC-003-05 | Switch sang Truy thu | Chọn "Truy thu commission" | Data thay đổi sang clawback, filter chức vụ bị ẩn | P0 |
| TC-003-06 | Truy thu giữ filter branch | Đang filter branch A, switch Truy thu | Vẫn filter branch A, data = clawback | P0 |
| TC-003-07 | Truy thu → switch lại Commission | Chọn Truy thu → chọn lại Commission | Filter chức vụ hiện lại, data = commission | P1 |
TC-FR-004: Export Excel
| TC | Mô tả | Input | Expected | Priority |
|---|---|---|---|---|
| TC-004-01 | Export có data | Table có 10 NV | File .xlsx: 10 data rows, đúng format pivot | P0 |
| TC-004-02 | Tên file đúng format | Export tháng 03/2026 | doanh-so-nv-03-2026_{timestamp}.xlsx | P1 |
| TC-004-03 | Header style | Mở file Excel | Header: bold, có background color | P1 |
| TC-004-04 | Số format VND | Mở file Excel | Số align right, format #,##0 | P1 |
| TC-004-05 | Export khi empty | Table không có data | File Excel chỉ có header, không có data rows | P2 |
| TC-004-06 | Export khớp với view | So sánh table vs Excel | Data giống y hệt | P0 |
TC-FR-005: SQL function commission
| TC | Mô tả | Input | Expected | Priority |
|---|---|---|---|---|
| TC-005-01 | Aggregate đúng theo ngày | NV có 3 commission ngày 01/03 | 1 row: sum 3 amounts | P0 |
| TC-005-02 | Timezone Asia/Ho_Chi_Minh | Commission paid_at = 2026-03-01 23:30:00 UTC | Thuộc ngày 02/03 (06:30 sáng ICT) | P0 |
| TC-005-03 | Filter branch | branch_ids = [branch_A_id] | Chỉ trả NV branch A | P0 |
| TC-005-04 | Filter job position | job_positions = ['dept_id'] | Chỉ trả NV department đó | P0 |
| TC-005-05 | Soft delete NV | NV có deleted_at != NULL | Không trả NV đã xóa | P0 |
| TC-005-06 | Empty branch filter | branch_ids = '{}' | Trả tất cả NV (không filter) | P1 |
| TC-005-07 | Loại trừ thanh toán bằng ví (DEC-012) | NV có commission từ invoice ví DIVA (payment_method_id = 'wallet') | Không tính commission từ invoice ví → total_amount giảm | P0 |
| TC-005-08 | Loại trừ ví khuyến mãi (DEC-012) | NV có commission từ invoice ví KM (payment_method_id = 'wallet_promotion') | Không tính commission từ invoice ví KM | P0 |
| TC-005-09 | NV chỉ có commission từ ví | Tất cả invoices của NV đều thanh toán bằng ví | NV không xuất hiện trong kết quả (không có row) | P1 |
TC-FR-006: SQL function tour
| TC | Mô tả | Input | Expected | Priority |
|---|---|---|---|---|
| TC-006-01 | Aggregate đúng theo ngày | NV có 2 tour done ngày 01/03 | 1 row: sum 2 tour_money | P0 |
| TC-006-02 | Timezone Asia/Ho_Chi_Minh | Tour done_at = 2026-03-01 23:30:00 UTC | Thuộc ngày 02/03 (06:30 sáng ICT) | P0 |
| TC-006-03 | Chỉ task done | Task status is_done = false | Không tính | P0 |
| TC-006-04 | tour_money = 0 | pta.tour_money = 0 | Không tính | P1 |
| TC-006-05 | tour_money = NULL | pta.tour_money IS NULL | Không tính | P1 |
| TC-006-06 | Supervisor/assigner excluded | pta.supervisor = true | Không tính | P1 |
| TC-006-07 | Cùng shape với commission | So sánh output 2 functions | Cùng columns: user_id, employee_code, display_name, report_date, total_amount | P0 |
TC-FR-007: SQL function truy thu commission (v1.1)
| TC | Mô tả | Input | Expected | Priority |
|---|---|---|---|---|
| TC-007-01 | Aggregate truy thu đúng theo ngày | NV có 2 truy thu cùng ngày 20/03 | 1 row: sum 2 amounts | P0 |
| TC-007-02 | Timezone Asia/Ho_Chi_Minh | Truy thu updated_at = 2026-03-20 23:30:00 UTC | Thuộc ngày 21/03 (06:30 sáng ICT) | P0 |
| TC-007-03 | Filter branch | branch_ids = [branch_A_id] | Chỉ trả NV branch A (qua wallet_user.branch_id) | P0 |
| TC-007-04 | Chỉ lấy status S | Có request status R (pending) và S (success) | Chỉ trả status = S | P0 |
| TC-007-05 | Chỉ lấy refund_commission | Có behavior_id = 'transaction_commission' và 'refund_commission' | Chỉ trả refund_commission | P0 |
| TC-007-06 | Cùng shape với commission/tour | So sánh output 3 functions | Cùng columns: user_id, employee_code, display_name, report_date, total_amount | P0 |
| TC-007-07 | NV không bị truy thu (approver không nhập) | Hoàn tiền nhưng không nhập truy thu | Không có row cho NV đó | P1 |
| TC-007-08 | Amount luôn dương | Kiểm tra output | total_amount >= 0 | P1 |
TC-FR-008: Drill-down popup chi tiết ngày (v1.1)
| TC | Mô tả | Input | Expected | Priority |
|---|---|---|---|---|
| TC-008-01 | Click ô commission → mở popup | Click 3.700.000 (NV Giang, 01/03) | Popup mở: title "Chi tiết doanh số — Nguyễn Thị Giang — 01/03/2026", danh sách đơn hàng | P0 |
| TC-008-02 | Popup hiện bút toán âm | NV có truy thu ngày 20/03 | Row "Truy thu commission" với amount âm, màu đỏ | P0 |
| TC-008-03 | Popup merge commission + truy thu | Dropdown = Commission, click ô ngày có cả 2 | Hiện cả commission (dương) + truy thu (âm) trong 1 popup | P0 |
| TC-008-04 | Click ô = 0 | Click ô có giá trị 0 | Popup hiện "Không có giao dịch" | P1 |
| TC-008-05 | Click cột Tổng | Click cột Tổng của NV | Popup hiện tất cả giao dịch cả tháng | P0 |
| TC-008-06 | Popup khi dropdown = Tour | Chọn Tiền tour, click ô | Popup chỉ hiện chi tiết tour, không có truy thu | P1 |
| TC-008-07 | Popup khi dropdown = Truy thu | Chọn Truy thu, click ô | Popup chỉ hiện bút toán truy thu | P1 |
| TC-008-08 | Mã đơn gốc trong truy thu | Truy thu có order_id link | Cột "Mã đơn hàng" hiện mã đơn gốc bị hoàn | P1 |
| TC-008-09 | Mã đơn gốc NULL | Truy thu không có order_id | Cột "Mã đơn hàng" hiện "—" | P2 |
| TC-008-10 | Mã giao dịch fallback | transaction_request.code = NULL | Hiện transaction_request.id (UUID) | P2 |
TC-FR-009: Hub tab container + redirect
| TC | Mô tả | Input | Expected | Priority |
|---|---|---|---|---|
| TC-009-01 | Card hiển thị trên Reports | Mở trang Reports | Card "Báo cáo doanh số cá nhân" hiển thị, 2 cards cũ (Doanh thu NV + Tour) không hiển thị | P0 |
| TC-009-02 | Default tab | Click card → vào page | Tab "Doanh số theo ngày" active, pivot table hiển thị | P0 |
| TC-009-03 | Switch tab Revenue | Click tab "Doanh thu theo đơn hàng" | Component EmployeeRevenueReport render đúng, có filter + chart + table | P0 |
| TC-009-04 | Switch tab Tour | Click tab "Tiền tour" | Component TourIncomeReport render đúng, có filter + chart + table | P0 |
| TC-009-05 | Redirect route cũ → revenue | Truy cập /r/reports/employee_revenue_report_group | Redirect → tab "Doanh thu theo đơn hàng" active | P0 |
| TC-009-06 | Redirect route cũ → tour | Truy cập /r/reports/tour_income_report_group | Redirect → tab "Tiền tour" active | P0 |
| TC-009-07 | Query param sync | URL ?tab=tour | Tab "Tiền tour" active | P1 |
| TC-009-08 | Query param invalid | URL ?tab=invalid | Fallback về tab "Doanh số theo ngày" | P2 |
| TC-009-09 | Tab switch giữ state | Chọn filter ở tab Daily, switch sang Revenue, switch lại Daily | Filter ở Daily vẫn giữ nguyên | P1 |
| TC-009-10 | Permission — chỉ có quyền 1 report | User chỉ có quyền xem tour report | Card "Báo cáo doanh số cá nhân" vẫn hiển thị | P1 |
D3) Seed Data
Dataset: DS-001 — Commission test data
Cách tạo: SQL Script
sql
-- Tạo commission cho NV test trong tháng 03/2026
-- NV 1: có commission nhiều ngày
-- NV 2: có commission 1 ngày
-- NV 3: không có commission (để verify không hiển thị)
-- Verify: SELECT * FROM search_employee_daily_commission('2026-03-01', '2026-03-31');Dataset: DS-002 — Tour test data
sql
-- Tạo tour income cho NV test trong tháng 03/2026
-- NV 1: có tour done nhiều ngày
-- NV 2: có tour nhưng is_done = false (không tính)
-- NV 3: có tour nhưng supervisor = true (không tính)
-- Verify: SELECT * FROM search_employee_daily_tour_income('2026-03-01', '2026-03-31');Dataset: DS-003 — Clawback test data (wallet) — v1.1
sql
-- Tạo truy thu commission cho NV test trong tháng 03/2026
-- NV 1: có truy thu ngày 20/03 (1 request, 2 transactions)
-- NV 2: có truy thu ngày 25/03 (1 request, order_id link đơn gốc)
-- NV 3: hoàn tiền nhưng approver KHÔNG nhập truy thu (không tạo transaction)
-- NV 4: có request nhưng status = 'R' (pending, chưa duyệt)
-- Verify: SELECT * FROM search_employee_daily_commission_clawback('2026-03-01', '2026-03-31');D4) Traceability
| FR | FE Artifact | BE Artifact | TC-ID | Status |
|---|---|---|---|---|
| FR-001 | SCR-01 PivotTable | — | TC-001-* | ✅ |
| FR-002 | SCR-01 FilterBar | — | TC-002-* | ✅ |
| FR-003 | SCR-01 Dropdown | — | TC-003-* | ✅ |
| FR-004 | SCR-01 ExportBtn | ExcelBuilder | TC-004-* | ✅ |
| FR-005 | — | search_employee_daily_commission | TC-005-* | ✅ |
| FR-006 | — | search_employee_daily_tour_income | TC-006-* | ✅ |
| FR-007 | — | search_employee_daily_commission_clawback | TC-007-* | ✅ |
| FR-008 | SCR-02 Popup | GetClawbackDetail + search_report_employee | TC-008-* | ✅ |
| FR-009 | SCR-00 Hub + Redirect | — | TC-009-* | ✅ |