Files
HRM-System/docs/PLAN-biometric-sync.md

58 lines
4.0 KiB
Markdown

# Biometric Attendance Synchronization Assessment & Manual Pairing Plan
This plan documents the current integration state between the biometric devices, the Windows Sync Agent, and the core HRMS attendance records, and proposes a design for enhanced manual pairing when multiple daily pings occur.
---
## 🔍 Codebase Assessment Findings
### 1. The Sync Pipeline Architecture
The system uses a pull-then-push architecture split into three main parts:
1. **Branch Sync Agent (`branch-agent/sync.js`)**:
- A packaged Node.js script (`sync-agent.exe`) running locally on a branch PC.
- It queries the local ZKTeco biometric device via TCP (port 4370) using the `zklib-js` library.
- It filters pings to the last 15 days and sends an HTTP POST request with an API key to the cloud API endpoint: `/api/zkteco/sync`.
2. **Receiving API (`AttendanceSyncController@sync`)**:
- Authenticates the agent using the `ZKTECO_SYNC_KEY` (configured in `.env`).
- Receives the JSON payload and registers punches in the `biometric_attendances` table with a state of `pending`. It avoids duplicates by checking `biometric_emp_id` and `punch_time`.
3. **Attendance Mapping & Conversion (`BiometricAttendanceController`)**:
- **Is it synced automatically?** **No.** It is currently designed to be manually triggered by an HR administrator from the `/hr/biometric-attendance` dashboard.
- **How it works:**
- **Bulk Trigger (`Pull Data & Sync` button)**: Loops through all `pending` biometric records, groups them by employee + date, takes the **first entry** as `clock_in`, the **last entry** as `clock_out` (requires at least 2 pings), creates an `AttendanceRecord`, and processes payroll hours.
- **Row Trigger (`Sync` action)**: Syncs a single employee-day grouping using the first/last punch logic.
---
## 🛠️ Proposed Improvements: Manual Triggering & Multiple Punch Pairing
Currently, if an employee has multiple entries (e.g., Clock In, break pings, Clock Out), the system automatically picks the first and last. If the user wants to **manually pair** custom punch times (e.g. ignoring a false scan or choosing a specific middle scan):
### Phase 1: Database Schema Support
No schema changes are required as `BiometricAttendance` records already store the individual raw punch timestamps and can be marked as `synced` individually.
### Phase 2: Backend Controller Updates (`BiometricAttendanceController`)
- **[New Endpoint] Custom Sync Pairing (`/hr/biometric-attendance/sync-custom`)**:
- Accept a custom POST request containing `employee_code`, `date`, `clock_in_biometric_id`, and `clock_out_biometric_id`.
- Fetch the specific biometric records by ID to extract the custom clock-in and clock-out times.
- Insert/update the `AttendanceRecord` with these custom values.
- Mark all biometric entries for that employee/date as `synced`.
### Phase 3: Frontend UI Enhancements (`resources/js/pages/hr/biometric-attendance/index.tsx`)
- Enhance the **Details Modal** (`View` component) to display checkbox selectors or action buttons next to the list of pings for a specific day.
- Allow HR to check one ping as the desired **"Clock In"** and another ping as the **"Clock Out"**.
- Provide a **"Confirm Custom Sync"** button in the modal that triggers the new custom pairing endpoint.
---
## 📋 Verification Plan
### Automated Verification
- Run `npm run build` to verify React components bundle correctly with Shadcn UI additions.
- Execute unit/integration tests for the new `sync-custom` endpoint.
### Manual Walkthrough
1. **Agent Simulation**: Push mock data containing 4 punches for an employee on a single day to `/api/zkteco/sync`.
2. **Dashboard Review**: View the record on the `/hr/biometric-attendance` page (it will show 4 total entries).
3. **Details Pairing**: Click "Details" (Eye icon), select Punch #1 as Clock In and Punch #4 as Clock Out, and click "Confirm Custom Sync".
4. **Attendance Parity**: Verify that the generated `AttendanceRecord` matches the chosen times, and all 4 logs are marked as `synced`.