fix(sidebar): resolve Tailwind compile issue and z-index overlap on calendar table

This commit is contained in:
2026-06-01 16:35:32 +08:00
parent f2e451605b
commit 07b2b37530
899 changed files with 18439 additions and 93704 deletions

View File

@@ -0,0 +1,118 @@
# PLAN: Biometric Shift Swap Fix
- **Target Files:**
- `app/Http/Controllers/BiometricAttendanceController.php`
---
## 📋 Overview
Currently, biometric attendance records are grouped strictly by the **calendar date** of the punch. For employees working night/cross-midnight shifts (e.g., 3:30 PM to 12:30 AM), their Clock In falls on Day 1 (e.g., 3:23 PM) and their Clock Out falls on Day 2 (e.g., 12:30 AM).
When grouped strictly by calendar date:
- The Clock Out at 12:30 AM on Day 2 gets grouped under Day 2.
- The Clock In at 3:30 PM on Day 2 gets grouped under Day 2.
- Chronological sorting causes 12:30 AM to be treated as "Clock In" and 3:30 PM as "Clock Out," leading to a swap.
This plan details how to implement shift-aware punch grouping and synchronization to resolve this issue and support syncing single punches.
---
## 🎯 Success Criteria
1. **Correct Grouping for Night Shifts**: Clock-in and clock-out punches for cross-midnight shifts are correctly grouped under the shift's starting date (work date).
2. **No Chronological Swap**: Punch pairs are assigned to the correct fields without swapping clock-in/out.
3. **Single Punch Syncing**: Single punches are successfully synced as clock-ins with missing clock-outs, rather than being ignored.
4. **Correct Status Syncing**: Biometric logs synced via automatic or custom sync correctly update the sync status of all relevant database rows.
---
## 🛠️ Tech Stack
- **Backend Framework**: Laravel 10 / PHP 8.x
- **Database**: MariaDB / MySQL
- **Date Management**: Carbon (PHP)
---
## 📁 File Structure
No new files will be created. The changes are localized to:
- [BiometricAttendanceController.php](file:///Users/dvapp/Documents/HRM/app/Http/Controllers/BiometricAttendanceController.php)
---
## 📝 Task Breakdown
### Task 1: Create Work Date Helper Function
- **Agent**: `backend-specialist`
- **Skills**: `clean-code`, `database-design`
- **Priority**: P0
- **Dependencies**: None
- **Description**: Add a static helper function `getWorkDateForPunch` to calculate the work date for any given punch based on the employee's assigned shift start and end times with a 4-hour grace window buffer.
- **INPUT**: Carbon `$punchTime`, Employee `$employee`
- **OUTPUT**: `string` (formatted `Y-m-d` date representing the shift/work date)
- **VERIFY**: Unit test or manual call returns correct shift date for night shift boundaries (e.g., `2026-05-22 00:30` returns `2026-05-21`).
---
### Task 2: Update index() Listing Grouping
- **Agent**: `backend-specialist`
- **Skills**: `clean-code`
- **Priority**: P1
- **Dependencies**: Task 1
- **Description**: Refactor the grouping logic in `BiometricAttendanceController@index` to group punches by work date rather than calendar date.
- **INPUT**: Raw biometric logs from DB
- **OUTPUT**: Grouped logs mapped by `$employeeId . '_' . $workDate`
- **VERIFY**: View the Biometric Attendance page; verify that Ana's punches for `2026-05-21` (3:23 PM and 12:30 AM next day) appear on a single row under date `2026-05-21`.
---
### Task 3: Update show() Detail Retrieval
- **Agent**: `backend-specialist`
- **Skills**: `clean-code`
- **Priority**: P1
- **Dependencies**: Task 1
- **Description**: Refactor `show()` to query punches in a +/- 1 day window around the work date, filtering them using `getWorkDateForPunch` to ensure punches on adjacent calendar days are retrieved.
- **INPUT**: `employeeCode`, `date` (work date)
- **OUTPUT**: JSON response containing all punches matching the work date
- **VERIFY**: Click "Details" modal for Ana's `2026-05-21` row; confirm both the `15:23` clock-in and the `00:30` next-day clock-out are listed.
---
### Task 4: Refactor syncAll() Bulk Syncing Logic
- **Agent**: `backend-specialist`
- **Skills**: `clean-code`
- **Priority**: P1
- **Dependencies**: Task 1
- **Description**:
1. Group pending biometric records using the new work-date helper.
2. Change the check from `$sorted->count() > 1` to `$sorted->count() >= 1` to support single-punch sync.
3. If only one punch is present, set `clock_in` to the punch time and `clock_out` to `null`.
4. Ensure all biometric records resolving to the synced work date are marked as `synced` in the DB.
- **INPUT**: Pending biometric records
- **OUTPUT**: Created/updated `AttendanceRecord`s and updated `sync_status`
- **VERIFY**: Perform bulk sync; check that single-punch employees get imported as "absent/present" with `clock_out = null` and all matched rows are marked `synced`.
---
### Task 5: Refactor sync() and syncCustom() Single Syncing Logic
- **Agent**: `backend-specialist`
- **Skills**: `clean-code`
- **Priority**: P1
- **Dependencies**: Task 1
- **Description**: Refactor `sync()` and `syncCustom()` to find and mark all associated biometric logs resolving to the synced work date as `synced` (rather than just matching the calendar date).
- **INPUT**: `sync` or `syncCustom` requests
- **OUTPUT**: Updated attendance sheets and correct `sync_status` in biometric logs
- **VERIFY**: Perform custom sync on a cross-midnight row; verify that both the Day 1 and Day 2 biometric rows are successfully marked as `synced`.
---
## ✅ PHASE X: Verification Checklist
### Automated Audits
- Run Laravel Tests (if any): `php artisan test`
- Security scan: `python .agent/skills/vulnerability-scanner/scripts/security_scan.py .`
### Manual Verification
- [ ] Check shift configurations in database to verify night-shift designations.
- [ ] Verify Ana's `2026-05-21` punches are correctly grouped under the `2026-05-21` row on the index page.
- [ ] Verify detail modal retrieves cross-midnight punches.
- [ ] Test sync with single-punch records (only clock-in, no clock-out).
- [ ] Check DB to ensure all relevant biometric punch rows are marked `synced` after synchronization.