Payroll / Timesheet — Góc nhìn end-user
Bốn bề mặt: Finance Settings (admin chọn cơ sở giờ), Staff Attendance (staff/admin chấm công), Timesheet Approved tab (admin duyệt & export) và dòng nghỉ không ca (leave-only row).
A. Finance Settings → Payroll tab
Admin Portal → Settings → Finance → Payroll. Tab chỉ hiện khi BU đang bật Staff Roster.
- Tab
Payrollhiện ngay sau Subsidy Settings; ẩn khi user/session không có quyềnSTAFF_ROSTERcho BU hiện tại. - Route
/settings/finance/payrollbảo vệ cùng quy tắc: truy cập thẳng khi không cóSTAFF_ROSTER→ không mở được. - Form có 2 lựa chọn map thẳng backend:
Rostered Hours=0,Actual Hours=1; thiếu setting → mặc địnhRostered Hours(0). - Lưu yêu cầu quyền
SettingFinance; payloadBusinessUnitPayrollSettingModelquaGET/POST /api/BusinessUnitSetting/Payroll(route là ranh giới quyền, không phải table).
Ví dụ thực tế: Admin không thấy tab Payroll trong Settings → Finance. → BU thiếu STAFF_ROSTER hoặc chưa bật Staff Roster. → Tab không render đúng quy tắc, không phải lỗi UI.
B. Staff Attendance — clock-in / clock-out
Màn chấm công; tạo ca mới cho nhân viên trong BU hiện tại.
- Clock-in ca mới: thiếu link
OrgEmployeeactive choEmployeeId+OrgId→ tự tạo rồi gánShift.OrgEmployeeId; đã có → tái dùng, không tạo trùng. - Clock-out tạo ca kế tiếp: ca copy thiếu/inactive
OrgEmployeeId→ resolve/tạo link active trước khi lưu ca mới. - Nhân viên hoặc org không active trong BU → ca mới bị reject, không tạo
OrgEmployee, không tạo ca.
Ví dụ thực tế: Staff chưa có OrgEmployee ở site mới, bấm clock-in. → Không để ca lưu fail vì thiếu link. → Backend tự tạo OrgEmployee active gắn vào Shift.OrgEmployeeId.
C. Timesheet Approved tab — export CSV
Timesheet → tab Approved → chọn dòng → Export. Toàn bộ file do server dựng, browser không assemble.
- Chọn dòng xong bấm Export → hệ thống hỏi chọn mode trước khi sinh file, mặc định
separated.separated: mỗi dòng timesheet được chọn = 1 CSV record.grouped: mỗi staff = 1 CSV record, gộp tổng giờ các dòng đã chọn.
- Hủy prompt: không sinh file, không đánh dấu dòng exported, giữ nguyên selection.
- File tải về là CSV duy nhất (không xlsx/PDF), tên file suy từ khoảng ngày yêu cầu.
- Dòng exported thành công được đánh dấu
exported; action un-export xóa cờ để dòng được chọn lại. - Dòng đã exported bị khóa chọn; chỉ còn action un-export.
Ví dụ thực tế: Admin chọn 3 dòng, Export mode separated. → File không phụ thuộc nội dung hiển thị của browser. → Server re-query 3 id, jsReport render CSV, đánh dấu 3 dòng exported trong một round-trip.
D. Dòng nghỉ không ca (leave-only row)
EmployeeAbsenceapproved vào ngày không có ca → hiện thành một dòng riêng vớiDate,Name,Leave Hours,Tracking Code;Orgvà cột giờ ca để trống.- Có vòng duyệt riêng: chuyển giữa draft / approved tab theo trạng thái timesheet của chính absence, không đụng duyệt leave.
- Approve/un-approve/export/un-export hoạt động như dòng ca, nhưng không ghi paid time / duration (không tồn tại trên leave).
- Leave trùng ca không tạo leave-only row — vẫn hiển thị bên trong cột leave của dòng ca.
- Leave chưa approved (pending/rejected) không xuất hiện thành dòng timesheet ở bất kỳ tab nào.
Ví dụ thực tế: Nghỉ approved 09:00–13:00 (code AL) hôm không có ca. → Dòng nghỉ vẫn vào bảng lương. → Timesheet hiện 1 dòng leave-only: Leave Hours = 4.00, Tracking Code = AL, cột giờ ca trống.
Tóm lại
| Vai | Làm gì |
|---|---|
| Admin (Finance) | Bật/đổi cơ sở giờ Rostered Hours / Actual Hours theo BU trong Settings → Finance → Payroll. |
| Staff / Admin (Attendance) | Clock-in/out; ca mới tự đảm bảo link OrgEmployee. |
| Admin (Timesheet) | Duyệt/un-duyệt dòng, chọn mode export, un-export; xử lý cả dòng ca và dòng nghỉ không ca. |
Contract hiển thị ngày/giờ trong export
Attendance export dùng ngày theo ISO và thời gian 24 giờ. Đây là format của file do server dựng, không phải format tạm của bảng Timesheet trên browser.
Ví dụ thực tế: Ca bắt đầu 08:05. → CSV ghi
08:05, không đổi thành8:05 AMtheo locale máy người dùng.