Appearance
Timekeeping - Technical Map
Auto-generated bởi codebase-doc-generator ngày 2026-03-23 (verified từ code thực). Không chỉnh sửa thủ công.
Routes
| Route | Path | Mục đích |
|---|---|---|
ROUTE_TIMEKEEPING_WORKING_SCHEDULE | /t/working-schedule | Ma trận lịch làm việc theo tuần |
ROUTE_TIMEKEEPING_WORKING_SHEET | /t/working-sheet | Bảng chấm công theo tháng |
Navigation & Permission
| Item | Giá trị |
|---|---|
| Menu title | Chấm Công |
Menu moduleId | clocking_management |
Working schedule moduleId | working_schedule |
Working sheet moduleId | clocking_history |
| Platforms | Admin, CRM, POS |
Permission matrix
| Area | Permissions |
|---|---|
| Working schedule route | ITLeader, ITStaff, BranchPOS, USER_GROUP_TREE[CallCenter] |
| Working sheet route config | ITLeader, ITStaff, BranchPOS |
| Working sheet submenu | ITLeader, ITStaff |
| FullPermissionWorkingTimeSheet | BOD, HRLeader, HRStaff, HRCheck, AuditLeader, ITLeader, ITStaff |
FE Pages (3)
| Page | File | Vai trò |
|---|---|---|
| Working schedule | pages/WorkingSchedule.tsx | Ma trận 7 ngày, filter phòng ban, import/export, edit |
| Working schedule create/edit | pages/WorkingScheduleCreate.tsx | Wrapper submit cho WorkingScheduleForm |
| Working time sheet | pages/WorkingTimeSheet.tsx | Ma trận chấm công theo tháng |
FE Components (8)
| Component | Vai trò |
|---|---|
WorkingScheduleForm | Form tạo/sửa lịch làm việc |
WorkingScheduleImport | Import lịch từ Excel |
WorkingScheduleUpdateBtn | Nút edit overlay khi hover cell |
WorkingTimeSheetItem | Cell detail cho timesheet |
NoClockCell | Popup giải thích ô thiếu clocking và request liên quan |
ExportWorkingTimeSheet | Export bảng công |
ExportWorkingTimeSheetByDay | Export theo ngày |
ExportTotalWorkingTimeSheetByDay | Export tổng hợp theo ngày |
GraphQL Operations
File: diva-admin/src/modules/timekeeping/graphql/working-schedule.graphql
Schedule/template
| Operation | Mục đích |
|---|---|
GetActiveTimeSlotTemplate | Lấy mẫu ca active |
GetAllTimeSlotTemplate | Lấy toàn bộ ca để import/map |
upsertTimeSlotUser | Delete lịch cũ trong range rồi insert/upsert lịch mới |
ListWorkingShift | Lấy lịch làm việc theo user + ca + request approved |
ListUserByDepartment | Lấy user theo phòng ban |
ListTimeSlotUser | Lấy slot user trong ngày để giải thích cell timesheet |
Timesheet
| Operation | Mục đích |
|---|---|
ListTimeKeeping | Lấy time_slot_time_keeping cho bảng công |
GetExportListTimeKeeping | Export raw timesheet |
ListRequestWorkingSchedule | Overlay request approved lên timesheet |
Supporting
| Operation | Mục đích |
|---|---|
getUserForWorkingSchedule | Lấy thông tin user khi thao tác lịch |
FE Runtime logic
WorkingSchedule.tsx
| Logic | Ghi chú |
|---|---|
| Weekly range | Dùng startOfWeek(..., weekStartsOn: 1) và endOfWeek |
| Default department | Full-permission role -> "all", user thường -> phòng ban đầu tiên không in_charge |
| Columns | Sinh 7 cột từ thứ 2 đến chủ nhật |
| User scope | Kết hợp department, keyword, branch user, shift group |
| Imports | Mở WorkingScheduleImport |
WorkingScheduleCreate.tsx
| Logic | Ghi chú |
|---|---|
| Create mode | Upsert cả tuần |
| Edit mode | Nếu có workingDate hoặc slot đang sửa thì chỉ thao tác theo ngày đó |
| Submit | Mutation upsertTimeSlotUser với userIds: [value.user_id] |
WorkingTimeSheet.tsx
| Logic | Ghi chú |
|---|---|
| Monthly range | Dùng startOfMonth / endOfMonth |
| Default department | Tương tự working schedule nhưng hỗ trợ multi-department |
| Data sources | ListTimeKeeping + ListRequestWorkingSchedule + helper user scope |
| Cell rendering | Dùng WorkingTimeSheetItem hoặc NoClockCell tùy trạng thái |
NoClockCell.tsx
| Logic | Ghi chú |
|---|---|
| Request overlay | Lọc request approved theo thời gian phủ lên ngày đang xem |
remote_weekly | Kiểm tra thêm weekday để match đúng thứ |
| Popup detail | Gọi ListTimeSlotUser để hiển thị khung giờ chuẩn và request liên quan |
Import logic
| Logic | Ghi chú |
|---|---|
| Parse row | Bỏ qua 2 dòng đầu, đọc từ row 3 |
| Day mapping | 7 ô ngày map sang tuần hiện tại hoặc tuần sau |
| User mapping | userName -> userName@diva.vn |
| Multi-shift | Một ô có thể chứa nhiều mã ca, tách bằng dấu phẩy |
Backend Actions / Events
check_attendance.go
| Hành vi | Ghi chú |
|---|---|
| Action name | checkAttendance |
| Input | status |
| Supported path | Hiện chỉ xử lý check_in |
| First download path | Nếu account chưa is_downloaded, cập nhật account và insert attendance trong cùng mutation |
| Side effects | Customer popup event + gamification login mission |
attendance_insert.go
| Hành vi | Ghi chú |
|---|---|
| Event name | attendance_insert |
| Trigger | Sau khi insert attendance |
| Side effect | AddPointsToCustomer() theo app settings |
Timekeeping/request events liên quan
| Event | Vai trò |
|---|---|
request_working_schedule_insert | Xử lý lifecycle request liên quan lịch/chấm công |
request_working_schedule_update | Đồng bộ request approved vào time_slot_time_keeping / slot |
time_slot_template_update | Đồng bộ thay đổi template xuống time_slot_user hiện có |
Store / Data model
time_slot_user
| Field | Ý nghĩa |
|---|---|
user_id | Nhân viên |
start_time, end_time | Giờ ca |
name | Tên ca snapshot |
break_time, start_break_time, end_break_time | Nghỉ giữa ca |
workday | Giá trị ngày công của ca |
time_keeping_id | Link sang bản ghi timesheet nếu đã map |
time_slot_time_keeping
| Field | Ý nghĩa |
|---|---|
created_by | Nhân viên được chấm công |
created_at | Thời điểm record |
clock_in, clock_out | Giờ vào/ra |
late_arrival, leave_early, off, overtime, is_holiday | Flags nghiệp vụ |
workday | Giá trị ngày công thực tế |
position_in, position_out | Vị trí check-in/out |
device_id_in, device_id_out | Thiết bị chấm công |
auto_update_reason | Lý do hệ thống tự hiệu chỉnh dữ liệu |
request_working_schedule
| Field | Ý nghĩa |
|---|---|
status_id | pending, approved, rejected, recalled, canceled, approved_step_one |
type | change_shift, overtime, leave, late_arrival_early_leave, forget_clock_in_out, clock_in_out, onsite, remote, ... |
behavior | Chi tiết hành vi như late_arrival, early_leave, remote_weekly, annual_leave |
from, to | Khoảng thời gian request |
workday | Ngày công điều chỉnh |
clock_in_out_items | Item con cho request clocking |
weekday | JSON weekday cho các request lặp như remote_weekly |
attendance
| Field | Ý nghĩa |
|---|---|
user_id | User attendance |
status | check_in / check_out |
created_at | Thời điểm attendance |
consecutive | Chuỗi streak hiện tại |
consecutive_record | Kỷ lục streak |
Key helper functions
| Function | Vai trò |
|---|---|
GetStartEndTimeKeeping() | Tính lại khung giờ chuẩn dựa trên slot + request |
MutationTimeSlotTimeKeeping() | Upsert timesheet với danh sách cột update khá rộng, gồm cả auto_update_reason |
QueryTimeSlotUser() | Query slot theo where/order; trả ErrTimeSlotUserNotFound nếu rỗng |
dateCompare() | So sánh request có phủ lên ngày chấm công hay không |
Attendance schema
Migration 1666248708222_attendance
| Object | Vai trò |
|---|---|
attendance_status | Master 2 trạng thái check_in, check_out |
attendance | Bảng log attendance |
attendance_unique | View lấy min(created_at) theo user_id, status, ngày ở timezone Asia/Ho_Chi_Minh |
Migration 1667186720446_alter_table_public_attendance_add_column_consecutive
| Cột | Vai trò |
|---|---|
consecutive | Chuỗi ngày liên tiếp |
consecutive_record | Kỷ lục chuỗi ngày liên tiếp |
Rủi ro / Findings kỹ thuật
| # | Note |
|---|---|
| 1 | MODULE_TIMEKEEPING = "t" làm route ngắn nhưng gây khó đọc khi tìm code theo tên module. |
| 2 | Mutation upsertTimeSlotUser xóa lịch cũ trong range trước khi insert lại, nên là mô hình replace-window chứ không patch từng slot nhỏ. |
| 3 | Attendance action hiện chỉ có branch xử lý check_in; check_out chưa thấy implementation thực sự trong action này. |
| 4 | Quyền clocking_history giữa route config và submenu không đồng bộ hoàn toàn cho BranchPOS. |