Skip to content

QA Test Plan: Cải thiện UX cài đặt Mã Công Việc / Tiền Tour

Feature slug: settings-ux-subtask-tagVersion: 1.0 Ngày: 2026-03-26


D1) Coverage

LoạiSố lượngChi tiết
FR8FR-001 → FR-008
NFR2NFR-001, NFR-003
Edge Cases10EC-01 → EC-10
Test Cases30TC-FR-001 → TC-FR-008, TC-BR-001 → TC-BR-003, TC-NFR-001 → TC-NFR-002, TC-EC-001 → TC-EC-010, TC-CP-001 → TC-CP-003

D2) Requirements Matrix

FR/NFRTest CasesPriority
FR-001 Trang TourFeeConfigTC-FR-001a (accordion), TC-FR-001b (CRUD group), TC-FR-001c (CRUD tag)Critical
FR-002 Range + Chi tiếtTC-FR-002a (flat), TC-FR-002b (multi), TC-FR-002c (empty)High
FR-003 "Đang dùng bởi"TC-FR-003a (count), TC-FR-003b (expand list)High
FR-004 Tag chip enrichedTC-FR-004a (settings), TC-FR-004b (projects), TC-FR-004c (ecommerce)Critical
FR-005 TooltipTC-FR-005High
FR-006 Dropdown enrichedTC-FR-006High
FR-007 SubTaskTableTC-FR-007a (cột), TC-FR-007b (filter), TC-FR-007c (fix label)High
FR-008 Rename + redirectsTC-FR-008a (sidebar), TC-FR-008b (redirects), TC-FR-008c (route name)Critical
Blast radiusTC-BR-001 (TaskForm), TC-BR-002 (OrderTaskLimitForm), TC-BR-003 (ServiceSubtaskItem)Critical
NFR-001 Page loadTC-NFR-001High
NFR-003 SubTaskTableTC-NFR-002High

D3) Seed Data

Dataset SD-01: Nhóm + Tags + Tour Moneys

Precondition: Dùng data sẵn có trên test env. Verify:

sql
-- Verify có ít nhất 2 nhóm tiền tour
SELECT id, code, name FROM project_task_group_tag WHERE disabled = false LIMIT 5;

-- Verify có tags với tour_moneys
SELECT t.id, t.code, t.name, t.group_tag_id,
       array_agg(tm.tour_money ORDER BY tm.seniority) as tour_moneys
FROM project_task_tag t
LEFT JOIN tag_tour_money tm ON tm.tag_id = t.id
WHERE t.disabled = false
GROUP BY t.id
LIMIT 10;

-- Verify có subtask dùng tags
SELECT s.code, s.name, array_agg(st.tag_id) as tag_ids
FROM subtask s
JOIN subtask_tag st ON st.subtask_id = s.id
GROUP BY s.id
LIMIT 10;

Dataset SD-02: Tag flat-rate + multi-rate

sql
-- Tìm 1 tag flat-rate (tất cả cấp bậc = nhau)
SELECT tag_id, array_agg(DISTINCT tour_money) as unique_amounts
FROM tag_tour_money
GROUP BY tag_id
HAVING count(DISTINCT tour_money) = 1
LIMIT 1;

-- Tìm 1 tag multi-rate (cấp bậc khác nhau)
SELECT tag_id, array_agg(DISTINCT tour_money) as unique_amounts
FROM tag_tour_money
GROUP BY tag_id
HAVING count(DISTINCT tour_money) > 1
LIMIT 1;

Dataset SD-03: Tag chưa cấu hình tour money

sql
-- Tìm tag không có tour_moneys
SELECT t.id, t.code, t.name
FROM project_task_tag t
LEFT JOIN tag_tour_money tm ON tm.tag_id = t.id
WHERE tm.id IS NULL
LIMIT 1;

D4) Test Cases

Critical Path Tests

TC-IDTênStepsExpectedPriority
TC-CP-001E2E: Tạo nhóm → tạo tag → gán vào subtask1. Mở Cấu Hình Tiền Tour 2. [+ Nhóm] → tạo "Test Group" 3. Expand → [+ Thêm tag] → tạo tag T-TEST 4. Mở Mã Công Việc → edit SUB280 5. Search T-TEST → chọn 6. LưuNhóm + tag tạo thành công. SUB280 có chip [T-TEST — {range}]Critical
TC-CP-002E2E: Verify blast radius — KTV chọn tag enriched1. Mở chi tiết khách hàng → Tab Công Việc 2. Tạo subtask → field "Loại tiền tour" 3. Mở dropdownDropdown hiện: Mã + Tên + Range + Nhóm (enriched format)Critical
TC-CP-003E2E: Route redirect + link ecommerce1. Mở URL cũ /s/internal-settings/task-tag 2. Mở URL cũ /task-tag/{id} 3. Trong form đơn hàng, click link tagTất cả redirect đúng sang /tour-fee-config. Link ecommerce vẫn mở đúng.Critical

FR Test Cases

TC-IDFRTênStepsExpectedPriority
TC-FR-001aFR-001Accordion expand/collapseMở Cấu Hình Tiền Tour → click ▼ nhómExpand hiện bảng tags. Click ▶ collapse.Critical
TC-FR-001bFR-001CRUD nhóm[+ Nhóm] → nhập code + name → Lưu. [Sửa nhóm] → đổi name → EnterNhóm tạo/sửa thành côngHigh
TC-FR-001cFR-001CRUD tag trong nhóm[+ Thêm tag] → form side dialog → nhập → Lưu. [Sửa] → đổi → LưuTag tạo/sửa trong nhómHigh
TC-FR-002aFR-002Range flat-rateMở nhóm có tag T26 (tất cả CĐ = 100k)Range = "100,000đ", Chi tiết = "CĐ1-5: đều 100k"High
TC-FR-002bFR-002Range multi-rateMở nhóm có tag T15 (CĐ khác nhau)Range = "50k~120k", Chi tiết = "CĐ1:50k ... CĐ5:120k"High
TC-FR-002cFR-002Range emptyMở nhóm có tag chưa config tour moneyRange = "—", Chi tiết = "Chưa có tiền tour"Medium
TC-FR-003aFR-003Usage countMở nhóm có tags đang dùngFooter hiện "Đang dùng bởi: N mã công việc" (N > 0)High
TC-FR-003bFR-003Usage expandClick [Xem ↗]Expand danh sách: Mã, Tên công việc, TagsHigh
TC-FR-004aFR-004Chip enriched (settings)Mở edit subtask có tag T26Chip hiện "[T26 — 100,000đ ×]" (không phải "[100k ×]")Critical
TC-FR-004bFR-004Chip enriched (projects)Mở TaskForm tạo subtask → chọn tagSelected hiện "T26 — 100k — 100,000đ (Tiền tour 2024)"Critical
TC-FR-004cFR-004Display enriched (ecommerce)Mở OrderTaskLimitForm có tagTag hiện "T08 (80,000đ)" thay vì "Ok"Critical
TC-FR-005FR-005Tooltip tiền tourHover chip tag trong SubTaskFormTooltip hiện: tên, nhóm, bảng 5 CĐ + tiền, link "Xem chi tiết ↗"High
TC-FR-006FR-006Dropdown enrichedMở SubTaskForm → search tagDropdown option hiện: Mã + Tên + Range + NhómHigh
TC-FR-007aFR-007Cột tag trong SubTaskTableMở Mã Công ViệcCột "Tag tiền tour" hiện data (VD: "T08: 80,000đ")High
TC-FR-007bFR-007Filter nhóm/tagChọn filter [Nhóm tiền tour: Tiền tour 2024]List filter đúng subtask có tags thuộc nhóm đóHigh
TC-FR-007cFR-007Fix label swapXem bảng SubTaskTableCột 3 = Loại (Dịch vụ/Thủ công), Cột 4 = Tên công việc. Đúng label.Medium
TC-FR-008aFR-008Sidebar renameMở sidebar "Quản Lý Công Việc"Hiện "Mã Công Việc" (không phải "Công Việc"), "Cấu Hình Tiền Tour" (gộp 2 cũ)High
TC-FR-008bFR-008Path redirectNavigate /s/internal-settings/task-tagRedirect sang /s/internal-settings/tour-fee-configCritical
TC-FR-008cFR-008Route name redirectTrong OrderTaskLimitForm, click tag linkMở /tour-fee-config?tag={id} (không 404)Critical

Blast Radius Tests

TC-IDNơiStepsExpectedPriority
TC-BR-001TaskForm (projects)Tạo subtask → field "Loại tiền tour" → chọn tag → verify tiền tour auto-fillDropdown enriched + tiền tour fill đúng theo cấp bậc KTVCritical
TC-BR-002OrderTaskLimitFormMở form đơn hàng có subtask với tag → xem hiển thị tagTag hiện "T08 (80,000đ)" + link xanh cho ITCritical
TC-BR-003ServiceSubtaskItemMở cài đặt dịch vụ có subtask với tagTag hiện "T08 (80,000đ)" + link xanh cho ITCritical

NFR Test Cases

TC-IDNFRStepsExpectedPriority
TC-NFR-001NFR-001Mở trang Cấu Hình Tiền Tour (cold load)First meaningful paint < 1sHigh
TC-NFR-002NFR-003Mở Mã Công Việc (275+ rows + cột tag)Table render < 500msHigh

Edge Case Test Cases

TC-IDECStepsExpectedPriority
TC-EC-001EC-01Tạo nhóm mới (0 tags) → expandHiện "Chưa có tag. Bấm [+ Thêm tag tiền tour]"Medium
TC-EC-002EC-02Xem tag chưa config tour moneyRange = "—", Chi tiết = "Chưa có tiền tour"Medium
TC-EC-003EC-03Edit subtask type = Thủ côngField "Tag tiền tour" readonly, list hiện "—"Medium
TC-EC-004EC-04Subtask có 4+ tagsChips wrap, SubTaskTable hiện 2 tags + "+N more"Medium
TC-EC-005EC-05Search tag không tìm thấyDropdown trống + "Không tìm thấy"Low
TC-EC-006EC-06Xóa nhóm đang có tagsBlock + toast "Nhóm đang có N tag..."High
TC-EC-007EC-07Navigate URL cũ /task-tag/abc123Redirect → /tour-fee-config?tag=abc123High
TC-EC-008EC-08Tag disabled đã gán vào subtaskChip hiện bình thường, dropdown filter raMedium
TC-EC-009EC-09Tất cả tiền tour = 0Range = "0đ"Low
TC-EC-010EC-10Group có 50+ tagsBảng tags trong accordion phân trangMedium

D5) Entry / Exit Criteria

Entry Criteria

  • [ ] pnpm codegen pass (GraphQL fragments mở rộng thành công)
  • [ ] TourFeeConfig page render (không error)
  • [ ] TaskTagSelect enriched chip hiển thị đúng
  • [ ] Test accounts: IT Leader, IT Staff, Admin, Manager, Staff (KTV)
  • [ ] Test data: ít nhất 2 nhóm, 5+ tags, subtasks có tags

Exit Criteria

  • [ ] 3/3 Critical Path tests pass (TC-CP-001 → TC-CP-003)
  • [ ] 18/18 FR tests pass
  • [ ] 3/3 Blast Radius tests pass
  • [ ] 2/2 NFR tests pass
  • [ ] 10/10 Edge Case tests pass
  • [ ] Route redirects hoạt động cho tất cả route cũ
  • [ ] Tiền tour auto-fill trong TaskForm KHÔNG bị ảnh hưởng
  • [ ] No P1/P2 bugs open