Appearance
QA Test Plan — Báo cáo Đơn hàng Voucher/Quà tặng
Ref: PRD v1.0 | Date: 19/03/2026
D1) Test Scope
| FR | Mô tả | Priority |
|---|---|---|
| FR-001 | Tab mới hiển thị trong Revenue Report Group | Must |
| FR-002 | Summary Bar 4 metrics | Must |
| FR-003 | Bảng dữ liệu 13 cột (STT + 12 data) + visual grouping | Must |
| FR-004 | Filter 6 tiêu chí (cascading) | Must |
| FR-005 | Export Excel | Must |
| FR-006 | Database indexes (performance) | Must |
| FR-007 | Permission + Migration seed | Must |
D2) Test Cases
TC-FR-001: Tab hiển thị
| TC | Mô tả | Input | Expected | Priority |
|---|---|---|---|---|
| TC-001-01 | Tab hiển thị khi có quyền | Login Admin có quyền report | Tab "Voucher/Quà tặng" hiển thị ở cuối Revenue Report Group | P0 |
| TC-001-02 | Tab ẩn khi không có quyền | Login Staff không có quyền report | Tab không hiển thị (không có trong DOM) | P0 |
| TC-001-03 | Click tab → render đúng component | Click tab mới | VoucherGiftOrderReportFilter + VoucherGiftOrderReportTable render | P0 |
| TC-001-04 | Các tab khác không bị ảnh hưởng | Click qua lại giữa tab cũ và mới | Data + filter reset đúng khi đổi tab | P1 |
TC-FR-002: Summary Bar
| TC | Mô tả | Input | Expected | Priority |
|---|---|---|---|---|
| TC-002-01 | 4 BoxInfo hiển thị đúng | Date range có dữ liệu | 4 cards: lượt dùng (+ số đơn), giá trị giảm, thực thu, tỷ lệ giảm | P0 |
| TC-002-02 | Tỷ lệ giảm tính đúng | Giảm=200.000đ, Thực thu=800.000đ | 200.000/(800.000+200.000)×100 = 20.0% | P0 |
| TC-002-03 | Mẫu số = 0 | Tất cả gift type "Lời chúc" (discount=0), paid=0 | Tỷ lệ giảm hiển thị "—" | P1 |
| TC-002-04 | Không tính đơn hủy (mặc định) | 10 đơn có voucher, 3 đã hủy | Tổng đơn = 7, không tính 3 đơn hủy | P0 |
| TC-002-05 | Loading state | Tab vừa click | 4 BoxInfo hiện QSkeleton | P1 |
| TC-002-06 | Lượt dùng ≠ đơn hàng | 1 đơn có 3 items dùng voucher | "3 lượt (1 đơn)" | P0 |
TC-FR-003: Bảng dữ liệu
| TC | Mô tả | Input | Expected | Priority |
|---|---|---|---|---|
| TC-003-01 | 13 cột hiển thị đúng | Có dữ liệu | 13 cột (STT + 12 cột data) với format đúng | P0 |
| TC-003-02 | Chỉ hiển thị items có voucher/gift | order_item không có gifted_id và voucher_discount_amount=0 | Không hiển thị item đó | P0 |
| TC-003-03 | Chỉ hiển thị đơn service/cosmetic/prepaid | Đơn order_transfer có voucher | Không hiển thị (DEC-008) | P0 |
| TC-003-04 | Pagination 20 items/page | 50 order_items có voucher | Trang 1: 20 items, trang 2: 20 items, trang 3: 10 items | P0 |
| TC-003-05 | Visual grouping: dim repeated cells | 1 đơn có 3 items voucher | Dòng 1: đầy đủ 13 cột. Dòng 2-3: STT vẫn hiện, cột order-level trống, chỉ hiện item-level | P0 |
| TC-003-06 | Sort theo created_at DESC | Đơn A: 15/03, Đơn B: 14/03 | Đơn A hiện trước | P1 |
| TC-003-07 | Click mã đơn | Click "DH-001" | Mở trang chi tiết đơn hàng DH-001 | P1 |
| TC-003-08 | Cột Voucher/Quà: 2 dòng | Tên dài + mã voucher | Dòng 1: tên (ellipsis nếu dài). Dòng 2: mã voucher (grey) | P1 |
| TC-003-09 | Cột Campaign render theo gifted_from | item từ voucher campaign | Hiển thị tên campaign. Item từ "Bạn bè" → "Quà từ bạn bè" | P0 |
| TC-003-10 | Empty state | Date range không có dữ liệu | "Không có đơn hàng voucher/quà tặng trong khoảng thời gian này" | P1 |
| TC-003-11 | Khách hàng từ order.addresses | Đơn có addresses | Hiển thị name + primary_phone (không call remote customer) | P1 |
TC-FR-004: Filter
| TC | Mô tả | Input | Expected | Priority |
|---|---|---|---|---|
| TC-004-01 | Filter thời gian | Chọn 01/03 - 15/03/2026 | Chỉ hiện đơn trong range, summary cập nhật | P0 |
| TC-004-02 | Filter chi nhánh (Admin) | Chọn "CN Quận 1" | Chỉ hiện đơn branch đó | P0 |
| TC-004-03 | Filter chi nhánh (Staff) | Login Staff branch "CN Quận 7" | Chỉ hiện đơn CN Quận 7, không thấy branch khác | P0 |
| TC-004-04 | Filter nguồn quà | Chọn "Lắc xì" | Chỉ hiện items có gifted_from = "gifted_from_gamification" | P0 |
| TC-004-05 | Cascading: nguồn → chiến dịch | Chọn "Voucher" | Dropdown chiến dịch enable + load danh sách voucher_campaigns | P0 |
| TC-004-06 | Cascading: chưa chọn nguồn | Không chọn nguồn quà | Dropdown chiến dịch disabled + "Chọn nguồn quà trước" | P0 |
| TC-004-07 | Cascading: đổi nguồn → reset campaign | Đã chọn Voucher + campaign X → đổi sang "Lắc xì" | Campaign dropdown reset, load danh sách gamification | P0 |
| TC-004-08 | Filter loại giảm | Chọn "Giảm %" | Chỉ hiện items có gift_type = "gift_type_discount_percent" | P0 |
| TC-004-09 | Filter trạng thái đơn = "Đã hủy" | Chọn "Đã hủy" | Hiện đơn đã hủy (canceled_at IS NOT NULL) | P1 |
| TC-004-10 | Filter trạng thái đơn mặc định | Load trang | Ẩn đơn hủy (canceled_at IS NULL) | P0 |
| TC-004-11 | Nguồn "Bạn bè" + "Thủ công" | Chọn cả 2 | Dropdown chiến dịch disabled + "Không áp dụng" | P1 |
| TC-004-12 | Filter thay đổi → reset page 1 | Đang ở page 3, đổi filter | Quay về page 1 | P1 |
TC-FR-005: Export Excel
| TC | Mô tả | Input | Expected | Priority |
|---|---|---|---|---|
| TC-005-01 | Export thành công | Filter có 100 dòng, click export | File don-hang-voucher-qua-tang_19-03-2026.xlsx download | P0 |
| TC-005-02 | Export đúng dữ liệu sau filter | Filter nguồn = "Lắc xì" | Excel chỉ chứa items từ Lắc xì | P0 |
| TC-005-03 | Export > 10,000 dòng | Filter trả về 15,000 dòng | Hiển thị confirmation dialog "có hơn 10,000 dòng, có thể mất vài phút". Chọn "Tiếp tục" → export thành công. Chọn "Hủy" → abort | P1 |
| TC-005-04 | Cột Excel đúng format | Export file | Headers đúng, số tiền format #,##0, ngày format DD/MM/YYYY HH:MM | P1 |
TC-FR-006: Performance (indexes)
| TC | Mô tả | Input | Expected | Priority |
|---|---|---|---|---|
| TC-006-01 | List query < 500ms | EXPLAIN ANALYZE trên staging, date range 3 tháng | Execution time < 500ms | P0 |
| TC-006-02 | Aggregate query < 3s | EXPLAIN ANALYZE trên staging, all branches, 3 tháng | Execution time < 3s | P0 |
| TC-006-03 | Index sử dụng đúng | EXPLAIN ANALYZE | Plan show Index Scan (không Seq Scan) trên order_item | P0 |
TC-FR-007: Permission
| TC | Mô tả | Input | Expected | Priority |
|---|---|---|---|---|
| TC-007-01 | Report role seed đúng | Query report_role table | Record "revenue_voucher_gift_order_report" tồn tại | P0 |
| TC-007-02 | REPORT_TREE cập nhật | Check types.ts | REVENUE_VOUCHER_GIFT_ORDER_REPORT có trong REPORT_TREE | P0 |
D3) Seed Data
Dataset: DS-001 — Đơn hàng với nhiều loại voucher/gift
Cách tạo: SQL Script
sql
-- Tạo 10 đơn hàng với các scenario:
-- 1. Đơn service có 1 voucher (gifted_from_voucher)
-- 2. Đơn service có 2 voucher từ lắc xì (gifted_from_gamification)
-- 3. Đơn cosmetic có 1 gift từ bạn bè (gifted_from_friend)
-- 4. Đơn service có voucher vòng quay (gifted_from_wheel_of_fortune)
-- 5. Đơn service có gift thủ công (gifted_from_manual)
-- 6. Đơn service KHÔNG có voucher (để verify filter)
-- 7. Đơn đã hủy có voucher (canceled_at IS NOT NULL)
-- 8. Đơn chưa xác nhận (customer_confirmed_at IS NULL)
-- 9. Đơn order_transfer có voucher (để verify order_kind filter)
-- 10. Đơn có gift type "Lời chúc" (voucher_discount_amount = 0)
-- Verify: SELECT COUNT(*) FROM order_item WHERE gifted_id IS NOT NULL;
-- Expected: 12 items có voucher/gift
-- Verify: SELECT COUNT(DISTINCT oi.order_id) FROM order_item oi JOIN "order" o ON oi.order_id = o.id WHERE oi.gifted_id IS NOT NULL AND o.customer_confirmed_at IS NOT NULL AND o.order_kind IN ('service', 'cosmetic', 'prepaid');
-- Expected: 7 đơn (trừ đơn 6 không voucher, đơn 8 chưa xác nhận, đơn 9 order_transfer bị loại bởi order_kind filter)D4) Traceability
| FR | TC-ID | Coverage | Status |
|---|---|---|---|
| FR-001 | TC-001-* | 4 test cases | |
| FR-002 | TC-002-* | 6 test cases | |
| FR-003 | TC-003-* | 11 test cases | |
| FR-004 | TC-004-* | 12 test cases | |
| FR-005 | TC-005-* | 4 test cases | |
| FR-006 | TC-006-* | 3 test cases | |
| FR-007 | TC-007-* | 2 test cases | |
| Total | 42 test cases |
D5) Entry / Exit Criteria
Entry (bắt đầu test)
- [ ] BE deploy xong: 4 indexes + seed report_role trên staging
- [ ] FE deploy xong trên staging
- [ ] Seed data DS-001 có sẵn trên staging
- [ ] Test accounts: 1 Admin, 1 Manager (branch cụ thể), 1 Staff (branch cụ thể), 1 Staff không có quyền report
Exit (kết thúc test)
- [ ] Tất cả P0 test cases (22 cases) PASS
- [ ] Tất cả P1 test cases (20 cases) PASS hoặc có waiver từ PO
- [ ] Performance verify: list query < 500ms, aggregate < 3s (EXPLAIN ANALYZE)
- [ ] No critical/major bugs open
- [ ] Export Excel verify: file mở được, data đúng, format đúng