Appearance
Type Deep Dive — Timesheet Merge And Side Effects
1. WorkingTimeSheet là merged projection
Page này load riêng:
ListTimeKeepingtừtime_slot_time_keeping,ListRequestWorkingScheduletừrequest_working_schedulevớistatus_id = approved,- rồi merge vào
workingShiftlocal state và storeuseWorkingScheduleStore.
formatSummary() chỉ tìm ô ngày từ time_slot_time_keeping. Phần request approved được component cell đọc thêm từ store.
2. Cell rendering precedence
WorkingTimeSheetItem:
- load
time_slot_usercủa ngày đó khi mở popup, - lấy request approved theo user từ store,
- filter request theo
dateCompare(created_at)và behavior đặc biệt nhưremote_weekly, - render popup gồm:
- slot chuẩn / changed shift,
- danh sách request approved của ngày,
- clock in / clock out / late / early / overtime / off flags.
Nói cách khác, một ô timesheet là synthesized view từ nhiều sources chứ không phải một record đơn.
3. Auto update flags
Cell dùng auto_update_reason để gắn cờ cho clock in/out tự cập nhật từ:
- request clock in/out,
- remote work request,
- forget clock in,
- forget clock out.
Điều này phản ánh rằng approved request có thể backfill timesheet thay vì chỉ hiện comment phụ.
4. Salary/timekeeping side effects
Trong request_working_schedule_update:
- approved leave có thể tăng
actual_workdayvà cập nhật/chèntime_slot_time_keeping, - remote onetime/clock in out path có logic backfill attendance,
- cancel/reject path có rollback tương ứng,
- annual leave path còn chạm
employee_profilevà annual leave logs.
Do đó WorkingTimeSheet chỉ là màn xem; source mutation thật nằm ở event side effects.
5. Export and report implication
Export components của timesheet đọc cùng family data và request overlays. Nếu request chưa được approve, export/report tháng sẽ không phản ánh request đó.
6. Findings kỹ thuật
| ID | Mức | Finding |
|---|---|---|
| T-01 | P0 | Timesheet UI không phải direct reflection của time_slot_time_keeping; nó phụ thuộc thêm approved requests stored theo user. |
| T-02 | P1 | Request matching trong cell dựa trên created_at của ô timesheet và khoảng from/to của request; semantics này đúng cho nhiều loại request nhưng cần test kỹ với range dài và remote_weekly. |
| T-03 | P1 | Vì ListRequestWorkingSchedule chỉ lấy approved requests, pending/rejected requests hoàn toàn biến mất khỏi bảng công dù user có thể kỳ vọng "đơn đã tạo" vẫn hiện ở đâu đó. |
| T-04 | P1 | Salary/timekeeping mutation nằm ở backend event, nên nếu event trigger fail thì UI query có thể lệch khỏi kỳ vọng approval dù action approve đã trả thành công. |