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

4.0 KiB

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.