Files
HRM-System/app/Http/Controllers/Api/AttendanceSyncController.php

106 lines
3.6 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Branch;
use App\Models\AttendanceEmployee;
use Illuminate\Support\Facades\Log;
class AttendanceSyncController extends Controller
{
public function sync(Request $request)
{
// 1. Verify API Key
$apiKey = $request->header('X-API-Key') ?? $request->input('api_key');
// You should store a master API key in your .env like ZKTECO_SYNC_KEY=xxx
$validKey = env('ZKTECO_SYNC_KEY', 'default_secure_sync_key_123');
if ($apiKey !== $validKey) {
Log::warning('Unauthorized ZKTeco sync attempt', ['ip' => $request->ip()]);
return response()->json(['error' => 'Unauthorized'], 401);
}
$branchId = $request->input('branch_id');
$zktecoIp = $request->input('zkteco_ip');
$attendances = $request->input('attendances', []);
if (empty($attendances)) {
return response()->json(['message' => 'No attendance records provided'], 400);
}
// 2. Find the branch
$branchQuery = Branch::query();
if ($branchId) {
$branchQuery->where('id', $branchId);
} elseif ($zktecoIp) {
$branchQuery->where('zkteco_ip', $zktecoIp);
} else {
return response()->json(['error' => 'Must provide branch_id or zkteco_ip'], 400);
}
$branch = $branchQuery->first();
if (!$branch) {
return response()->json(['error' => 'Branch not found'], 404);
}
// 3. Process the logs (same logic as BiometricAttendanceController)
$processed = 0;
$inserted = 0;
foreach ($attendances as $record) {
$processed++;
// Typical payload from zklib-js: { userSn: 1, deviceUserId: '1', recordTime: '2023-10-14 08:30:00' }
$empCode = $record['deviceUserId'] ?? $record['id'] ?? null;
$punchTime = $record['recordTime'] ?? $record['timestamp'] ?? null;
if (!$empCode || !$punchTime) {
continue;
}
// Find employee by emp_code inside this branch's company
$employee = \App\Models\Employee::where('emp_code', $empCode)
->where('created_by', $branch->created_by)
->first();
if (!$employee) {
continue;
}
// Parse date and time
$ts = strtotime($punchTime);
$date = date('Y-m-d', $ts);
$time = date('H:i:s', $ts);
// Check if record already exists to prevent duplicates
$exists = AttendanceEmployee::where('employee_id', $employee->id)
->where('date', $date)
->where('clock_in', $time)
->exists();
if (!$exists) {
AttendanceEmployee::create([
'employee_id' => $employee->id,
'date' => $date,
'status' => 'Present',
'clock_in' => $time,
'clock_out' => '00:00:00',
'late' => '00:00:00',
'early_leaving' => '00:00:00',
'overtime' => '00:00:00',
'total_rest' => '00:00:00',
'created_by' => $branch->created_by,
]);
$inserted++;
}
}
return response()->json([
'success' => true,
'message' => "Processed {$processed} records, Inserted {$inserted} new attendances.",
]);
}
}