Appearance
Kế hoạch kiểm thử (QA Test Plan) — Chấm công đa đơn vị trên shared tenant
v3.1.4 — 21/04/2026
| Thay đổi | Section | Ảnh hưởng |
|---|---|---|
Sửa oracle missing_break: không auto ép workday = 0.5 chỉ vì thiếu mốc giữa ca | D2) Danh sách test case | QA, FE, BE |
Đổi coverage Daisy break linh hoạt sang mô hình Day-1: đủ 4 mốc, tính actual_hours, export đủ mốc; không test tolerance window như rule đang enforce | D2) Danh sách test case | QA, BE |
Chốt test contract remote: không có entry mới trong attendance shell, nhưng flow legacy vẫn dùng cho nhóm nhỏ đã approved | D2) Danh sách test case | QA, FE |
Sửa oracle part-time PN thành (4/4) x 0.5 = 0.5 để tránh copy nhầm rule cho ca khác | D2) Danh sách test case | QA |
Tham chiếu (Ref): PRD v3.1.4 | Ngày (Date): 21/04/2026
Changelog
| Version | Date | Author | Thay đổi |
|---|---|---|---|
| 3.1.4 | 21/04/2026 | PO/BA | Sửa oracle missing_break, remote và PN part-time; đồng thời đổi coverage Daisy break linh hoạt sang hướng Day-1 metadata + actual-hours thay vì tolerance window đang enforce |
| 3.1.3 | 15/04/2026 | PO/BA | Đổi oracle Công chuẩn sang test theo nhóm áp dụng công chuẩn và mapping department -> scope, thêm case riêng cho Daisy Kế toán / Daisy Tele-CSKH-Page-CN |
| 3.0 | 07/04/2026 | PO/BA | Initial QA coverage cho multi-unit timekeeping |
| 3.0.1 | 07/04/2026 | PO/BA | Đồng bộ test/go-live wording theo break_mode, annual leave Day-1 và PN/Daisy runtime đã chốt |
| 3.1 | 13/04/2026 | PO/BA | Mở rộng test matrix cho assignment theo branch/department, readiness checklist, rollout gating và hidden filters theo mapping disabled |
| 3.1.1 | 13/04/2026 | PO/BA | Làm rõ GPS test oracle: branch coordinates lấy từ branch master data hiện có, còn bán kính ưu tiên gps_radius_meters của unit rồi mới fallback global |
| 3.1.2 | 14/04/2026 | PO/BA | Chuyển test matrix mode tính công xuống Ca làm việc, bỏ expectation cũ ở Tab Quy định, thêm test cho Công tối đa của ca / Giờ chuẩn của ca, và chuyển yêu cầu GPS của ca sang gps_required = Bắt buộc / Không bắt buộc ở shift |
D1) Phạm vi kiểm thử (Test Scope)
| FR | Mô tả | Priority |
|---|---|---|
| FR-001 | Timekeeping unit scope | Must |
| FR-001A | User assignment / headcount scope | Must |
| FR-001B | Triển khai rollout theo đơn vị | Must |
| FR-002 | Daisy 4 mốc | Must |
| FR-003 | Runtime multi-clock | Must |
| FR-004 | Admin working schedule / working sheet | Must |
| FR-005 | Mobile attendance | Must |
| FR-006 | Timekeeping approver / request | Must |
| FR-007 | Export vận hành chấm công | Must |
| FR-008 | Rollout guardrails / non-regression timekeeping | Must |
Regression Impact Map
| Surface | Mức độ | Bắt buộc test lại | Wave |
|---|---|---|---|
timekeeping admin web | Rất cao | Filter unit, working sheet, popup detail, export | 1A, 1B |
| Mobile attendance | Rất cao | PN 2 mốc, Daisy 4 mốc, CTA, history, GPS | 1A, 1B |
| Shift settings | Cao | Filter unit, contract nghỉ giữa ca (break_time, break_clocking_required, break_mode, break_flex_minutes), canonical key | 1A, 1B |
| Timekeeping approver settings | Cao | Scope đúng unit, không lẫn approver | 1A, 1B |
| Diva timekeeping hiện tại | Cao | Non-regression chấm công hiện tại trong scope Diva | 1A, 1B, 1C |
| Dashboard/report legacy | Không thuộc scope | Không retest trong package này | — |
| Salary/payroll legacy | Không thuộc scope | Không retest trong package này | — |
D2) Danh sách test case (Test Cases)
TC-FR-001: Timekeeping unit scope
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-001-01 | HR Daisy vào working sheet của Daisy | Chỉ thấy dữ liệu Daisy | P0 |
| TC-001-02 | HR PN vào working sheet của PN | Chỉ thấy dữ liệu PN | P0 |
| TC-001-03 | User Daisy cố xem unit PN | Bị chặn | P0 |
| TC-001-04 | GPS gần branch ngoài unit | Không bind nhầm | P0 |
| TC-001-05 | Đổi timekeeping_unit trên admin filter | Reset branch/department/shift group đúng | P1 |
TC-FR-001A: Assignment
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-001A-01 | Một user có active unit | Hiển thị đúng unit | P0 |
| TC-001A-02 | User đổi unit giữa tháng | Record cũ không hồi tố | P0 |
| TC-001A-03 | Save assignment trùng active unit | Bị chặn | P0 |
| TC-001A-04 | Headcount theo unit | Count đúng theo assignment active | P1 |
| TC-001A-05 | Tạo 2 assignment overlap ngày hiệu lực | Bị chặn ở DB/service | P0 |
| TC-001A-06 | Bulk import mã NV vào unit | Match đúng user hợp lệ, trả danh sách mã không hợp lệ | P0 |
| TC-001A-07 | Dán danh sách mã NV nhiều dòng | Preview đúng danh sách match/unmatch | P1 |
| TC-001A-08 | Re-assignment user sang unit khác | Đóng assignment cũ, tạo assignment mới đúng ngày hiệu lực | P0 |
| TC-001A-09 | Xóa nhân viên khỏi đơn vị | Assignment chuyển Đã hết hiệu lực, không hard delete | P0 |
| TC-001A-10 | Assignment có primary_department_id | Filter/approver/export đọc đúng phòng ban áp dụng | P0 |
TC-FR-001B: Triển khai rollout
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-001B-01 | Checklist readiness đủ dữ liệu | Tất cả badge ra đúng count/status | P0 |
| TC-001B-02 | Click badge checklist | Điều hướng đúng tab còn thiếu | P1 |
| TC-001B-03 | Còn badge ❌ | Nút Bật rollout bị disable | P0 |
| TC-001B-04 | Không còn badge ❌ | Cho phép Bật rollout | P0 |
| TC-001B-05 | Lưu ghi chú triển khai | Snapshot checklist + ghi chú được lưu | P1 |
TC-FR-002: Daisy 4 mốc
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-002-01 | Chấm đủ 4 mốc | complete, workday = 1.0 | P0 |
| TC-002-02 | Thiếu Ra nghỉ (chỉ 3 mốc: vào ca, vào lại, ra về) | missing_break | P0 |
| TC-002-03 | Punch thứ 5 | Reject "Đã chấm đủ mốc" | P1 |
| TC-002-04 | Daisy VP user chấm ca 2 mốc (break_clocking_required = false) | CTA chỉ Vào ca/Ra về, không hiện 4 CTA | P0 |
| TC-002-05 | Daisy DV user đi trễ segment 0 >60 phút | Bị flag vi phạm theo rule ca fixed/flex đang áp dụng; không suy diễn thêm rule missing_break | P1 |
| TC-002-06 | Daisy DV user thiếu cả segment 1 | missing_break; hệ thống không auto ép workday = 0.5 chỉ vì thiếu mốc giữa ca | P1 |
TC-FR-003: Runtime multi-clock
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-003-01 | Map đúng time_slot_user_id | Pass | P0 |
| TC-003-02 | Double tap | Không tạo duplicate sai | P0 |
| TC-003-03 | User không có ca ngày đó | Reject + message phù hợp | P1 |
TC-FR-004: Admin working sheet
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-004-01 | PN ngày đủ 2 mốc | Hiện Đủ mốc | P0 |
| TC-004-02 | Daisy ngày thiếu giữa trưa | Hiện Thiếu giữa trưa | P0 |
| TC-004-03 | Popup chi tiết ngày | Hiện đúng số mốc theo ca | P0 |
TC-FR-005: Mobile attendance
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-005-01 | PN app 2 mốc | CTA đúng Vào ca/Ra về | P0 |
| TC-005-02 | Daisy DV app 4 mốc | CTA đúng 4 trạng thái theo state machine | P0 |
| TC-005-03 | GPS ngoài branch hợp lệ | Chặn punch + hiện lý do | P0 |
| TC-005-04 | Diva user ngoài rollout | Không đổi hành vi cũ | P0 |
| TC-005-05 | User rollout mở request list mobile | Không có CTA/request entry remote mới trên attendance shell; nhóm nhỏ vẫn dùng flow legacy đã được cấp quyền/approved | P1 |
| TC-005-06 | PN ca gãy (break 3h) — 4 CTA (DEC-014 confirmed) | CTA Vào ca/Ra nghỉ/Vào lại/Ra về theo state machine 4 mốc | P0 |
| TC-005-07 | Daisy VP user (ca 2 mốc) | CTA Vào ca/Ra về | P0 |
| TC-005-08 | Daisy DV double-tap <5s | Reject "Vui lòng đợi" | P1 |
| TC-005-09 | Daisy DV chấm vào ca → ra nghỉ → vào lại → ra về (happy path 4 mốc) | 2 records segment 0+1, status complete | P0 |
| TC-005-10 | User không có ca hôm nay | Reject "Không có ca hôm nay" | P1 |
TC-FR-006: Timekeeping approver / request
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-006-01 | Request quên chấm của Daisy | Resolve đúng approver Daisy | P0 |
| TC-006-02 | Approver cấu hình khác unit | Không được dùng | P0 |
| TC-006-03 | Tab remote trên approver settings | Vẫn tồn tại theo UI legacy nếu tenant đang dùng; feature này không redesign hay mở config remote mới trong scope Day-1 | P1 |
| TC-006-04 | Flow ngoài timekeeping | Không đổi vì feature này | P1 |
TC-FR-007: Export vận hành
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-007-01 | Export bảng công tháng PN | File đúng, cột 2 mốc | P0 |
| TC-007-02 | Export chi tiết ngày Daisy DV | Có đủ 4 cột mốc (vào ca, ra nghỉ, vào lại, ra về) | P0 |
| TC-007-03 | Export chi tiết ngày Daisy VP | Chỉ 2 cột mốc (vào ca, ra về) | P0 |
| TC-007-04 | Export trễ/sớm | Có cột phút trễ/sớm + cột tiền phạt (tự tính từ penalty_rule) | P0 |
| TC-007-05 | Annual leave report PN | HR PN mở → hiện data PN. Daisy không thấy entry report trong rollout này. Diva giữ nguyên | P0 |
| TC-007-06 | PN export OT request < 30 phút | Bỏ qua, không hiện trong export | P1 |
| TC-007-07 | PN export OT request >= 30 phút | Hiện đúng ot_hours | P1 |
| TC-007-08 | Export quên chấm: đếm số lần missing per type | Hiện missing_start_count, missing_end_count, missing_break_count | P1 |
| TC-007-09 | Export bảng công tháng PN có cột "Tiền phạt" tự tính đúng | Tiền phạt khớp penalty_rule (exempt_count = 0 cho quên vào ca, = 3 cho quên trưa) | P0 |
| TC-007-10 | Export bảng công tháng Daisy có cột "Tiền phạt" (shared pool exempt) | Tiền phạt = 0 khi tổng lần quên <= 3 (shared pool), có phạt khi vượt 3 | P0 |
| TC-007-11 | Export bảng công tháng có cột "Tiền OT" tự tính đúng | Tiền OT = ot_hours × ot_rate per role (PN thường 50k, PN BS 150k, Daisy 35k) | P0 |
TC-FR-009: Seed shift templates
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-009-01 | PN ca gãy 7:00 14:00 (break 11:00-14:00) | Template có break_time=true, break đúng 3h | P0 |
| TC-009-02 | Cronjob tính late/early cho PN ca gãy | Ra 11:00 = không tính về sớm; vào 14:00 = không tính đi trễ | P0 |
| TC-009-03 | Daisy ca BS 4 mốc template | break_clocking_required = true | P0 |
| TC-009-04 | Daisy ca Kế toán 2 mốc template | break_clocking_required = false | P0 |
TC-FR-010: Daisy ca xoay
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-010-01 | Cron generate_working_shift cho Daisy (auto_schedule_disabled=true) | Skip, không tạo lịch tự động | P0 |
| TC-010-02 | Cron generate_working_shift cho PN (auto_schedule_disabled=false) | Copy tuần trước → tuần sau bình thường | P0 |
| TC-010-03 | HR Daisy import Excel lịch tuần | Lịch tuần mới override đúng | P1 |
TC-FR-011: Phân quyền HR 3 bên
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-011-01 | HR Daisy mở Working Sheet | Auto-select unit Daisy, chỉ thấy NV Daisy | P0 |
| TC-011-02 | HR PN mở Working Sheet | Auto-select unit PN, chỉ thấy NV PN | P0 |
| TC-011-03 | HR Daisy cố query data PN qua API | Bị chặn (Hasura permission) | P0 |
| TC-011-04 | System Admin mở Working Sheet chưa chọn unit | Empty state, bắt buộc chọn | P1 |
| TC-011-05 | Diva native user (không thuộc unit) mở Working Sheet | Không thấy filter unit, data legacy bình thường | P0 |
| TC-011-06 | Manager Daisy mở Working Sheet | Chỉ thấy NV thuộc department/branch mình quản lý, trong scope Daisy | P0 |
| TC-011-07 | HR Daisy mở filter Chi nhánh | Chỉ thấy 6 CN + 3 VP Daisy, không thấy CN PN | P0 |
| TC-011-08 | HR PN mở filter Chi nhánh | Chỉ thấy 3 PK + 1 VP PN, không thấy CN Daisy | P0 |
| TC-011-09 | Chi nhánh đã Ngưng áp dụng | Không hiện ở filter mặc định | P1 |
| TC-011-10 | Phòng ban đã Ngưng áp dụng | Không hiện ở filter mặc định | P1 |
TC-FR-012: Đơn đi trễ/về sớm — rule per unit
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-012-01 | NV Daisy tạo đơn đi trễ 45 phút | OK, cho tạo | P0 |
| TC-012-02 | NV Daisy tạo đơn đi trễ 70 phút | Reject "Vượt quá 60 phút" | P0 |
| TC-012-03 | NV PN tạo đơn đi trễ 90 phút | OK, cho tạo (PN không giới hạn) | P0 |
| TC-012-04 | NV Daisy đã có 3 đơn approved trong tháng, tạo đơn thứ 4 | Hiện cảnh báo "4/3 lần", vẫn cho tạo | P1 |
| TC-012-05 | Mobile hiển thị "2/3 lần" khi NV đã dùng 2 đơn | Đúng count, scoped per unit | P0 |
| TC-012-06 | NV Diva (không có unit) tạo đơn trễ/sớm | Dùng global count legacy, không có max duration | P1 |
TC-FR-013: Đơn quên chấm — count per unit
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-013-01 | NV PN đã có 2 đơn quên chấm approved, tạo đơn 3 | Hiện "3/3 lần", cho tạo | P0 |
| TC-013-02 | Count chỉ đếm approved + pending | Đơn rejected/canceled không đếm | P0 |
TC-FR-014: Daisy ca linh hoạt (4 mốc, break metadata 12:00–14:00)
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-014-01 | Daisy BS chấm 08:00 -> 12:30 -> 13:30 -> 17:00 | actual_hours = 4.5 + 3.5 = 8.0h | P0 |
| TC-014-02 | Daisy BS chấm 08:00 -> 10:50 -> 14:10 -> 17:00 | Không block/phạt vì lệch khung break; export đủ 4 mốc | P0 |
| TC-014-03 | Daisy BS thiếu mốc 2 hoặc 3 | Mark missing_break, vẫn ghi nhận segment đủ dữ liệu | P0 |
| TC-014-04 | Daisy BS đủ 4 mốc nhưng tổng giờ < chuẩn ca | Tính workday theo logic của ca, không dùng break window để phạt giữa ca | P0 |
| TC-014-05 | Export chi tiết ngày Daisy | Hiện đủ 4 mốc để HR tự đối soát/tính nếu cần | P0 |
TC-FR-015: PN tính công theo giờ (DEC-022)
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-015-01 | PN NV Khối DV ca 8h, làm đủ 8h, không đơn | workday = 1.0 | P0 |
| TC-015-02 | PN NV Khối DV ca 8h, về sớm (7h), KHÔNG có đơn | workday = 7/8 = 0.875 | P0 |
| TC-015-03 | PN NV Khối DV ca 8h, về sớm (7h), CÓ đơn trễ/sớm approved | workday = 1.0 (full) | P0 |
| TC-015-04 | PN NV Khối VP ca 7.5h chuẩn, làm đủ | workday = 1.0 | P0 |
| TC-015-05 | PN NV Khối VP ca 7.5h, về sớm (5.5h), không đơn | workday = 5.5/7.5 = 0.73 | P0 |
| TC-015-06 | PN part-time ca 4h, đi đủ 4h | workday = (4/4) x 0.5 = 0.5 | P1 |
| TC-015-07 | PN NV ca gãy 4 mốc, đủ mốc, tổng 8h | workday = 1.0 | P0 |
| TC-015-08 | PN NV ca gãy 4 mốc, thiếu chiều (4h sáng), không đơn | workday = 4/8 = 0.5 | P0 |
| TC-015-09 | Daisy NV cùng scenario (7h, không đơn) | workday = 1.0 (Daisy dùng fixed, KHÔNG hourly) | P0 |
| TC-015-10 | Diva NV cùng scenario | workday = logic legacy (không đổi) | P0 |
TC-FR-016: Báo cáo phép năm PN — reuse AnnualLeaveReport (DEC-023)
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-016-01 | HR PN mở Báo cáo phép năm (reuse AnnualLeaveReport.tsx) | Hiện filter Timekeeping Unit auto-select PN, chỉ thấy NV PN | P0 |
| TC-016-02 | PN NV nghỉ phép 2 ngày → count đã dùng tăng 2 | Đúng, remaining_leave_days giảm 2 | P0 |
| TC-016-03 | Daisy mở report/timekeeping menu Day-1 | Không thấy entry báo cáo phép năm trong rollout này | P1 |
| TC-016-04 | Diva HR mở báo cáo phép năm | Giữ nguyên — không thấy filter unit, data Diva bình thường | P0 |
| TC-016-05 | Cron add_annual_leave ngày 1 tháng mới | NV PN/Daisy cũng được +1 phép (cron query ALL, không filter unit) | P0 |
| TC-016-06 | annual_leave_logs NV PN có timekeeping_unit_id = PN | Record audit có unit_id đúng | P1 |
TC-FR-017: PN ca gãy 4 mốc
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-017-01 | PN NV ca gãy 7:00 14:00, chấm 4 mốc đủ | complete, CTA đúng 4 trạng thái | P0 |
| TC-017-02 | PN NV ca gãy, thiếu mốc vào lại chiều | missing_break | P0 |
| TC-017-03 | PN NV ca gãy, trễ đầu ca chiều 15p | Segment 1 late = 15p | P0 |
| TC-017-04 | PN NV ca thường (Ca HC, 2 mốc) | Chỉ 2 CTA: Vào ca, Ra về | P0 |
TC-STD: Công chuẩn — theo nhóm áp dụng công chuẩn
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-STD-01 | PN NV thuộc department map vào scope PN_SERVICE, tháng 30 ngày 4 CN | Công chuẩn = 26 (days_minus_sun) | P0 |
| TC-STD-02 | PN NV thuộc department map vào scope PN_OFFICE, tháng 30 ngày 4 CN 4 T7 | Công chuẩn = 24 (days_minus_sun_half_sat) | P0 |
| TC-STD-03 | Daisy NV Kế toán thuộc scope DAISY_OFFICE_ACCOUNTING | Công chuẩn = 24 | P0 |
| TC-STD-04 | Daisy NV Tele/CSKH/Page/Chi nhánh thuộc scope DAISY_OFFICE_TELE_CSKH_PAGE_BRANCH | Công chuẩn = 26 | P0 |
| TC-STD-05 | Daisy NV Khối Dịch vụ thuộc scope DAISY_SERVICE | Công chuẩn = 26 | P0 |
| TC-STD-06 | Diva NV (unit_id = NULL) | Dùng logic cũ InitThisMonthSalaryData() — kết quả KHÔNG ĐỔI | P0 |
| TC-STD-07 | Admin đổi formula scope PN_OFFICE từ days_minus_sun_half_sat → days_minus_sun | Tháng sau công chuẩn VP = 26 | P1 |
| TC-STD-08 | Admin tạo scope mới cho Daisy và gán 1 department vào scope đó | NV department đó dùng công chuẩn của scope mới từ tháng sau | P1 |
| TC-STD-09 | Department không có scope mapping | Fallback 26.0 và có log cảnh báo để Ops xử lý | P1 |
TC-PENALTY: Penalty engine — timekeeping_penalty_rule
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-PEN-01 | PN NV quên chấm vào ca lần 1 | Phạt 30.000đ ngay (exempt_count = 0, individual) | P0 |
| TC-PEN-02 | PN NV quên chấm giữa trưa lần 1-3 | Miễn (exempt_count = 3, individual pool) | P0 |
| TC-PEN-03 | PN NV quên chấm giữa trưa lần 4 | Phạt 30.000đ | P0 |
| TC-PEN-04 | Daisy NV quên chấm vào ca lần 1-3 | Miễn (exempt_count = 3, shared pool) | P0 |
| TC-PEN-05 | Daisy NV quên vào ca 2 lần + quên trưa 1 lần = 3 lần gộp, quên ra ca lần 4 | Phạt trừ 0.5 công (shared pool vượt 3) | P0 |
| TC-PEN-06 | Daisy NV trễ lần 4, 15 phút | Phạt 15 × 10.000 = 150.000đ | P0 |
| TC-PEN-07 | Diva NV trễ 15 phút | Dùng logic cũ hardcode 10k/phút — KHÔNG query penalty_rule | P0 |
| TC-PEN-08 | Export bảng công PN hiện cột "Tiền phạt" tự tính | Đúng theo rule, HR không cần Excel | P0 |
TC-OT-RATE: OT rate tự động
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-OTR-01 | PN NV thường OT 2h | Tiền OT = 2 × 50.000 = 100.000đ | P0 |
| TC-OTR-02 | PN BS OT 2h | Tiền OT = 2 × 150.000 = 300.000đ | P0 |
| TC-OTR-03 | Daisy NV thường OT 2h | Tiền OT = 2 × 35.000 = 70.000đ | P0 |
| TC-OTR-04 | PN OT request 20p (< threshold 30p) | Bỏ qua, tiền OT = 0 | P0 |
| TC-OTR-05 | Diva NV OT | Dùng logic cũ — KHÔNG query ot_rate | P0 |
TC-CFG: Settings Module — Tab Quy định
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-CFG-01 | System Admin mở Tab Quy định cho PN | Không còn field Cách tính công; chỉ thấy policy unit như đơn từ, OT, GPS | P0 |
| TC-CFG-02 | System Admin mở Tab Quy định cho Daisy | Không còn field Cách tính công; không còn field break tolerance ở cấp unit | P0 |
| TC-CFG-03 | Đổi Daisy max phút trễ/sớm từ 60 → 90 → Lưu | NV Daisy tạo đơn 75 phút → OK (trước đó bị reject) | P1 |
| TC-CFG-04 | Đổi config → record hôm nay KHÔNG bị ảnh hưởng | Chỉ áp dụng từ ngày mai | P0 |
| TC-CFG-05 | HR (không phải System Admin) cố mở Tab Quy định | Bị chặn hoặc readonly | P0 |
| TC-CFG-06 | Đổi config → audit log ghi đúng (ai, đổi gì, lúc nào) | Có record trong audit log | P1 |
| TC-CFG-07 | Đổi PN OT threshold từ 30 → 0 → export OT | OT request 20p xuất hiện trong export (trước đó bị skip) | P1 |
TC-SHIFT-CFG: Cấu hình cách tính công ở Ca làm việc
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-SHIFT-01 | Mở popup sửa ca PN ca DV | Hiện Cách tính công = Theo giờ, Công tối đa của ca = 1.0, Giờ chuẩn của ca = 8.0 | P0 |
| TC-SHIFT-02 | Mở popup sửa ca PN ca VP | Hiện Cách tính công = Theo giờ, Giờ chuẩn của ca = 7.5 | P0 |
| TC-SHIFT-03 | Mở popup sửa ca Daisy | Hiện Cách tính công = Theo ngày công, ẩn Giờ chuẩn của ca | P0 |
| TC-SHIFT-04 | Đổi một ca từ Theo giờ → Theo ngày công | Giờ chuẩn của ca ẩn đi; cron ngày hôm sau dùng logic fixed cho đúng ca này | P0 |
| TC-SHIFT-05 | Đổi một ca part-time sang Theo giờ, Giờ chuẩn = 4, Công tối đa = 0.5 | Đi đủ 4h thì bảng công = 0.5 | P0 |
| TC-SHIFT-06 | Chọn Theo giờ nhưng để trống Giờ chuẩn của ca | Không cho lưu, hiện validation | P0 |
| TC-SHIFT-07 | Chọn GPS cho ca này = Bắt buộc | Lưu thành công; ca này bắt buộc check GPS khi punch | P0 |
| TC-SHIFT-08 | Chọn GPS cho ca này = Không bắt buộc | Lưu thành công; ca này không check GPS khi punch | P1 |
TC-FR-018: Mobile lịch sử cá nhân
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-018-01 | NV PN ca thường xem lịch sử | ca 2 mốc, running total | P0 |
| TC-018-02 | NV PN ca gãy xem lịch sử | Ca 4 mốc hiện 4 dòng | P0 |
| TC-018-03 | NV Daisy DV xem lịch sử | Ca 4 mốc hiện 4 dòng | P0 |
| TC-018-04 | NV xem tổng tháng | Đúng: ngày công, lần trễ, lần sớm, lần quên | P1 |
TC-FR-008: Guardrails
| TC | Mô tả | Expected | Priority |
|---|---|---|---|
| TC-008-01 | Tắt rollout flag unit | Unit đó không chấm được path mới | P0 |
| TC-008-02 | Diva timekeeping legacy | Không regress | P0 |
| TC-008-03 | Update template cùng tên khác unit | Không rewrite chéo unit | P0 |
D3) Dữ liệu seed (Seed Data)
sql
-- timekeeping units
-- DIVA, DAISY, PHUONG_NAM
-- users
-- 1 HR + 1 manager + 2 staff cho mỗi unit
-- shifts
-- PN: 1 ca 2 mốc + 1 ca gãy 4 mốc
-- Daisy: 1 ca 4 mốc (BS/Phụ tá) + 1 ca 2 mốc (VP)
-- requests
-- forget_clock
-- late_early
-- overtime
-- penalty_rule
-- PN: quên vào ca (exempt_count=0, individual), quên trưa (exempt_count=3, individual)
-- Daisy: quên chấm (exempt_count=3, shared pool)
-- ot_rate
-- PN thường: 50.000đ/h, PN BS: 150.000đ/h, Daisy thường: 35.000đ/h
-- explicit deferred
-- remote_request (không seed vào Day-1 flow)D4) Quy tắc đối chiếu kết quả (Test Oracle)
| Artifact | Mục đích |
|---|---|
timekeeping-isolation-matrix.csv | Case expected theo từng unit |
timekeeping-working-sheet-sample.xlsx | Đối chiếu working sheet/export |
mobile-cta-state-matrix.md | Oracle cho CTA mobile |
gps-branch-validation-matrix.csv | Oracle cho GPS đúng/sai theo branch trong unit |
penalty-calculation-matrix.csv | Oracle cho tiền phạt theo penalty_rule per unit |
ot-rate-calculation-matrix.csv | Oracle cho tiền OT theo ot_rate per role |
D5) Điều kiện vào / ra (Entry / Exit)
Entry
- Seed data cho 3 unit có sẵn
- Shift PN 2 mốc, PN ca gãy 4 mốc, và Daisy 4 mốc có sẵn
- Approver timekeeping có cấu hình mẫu
- GPS test points cho ít nhất 1 branch đúng unit và 1 branch ngoài unit
- Penalty rules và OT rates đã seed theo D3
Exit
- Tất cả P0 pass
- Không có regression P0/P1 với Diva timekeeping hiện tại
- Export vận hành khớp working sheet
- Daisy 4 mốc, PN 4 mốc (ca gãy) và PN 2 mốc (ca thường) pass pilot smoke
- GPS validation matrix pass
- Penalty + OT export khớp test oracle