diff --git a/.DS_Store b/.DS_Store index e7e831448..96220d98c 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/app/Console/Commands/ClearOldBiometricData.php b/app/Console/Commands/ClearOldBiometricData.php new file mode 100644 index 000000000..9141cb612 --- /dev/null +++ b/app/Console/Commands/ClearOldBiometricData.php @@ -0,0 +1,34 @@ +subDays(30); + $deleted = BiometricAttendance::where('punch_time', '<', $date)->delete(); + $this->info("Deleted {$deleted} old biometric attendance records."); + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index f04b3d03b..7004f0ef0 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -13,6 +13,7 @@ class Kernel extends ConsoleKernel protected function schedule(Schedule $schedule): void { // $schedule->command('inspire')->hourly(); + $schedule->command('biometric:clear-old')->daily(); } /** diff --git a/app/Http/Controllers/Api/AttendanceSyncController.php b/app/Http/Controllers/Api/AttendanceSyncController.php index 647f24aa8..975897f38 100644 --- a/app/Http/Controllers/Api/AttendanceSyncController.php +++ b/app/Http/Controllers/Api/AttendanceSyncController.php @@ -46,8 +46,8 @@ class AttendanceSyncController extends Controller return response()->json(['error' => 'Branch not found'], 404); } - // 3. Process the logs into a standardized format for the dashboard - $formattedAttendances = []; + // 3. Save directly to biometric_attendances table + $processed = 0; foreach ($attendances as $record) { $empCode = $record['deviceUserId'] ?? $record['id'] ?? null; $rawPunchTime = $record['recordTime'] ?? $record['timestamp'] ?? null; @@ -56,47 +56,28 @@ class AttendanceSyncController extends Controller $type = $record['state'] ?? $record['type'] ?? 0; if ($empCode && $punchTime) { - // We format it identically to how ZKTeco hardware outputs `$raw_attendance` - // so BiometricAttendanceController can process it natively. - $formattedAttendances[] = [ - 'uid' => $uid, - 'id' => (string) $empCode, - 'timestamp' => $punchTime->toDateTimeString(), // Clean Y-m-d H:i:s format - 'type' => $type - ]; - } - } + // Insert or ignore based on biometric_emp_id and punch_time to prevent duplicates + $exists = \App\Models\BiometricAttendance::where('biometric_emp_id', $empCode) + ->where('punch_time', $punchTime->toDateTimeString()) + ->exists(); - // Save the formatted records to a JSON file cache for the branch - if (!empty($formattedAttendances)) { - $filePath = storage_path("app/biometric_cache_branch_{$branch->id}.json"); - - // If the file exists, we merge the new records with the old ones, keeping only unique punches - if (file_exists($filePath)) { - $existing = json_decode(file_get_contents($filePath), true) ?? []; - $merged = array_merge($existing, $formattedAttendances); - - // Remove exact duplicates by using a unique key - $unique = collect($merged)->unique(function ($item) { - return $item['id'] . '_' . $item['timestamp']; - })->values()->toArray(); - - // Keep only the last 3000 records to prevent file bloat - if (count($unique) > 3000) { - $unique = array_slice($unique, -3000); + if (!$exists) { + \App\Models\BiometricAttendance::create([ + 'branch_id' => $branch->id, + 'biometric_emp_id' => $empCode, + 'punch_time' => $punchTime->toDateTimeString(), + 'punch_type' => $type, + 'terminal_alias' => $branch->name . ' (Agent)', + 'sync_status' => 'pending', + ]); + $processed++; } - - file_put_contents($filePath, json_encode($unique)); - } else { - file_put_contents($filePath, json_encode($formattedAttendances)); } } - $processed = count($formattedAttendances); - return response()->json([ 'success' => true, - 'message' => "Successfully pushed {$processed} records to the Biometric Attendance waiting room for Branch {$branch->id}.", + 'message' => "Successfully pushed {$processed} new records to the Biometric Attendance database for Branch {$branch->id}.", ]); } diff --git a/app/Http/Controllers/BiometricAttendanceController.php b/app/Http/Controllers/BiometricAttendanceController.php index b5d680d81..7cd3963ff 100644 --- a/app/Http/Controllers/BiometricAttendanceController.php +++ b/app/Http/Controllers/BiometricAttendanceController.php @@ -17,218 +17,97 @@ class BiometricAttendanceController extends Controller { public function index(Request $request) { - if (Auth::user()->can('manage-biometric-attendance')) { - $company_setting = settings(); - $api_urls = !empty($company_setting['zkteco_api_url']) ? $company_setting['zkteco_api_url'] : ''; - $username = !empty($company_setting['zkteco_username']) ? $company_setting['zkteco_username'] : ''; - $password = !empty($company_setting['zkteco_password']) ? $company_setting['zkteco_password'] : ''; - $token = !empty($company_setting['zkteco_auth_token']) ? $company_setting['zkteco_auth_token'] : ''; - $isZktecoSync = !empty($company_setting['isZktecoSync']) && $company_setting['isZktecoSync'] == '1'; - - $isDirectIP = filter_var($api_urls, FILTER_VALIDATE_IP); - - // Check if any branches are configured for local IP (which the agent uses) - $branches = \App\Models\Branch::whereNotNull('zkteco_ip')->whereIn('created_by', getCompanyAndUsersId())->get(); - - $configurationMissing = empty($api_urls) || (!$isDirectIP && (empty($username) || empty($password) || empty($token) || !$isZktecoSync)); - - // If branches have IPs configured, we don't need the global API settings - if ($branches->isNotEmpty()) { - $configurationMissing = false; - } - - if (!empty($request->start_date) && !empty($request->end_date)) { - $start_date = date('Y-m-d H:i:s', strtotime($request->start_date)); - $end_date = date('Y-m-d H:i:s', strtotime($request->end_date) + 86400 - 1); - } else { - $start_date = date('Y-m-d', strtotime('-7 days')); - $end_date = date('Y-m-d'); - } - - $attendances = []; - - $branches = \App\Models\Branch::whereNotNull('zkteco_ip')->whereIn('created_by', getCompanyAndUsersId())->get(); - if ($branches->isNotEmpty()) { - foreach ($branches as $branch) { - try { - $zk = new \App\Library\ZKTeco\ZKTeco($branch->zkteco_ip); - if ($zk->connect()) { - $raw_attendance = $zk->getAttendance(); - $startTs = strtotime(strlen($start_date) == 10 ? $start_date . ' 00:00:00' : $start_date); - $endTs = strtotime(strlen($end_date) == 10 ? $end_date . ' 23:59:59' : $end_date); - foreach ($raw_attendance as $record) { - $punchTs = strtotime($record['timestamp']); - if ($punchTs >= $startTs && $punchTs <= $endTs) { - $attendances[] = [ - 'id' => $record['uid'], - 'emp_code' => (string) $record['id'], - 'punch_time' => $record['timestamp'], - 'punch_state_display' => $record['type'] == 0 ? 'Clock In' : 'Clock Out', - 'terminal_alias' => $branch->name, - 'branch_id' => $branch->id - ]; - } - } - $zk->disconnect(); - } - } catch (\Throwable $th) {} - - // Read from local JSON cache if agent pushed data - try { - $cacheFile = storage_path("app/biometric_cache_branch_{$branch->id}.json"); - if (file_exists($cacheFile)) { - $cached_attendance = json_decode(file_get_contents($cacheFile), true) ?? []; - $startTs = strtotime(strlen($start_date) == 10 ? $start_date . ' 00:00:00' : $start_date); - $endTs = strtotime(strlen($end_date) == 10 ? $end_date . ' 23:59:59' : $end_date); - foreach ($cached_attendance as $record) { - $punchTs = strtotime($record['timestamp']); - if ($punchTs >= $startTs && $punchTs <= $endTs) { - $attendances[] = [ - 'id' => $record['uid'], - 'emp_code' => (string) $record['id'], - 'punch_time' => $record['timestamp'], - 'punch_state_display' => $record['type'] == 0 ? 'Clock In' : 'Clock Out', - 'terminal_alias' => $branch->name . ' (Agent)', - 'branch_id' => $branch->id - ]; - } - } - } - } catch (\Throwable $th) {} - } - } else if (!empty($api_urls)) { - if ($isDirectIP) { - try { - $zk = new \App\Library\ZKTeco\ZKTeco($api_urls); - if ($zk->connect()) { - $raw_attendance = $zk->getAttendance(); - $startTs = strtotime(strlen($start_date) == 10 ? $start_date . ' 00:00:00' : $start_date); - $endTs = strtotime(strlen($end_date) == 10 ? $end_date . ' 23:59:59' : $end_date); - foreach ($raw_attendance as $record) { - $punchTs = strtotime($record['timestamp']); - if ($punchTs >= $startTs && $punchTs <= $endTs) { - $attendances[] = [ - 'id' => $record['uid'], - 'emp_code' => (string) $record['id'], - 'punch_time' => $record['timestamp'], - 'punch_state_display' => $record['type'] == 0 ? 'Clock In' : 'Clock Out', - 'terminal_alias' => 'Local ZKTeco' - ]; - } - } - $zk->disconnect(); - } - } catch (\Throwable $th) {} - } else if (!empty($token)) { - $api_url = rtrim($api_urls, '/'); - $url = $api_url . '/iclock/api/transactions/?' . http_build_query([ - 'start_time' => $start_date, - 'end_time' => $end_date, - 'page_size' => 10000, - ]); - $curl = curl_init(); - try { - curl_setopt_array($curl, array( - CURLOPT_URL => $url, - CURLOPT_RETURNTRANSFER => true, - CURLOPT_HTTPHEADER => array('Content-Type: application/json', 'Authorization: Token ' . $token) - )); - $response = curl_exec($curl); - curl_close($curl); - $json = json_decode($response, true); - $attendances = $json['data'] ?? []; - } catch (\Throwable $th) {} - } - } - - - if (isDemo()) { - $attendances = isSaas() ? $this->getSaasDemoData() : $this->getNonSaasDemoData(); - } - - - // Group by employee code and date - $groupedAttendances = collect($attendances) - ->groupBy(function ($item) { - return $item['emp_code'] . '_' . date('Y-m-d', strtotime($item['punch_time'])); - }) - ->map(function ($dayEntries) { - $sorted = $dayEntries->sortBy('punch_time'); - $firstEntry = $sorted->first(); - $lastEntry = $sorted->last(); - $q = Employee::with('user')->where('biometric_emp_id', $firstEntry['emp_code']); - if (isset($firstEntry['branch_id'])) { - $q->where('branch_id', $firstEntry['branch_id']); - } - $employee = $q->first(); - if (!$employee) return null; - - return [ - 'id' => $firstEntry['id'], - 'employee_code' => $firstEntry['emp_code'], - 'name' => $employee && $employee->user ? $employee->user->name : 'Unknown', - 'date' => date('Y-m-d', strtotime($firstEntry['punch_time'])), - 'clock_in' => date('H:i:s', strtotime($firstEntry['punch_time'])), - 'clock_out' => $sorted->count() > 1 ? date('H:i:s', strtotime($lastEntry['punch_time'])) : null, - 'total_entries' => $sorted->count(), - 'terminal' => $firstEntry['terminal_alias'] ?? 'Unknown' - ]; - })->filter()->values(); - $query = $groupedAttendances; - - // Handle search - if ($request->has('search') && !empty($request->search)) { - $query = $query->filter(function ($item) use ($request) { - return stripos($item['name'], $request->search) !== false || - stripos($item['employee_code'], $request->search) !== false; - }); - } - - // Handle date range filter - if ($request->has('start_date') && !empty($request->start_date)) { - $query = $query->filter(function ($item) use ($request) { - return $item['date'] = $request->start_date; - }); - } - - if ($request->has('end_date') && !empty($request->end_date)) { - $query = $query->filter(function ($item) use ($request) { - return $item['date'] <= $request->end_date; - }); - } - - // Handle sorting - if ($request->has('sort_field') && !empty($request->sort_field)) { - $direction = $request->sort_direction ?? 'asc'; - $query = $query->sortBy($request->sort_field, SORT_REGULAR, $direction === 'desc'); - } else { - $query = $query->sortByDesc('id'); - } - - // Manual pagination for collection - $perPage = $request->per_page ?? 10; - $currentPage = $request->page ?? 1; - $total = $query->count(); - $items = $query->forPage($currentPage, $perPage)->values(); - - $biometricData = new LengthAwarePaginator( - $items, - $total, - $perPage, - $currentPage, - [ - 'path' => $request->url(), - 'pageName' => 'page', - ] - ); - return Inertia::render('hr/biometric-attendance/index', [ - 'biometricData' => $biometricData, - 'filters' => $request->all(['search', 'start_date', 'end_date', 'sort_field', 'sort_direction', 'per_page']), - 'configurationMissing' => $configurationMissing, - ]); - } else { + if (!Auth::user()->can('manage-biometric-attendance')) { return redirect()->back()->with('error', __('Permission Denied.')); } + + $query = \App\Models\BiometricAttendance::with(['branch']); + + // Filter by dates + if ($request->has('start_date') && !empty($request->start_date)) { + $query->whereDate('punch_time', '>=', $request->start_date); + } else { + $query->whereDate('punch_time', '>=', Carbon::now()->subDays(7)); + } + + if ($request->has('end_date') && !empty($request->end_date)) { + $query->whereDate('punch_time', '<=', $request->end_date); + } else { + $query->whereDate('punch_time', '<=', Carbon::now()); + } + + $records = $query->get(); + + $groupedAttendances = collect($records) + ->groupBy(function ($item) { + return $item->biometric_emp_id . '_' . $item->punch_time->format('Y-m-d'); + }) + ->map(function ($dayEntries) { + $sorted = $dayEntries->sortBy('punch_time'); + $firstEntry = $sorted->first(); + $lastEntry = $sorted->last(); + + return [ + 'id' => $firstEntry->id, + 'employee_code' => $firstEntry->biometric_emp_id, + 'date' => $firstEntry->punch_time->format('Y-m-d'), + 'clock_in' => $firstEntry->punch_time->format('H:i:s'), + 'clock_out' => $sorted->count() > 1 ? $lastEntry->punch_time->format('H:i:s') : null, + 'total_entries' => $sorted->count(), + 'terminal' => $firstEntry->terminal_alias ?? 'Agent', + 'sync_status' => $firstEntry->sync_status, + ]; + })->filter()->values(); + + // Attach employee names + $empIds = $groupedAttendances->pluck('employee_code')->unique(); + $employees = \App\Models\Employee::with('user')->whereIn('biometric_emp_id', $empIds)->get()->keyBy('biometric_emp_id'); + + $groupedAttendances = $groupedAttendances->map(function($item) use ($employees) { + $emp = $employees->get($item['employee_code']); + $item['name'] = $emp && $emp->user ? $emp->user->name : 'Unknown'; + return $item; + }); + + // Search filter + if ($request->has('search') && !empty($request->search)) { + $search = strtolower($request->search); + $groupedAttendances = $groupedAttendances->filter(function ($item) use ($search) { + return str_contains(strtolower($item['name']), $search) || + str_contains(strtolower($item['employee_code']), $search); + }); + } + + // Sorting + if ($request->has('sort_field') && !empty($request->sort_field)) { + $direction = $request->sort_direction ?? 'asc'; + $groupedAttendances = $groupedAttendances->sortBy($request->sort_field, SORT_REGULAR, $direction === 'desc'); + } else { + $groupedAttendances = $groupedAttendances->sortByDesc('date'); + } + + // Pagination + $perPage = $request->per_page ?? 10; + $currentPage = $request->page ?? 1; + $total = $groupedAttendances->count(); + $items = $groupedAttendances->forPage($currentPage, $perPage)->values(); + + $biometricData = new LengthAwarePaginator( + $items, + $total, + $perPage, + $currentPage, + [ + 'path' => $request->url(), + 'pageName' => 'page', + ] + ); + + return Inertia::render('hr/biometric-attendance/index', [ + 'biometricData' => $biometricData, + 'filters' => $request->all(['search', 'start_date', 'end_date', 'sort_field', 'sort_direction', 'per_page']), + 'configurationMissing' => false, + ]); } public function show(Request $request, $employeeCode, $date) @@ -241,107 +120,21 @@ class BiometricAttendanceController extends Controller ], 403); } - if (isDemo()) { - $allDemoData = isSaas() ? $this->getSaasDemoData() : $this->getNonSaasDemoData(); - $attendances = collect($allDemoData) - ->filter(function ($item) use ($employeeCode, $date) { - return $item['emp_code'] === $employeeCode && - date('Y-m-d', strtotime($item['punch_time'])) === $date; - }) - ->values() - ->toArray(); - } else { - $company_setting = settings(); - $token = $company_setting['zkteco_auth_token'] ?? ''; - $api_urls = $company_setting['zkteco_api_url'] ?? ''; + $attendances = \App\Models\BiometricAttendance::where('biometric_emp_id', $employeeCode) + ->whereDate('punch_time', $date) + ->orderBy('punch_time', 'asc') + ->get(); - $isDirectIP = filter_var($api_urls, FILTER_VALIDATE_IP); - - if (empty($api_urls) || (!$isDirectIP && empty($token))) { - return response()->json([ - 'success' => false, - 'message' => 'ZKTeco API configuration missing' - ], 400); - } - - if ($isDirectIP) { - try { - $zk = new \App\Library\ZKTeco\ZKTeco($api_urls); - if ($zk->connect()) { - $raw_attendance = $zk->getAttendance(); - foreach ($raw_attendance as $record) { - if ((string)$record['id'] === (string)$employeeCode && str_starts_with($record['timestamp'], $date)) { - $attendances[] = [ - 'id' => $record['uid'], - 'punch_time' => $record['timestamp'], - 'punch_state_display' => $record['type'] == 0 ? 'Clock In' : 'Clock Out', - 'verify_type_display' => 'Unknown', - 'terminal_alias' => 'Local ZKTeco' - ]; - } - } - $zk->disconnect(); - } - } catch (\Throwable $th) { - return response()->json([ - 'success' => false, - 'message' => 'Failed to connect to local ZKTeco' - ], 500); - } - } else { - $start_date = $date . ' 00:00:00'; - $end_date = $date . ' 23:59:59'; - - $api_url = rtrim($api_urls, '/'); - $url = $api_url . '/iclock/api/transactions/?' . http_build_query([ - 'emp_code' => $employeeCode, - 'start_time' => $start_date, - 'end_time' => $end_date, - 'page_size' => 1000, - ]); - - $curl = curl_init(); - curl_setopt_array($curl, [ - CURLOPT_URL => $url, - CURLOPT_RETURNTRANSFER => true, - CURLOPT_TIMEOUT => 30, - CURLOPT_HTTPHEADER => [ - 'Content-Type: application/json', - 'Authorization: Token ' . $token - ], - ]); - - $response = curl_exec($curl); - $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); - curl_close($curl); - - if ($httpCode !== 200 || !$response) { - return response()->json([ - 'success' => false, - 'message' => 'Failed to fetch data from ZKTeco API' - ], 500); - } - - $json_attendance = json_decode($response, true); - $attendances = $json_attendance['data'] ?? []; - } - } - - - // Process entries (already filtered by API) - $dayEntries = collect($attendances) - ->sortBy('punch_time') - ->map(function ($item) { - return [ - 'id' => $item['id'], - 'punch_time' => $item['punch_time'], - 'time' => date('H:i:s', strtotime($item['punch_time'])), - 'punch_state_display' => $item['punch_state_display'] ?? 'Unknown', - 'verify_type_display' => $item['verify_type_display'] ?? 'Unknown', - 'terminal_alias' => $item['terminal_alias'] ?? 'Unknown' - ]; - }) - ->values(); + $dayEntries = $attendances->map(function ($item) { + return [ + 'id' => $item->id, + 'punch_time' => $item->punch_time->format('Y-m-d H:i:s'), + 'time' => $item->punch_time->format('H:i:s'), + 'punch_state_display' => $item->punch_type == 0 ? 'Clock In' : 'Clock Out', + 'verify_type_display' => 'Unknown', + 'terminal_alias' => $item->terminal_alias ?? 'Unknown' + ]; + }); if ($dayEntries->isEmpty()) { return response()->json([ @@ -368,221 +161,38 @@ class BiometricAttendanceController extends Controller public function syncAll(Request $request) { - if (Auth::user()->can('sync-biometric-attendance')) { - $company_setting = settings(); - $api_urls = !empty($company_setting['zkteco_api_url']) ? $company_setting['zkteco_api_url'] : ''; - $token = !empty($company_setting['zkteco_auth_token']) ? $company_setting['zkteco_auth_token'] : ''; - - $start_date = date('Y-m-d', strtotime('-7 days')); - $end_date = date('Y-m-d'); - - $isDirectIP = filter_var($api_urls, FILTER_VALIDATE_IP); - $attendances = []; - - $branches = \App\Models\Branch::whereNotNull('zkteco_ip')->whereIn('created_by', getCompanyAndUsersId())->get(); - if ($branches->isNotEmpty()) { - foreach ($branches as $branch) { - try { - $zk = new \App\Library\ZKTeco\ZKTeco($branch->zkteco_ip); - if ($zk->connect()) { - $raw_attendance = $zk->getAttendance(); - $startTs = strtotime($start_date . ' 00:00:00'); - $endTs = strtotime($end_date . ' 23:59:59'); - foreach ($raw_attendance as $record) { - $punchTs = strtotime($record['timestamp']); - if ($punchTs >= $startTs && $punchTs <= $endTs) { - $attendances[] = [ - 'id' => $record['uid'], - 'emp_code' => (string) $record['id'], - 'punch_time' => $record['timestamp'], - 'branch_id' => $branch->id - ]; - } - } - $zk->disconnect(); - } - } catch (\Throwable $th) {} - - // Read from local JSON cache if agent pushed data - try { - $cacheFile = storage_path("app/biometric_cache_branch_{$branch->id}.json"); - if (file_exists($cacheFile)) { - $cached_attendance = json_decode(file_get_contents($cacheFile), true) ?? []; - $startTs = strtotime(strlen($start_date) == 10 ? $start_date . ' 00:00:00' : $start_date); - $endTs = strtotime(strlen($end_date) == 10 ? $end_date . ' 23:59:59' : $end_date); - foreach ($cached_attendance as $record) { - $punchTs = strtotime($record['timestamp']); - if ($punchTs >= $startTs && $punchTs <= $endTs) { - $attendances[] = [ - 'id' => $record['uid'], - 'emp_code' => (string) $record['id'], - 'punch_time' => $record['timestamp'], - 'branch_id' => $branch->id - ]; - } - } - } - } catch (\Throwable $th) {} - } - } else if (!empty($api_urls)) { - if ($isDirectIP) { - try { - $zk = new \App\Library\ZKTeco\ZKTeco($api_urls); - if ($zk->connect()) { - $raw_attendance = $zk->getAttendance(); - $startTs = strtotime($start_date . ' 00:00:00'); - $endTs = strtotime($end_date . ' 23:59:59'); - foreach ($raw_attendance as $record) { - $punchTs = strtotime($record['timestamp']); - if ($punchTs >= $startTs && $punchTs <= $endTs) { - $attendances[] = [ - 'id' => $record['uid'], - 'emp_code' => (string) $record['id'], - 'punch_time' => $record['timestamp'], - ]; - } - } - $zk->disconnect(); - } - } catch (\Throwable $th) {} - } else if (!empty($token)) { - $api_url = rtrim($api_urls, '/'); - $url = $api_url . '/iclock/api/transactions/?' . http_build_query([ - 'start_time' => date('Y-m-d H:i:s', strtotime($start_date . ' 00:00:00')), - 'end_time' => date('Y-m-d H:i:s', strtotime($end_date . ' 23:59:59')), - 'page_size' => 10000, - ]); - $curl = curl_init(); - try { - curl_setopt_array($curl, array( - CURLOPT_URL => $url, - CURLOPT_RETURNTRANSFER => true, - CURLOPT_HTTPHEADER => array('Content-Type: application/json', 'Authorization: Token ' . $token) - )); - $response = curl_exec($curl); - curl_close($curl); - $json = json_decode($response, true); - $attendances = $json['data'] ?? []; - } catch (\Throwable $th) {} - } - } - - $groupedAttendances = collect($attendances)->groupBy(function ($item) { - return $item['emp_code'] . '_' . date('Y-m-d', strtotime($item['punch_time'])); - }); - - $syncedCount = 0; - foreach ($groupedAttendances as $key => $dayEntries) { - $sorted = $dayEntries->sortBy('punch_time'); - $firstEntry = $sorted->first(); - $lastEntry = $sorted->last(); - - $q = Employee::with('user')->whereIn('created_by', getCompanyAndUsersId())->where('biometric_emp_id', $firstEntry['emp_code']); - if (isset($firstEntry['branch_id'])) { - $q->where('branch_id', $firstEntry['branch_id']); - } - $employee = $q->first(); - if ($employee && $sorted->count() > 1) { - $attedanceDate = date('Y-m-d', strtotime($firstEntry['punch_time'])); - $clockInTime = date('H:i:s', strtotime($firstEntry['punch_time'])); - $clockOutTime = date('H:i:s', strtotime($lastEntry['punch_time'])); - - $exists = AttendanceRecord::where('employee_id', $employee->user_id)->where('date', $attedanceDate)->whereIn('created_by', getCompanyAndUsersId())->exists(); - if (!$exists) { - $shift = Shift::where('id', $employee->shift_id)->where('status', 'active')->first() ?? Shift::whereIn('created_by', getCompanyAndUsersId())->where('status', 'active')->first(); - $policy = AttendancePolicy::where('id', $employee->attendance_policy_id)->where('status', 'active')->first() ?? AttendancePolicy::whereIn('created_by', getCompanyAndUsersId())->where('status', 'active')->first(); - - $attendance = new AttendanceRecord(); - $attendance->employee_id = $employee->user_id; - $attendance->biometric_id = $firstEntry['id']; - $attendance->shift_id = $shift?->id; - $attendance->attendance_policy_id = $policy?->id; - $attendance->date = $attedanceDate; - $attendance->clock_in = $clockInTime; - $attendance->clock_out = $clockOutTime; - $attendance->created_by = creatorId(); - $attendance->save(); - - $attendance->fresh(); - $attendance->processAttendance(); - $syncedCount++; - } - } - } - return redirect()->back()->with('success', __("Bulk sync completed. Synced {$syncedCount} new records.")); + if (!Auth::user()->can('sync-biometric-attendance')) { + return redirect()->back()->with('error', __('Permission Denied.')); } - return redirect()->back()->with('error', __('Permission Denied.')); - } - - public function sync(Request $request, $id) - { - if (Auth::user()->can('sync-biometric-attendance')) { - $biometricEmpId = $request->biometric_emp_id; - $biometricId = $request->biometric_id; - // $punchTime = $request->punch_time; - $attedanceDate = $request->date; - $clockInTime = $request->clock_in; - $clockOutTime = $request->clock_out; - - $company_setting = settings(); - - $isDirectIP = filter_var($company_setting['zkteco_api_url'] ?? '', FILTER_VALIDATE_IP); - - if (!$isDirectIP && empty($company_setting['zkteco_auth_token'])) { - return redirect()->back()->with('error', __('Create the Auth Token From the Setting page.')); - } - - $employee = Employee::with('user')->whereIn('created_by', getCompanyAndUsersId())->where('biometric_emp_id', $biometricEmpId)->first(); - - if ($employee) { - - if (is_null($clockOutTime)) { - return redirect()->back()->with('error', __("Still Employee is not Clock Out. So You Can't Sync That Attedance.")); - } - - // Check Attendance Already Sync or not - $attendance = AttendanceRecord::where('biometric_id', $biometricId) - ->where('date', $attedanceDate) - ->whereIn('created_by', getCompanyAndUsersId()) - ->first(); - - if ($attendance) { - return redirect()->back()->with('error', __('Attendance Is Alredady Sync.')); - } - - // Check if record already exists - $exists = AttendanceRecord::where('employee_id', $employee->user_id) - ->where('date', $attedanceDate) - ->whereIn('created_by', getCompanyAndUsersId()) - ->exists(); - - if ($exists) { - return redirect()->back()->with('error', __('Attendance record already exists for this employee and date.')); - } else { - $shift = Shift::where('id', $employee->shift_id) - ->where('status', 'active') - ->first(); - - if (!$shift) { - $shift = Shift::whereIn('created_by', getCompanyAndUsersId()) - ->where('status', 'active') - ->first(); - } - - $policy = AttendancePolicy::where('id', $employee->attendance_policy_id) - ->where('status', 'active') - ->first(); - - if (!$policy) { - $policy = AttendancePolicy::whereIn('created_by', getCompanyAndUsersId()) - ->where('status', 'active') - ->first(); - } - + // Fetch all pending records + $pendingRecords = \App\Models\BiometricAttendance::where('sync_status', 'pending')->get(); + + $groupedAttendances = $pendingRecords->groupBy(function ($item) { + return $item->biometric_emp_id . '_' . $item->punch_time->format('Y-m-d'); + }); + + $syncedCount = 0; + foreach ($groupedAttendances as $key => $dayEntries) { + $sorted = $dayEntries->sortBy('punch_time'); + $firstEntry = $sorted->first(); + $lastEntry = $sorted->last(); + + $employee = Employee::with('user')->whereIn('created_by', getCompanyAndUsersId())->where('biometric_emp_id', $firstEntry->biometric_emp_id)->first(); + + if ($employee && $sorted->count() > 1) { + $attedanceDate = $firstEntry->punch_time->format('Y-m-d'); + $clockInTime = $firstEntry->punch_time->format('H:i:s'); + $clockOutTime = $lastEntry->punch_time->format('H:i:s'); + + $exists = AttendanceRecord::where('employee_id', $employee->user_id)->where('date', $attedanceDate)->whereIn('created_by', getCompanyAndUsersId())->exists(); + if (!$exists) { + $shift = Shift::where('id', $employee->shift_id)->where('status', 'active')->first() ?? Shift::whereIn('created_by', getCompanyAndUsersId())->where('status', 'active')->first(); + $policy = AttendancePolicy::where('id', $employee->attendance_policy_id)->where('status', 'active')->first() ?? AttendancePolicy::whereIn('created_by', getCompanyAndUsersId())->where('status', 'active')->first(); + $attendance = new AttendanceRecord(); $attendance->employee_id = $employee->user_id; - $attendance->biometric_id = $biometricId; + $attendance->biometric_id = $firstEntry->id; $attendance->shift_id = $shift?->id; $attendance->attendance_policy_id = $policy?->id; $attendance->date = $attedanceDate; @@ -590,17 +200,100 @@ class BiometricAttendanceController extends Controller $attendance->clock_out = $clockOutTime; $attendance->created_by = creatorId(); $attendance->save(); - - $attendance->fresh(); // Reload to get relationships + + $attendance->fresh(); $attendance->processAttendance(); - - return redirect()->back()->with('success', __('Biometric data synced successfully.')); + + // Mark as synced + foreach ($dayEntries as $entry) { + $entry->update(['sync_status' => 'synced']); + } + + $syncedCount++; + } else { + // Already exists, just mark as synced so they don't pile up in pending + foreach ($dayEntries as $entry) { + $entry->update(['sync_status' => 'synced']); + } } + } + } + return redirect()->back()->with('success', __("Bulk sync completed. Synced {$syncedCount} new records.")); + } + + public function sync(Request $request, $id) + { + if (!Auth::user()->can('sync-biometric-attendance')) { + return redirect()->back()->with('error', __('Permission Denied.')); + } + + $biometricEmpId = $request->biometric_emp_id; + $biometricId = $request->biometric_id; + $attedanceDate = $request->date; + $clockInTime = $request->clock_in; + $clockOutTime = $request->clock_out; + + $employee = Employee::with('user')->whereIn('created_by', getCompanyAndUsersId())->where('biometric_emp_id', $biometricEmpId)->first(); + + if ($employee) { + if (is_null($clockOutTime)) { + return redirect()->back()->with('error', __("Still Employee is not Clock Out. So You Can't Sync That Attedance.")); + } + + // Check if record already exists + $exists = AttendanceRecord::where('employee_id', $employee->user_id) + ->where('date', $attedanceDate) + ->whereIn('created_by', getCompanyAndUsersId()) + ->exists(); + + if ($exists) { + // Just mark it as synced so it doesn't show up again + \App\Models\BiometricAttendance::where('biometric_emp_id', $biometricEmpId)->whereDate('punch_time', $attedanceDate)->update(['sync_status' => 'synced']); + return redirect()->back()->with('error', __('Attendance record already exists for this employee and date.')); } else { - return redirect()->back()->with('error', __('Employee not found')); + $shift = Shift::where('id', $employee->shift_id) + ->where('status', 'active') + ->first(); + + if (!$shift) { + $shift = Shift::whereIn('created_by', getCompanyAndUsersId()) + ->where('status', 'active') + ->first(); + } + + $policy = AttendancePolicy::where('id', $employee->attendance_policy_id) + ->where('status', 'active') + ->first(); + + if (!$policy) { + $policy = AttendancePolicy::whereIn('created_by', getCompanyAndUsersId()) + ->where('status', 'active') + ->first(); + } + + $attendance = new AttendanceRecord(); + $attendance->employee_id = $employee->user_id; + $attendance->biometric_id = $biometricId; + $attendance->shift_id = $shift?->id; + $attendance->attendance_policy_id = $policy?->id; + $attendance->date = $attedanceDate; + $attendance->clock_in = $clockInTime; + $attendance->clock_out = $clockOutTime; + $attendance->created_by = creatorId(); + $attendance->save(); + + $attendance->fresh(); // Reload to get relationships + $attendance->processAttendance(); + + // Mark DB entries as synced + \App\Models\BiometricAttendance::where('biometric_emp_id', $biometricEmpId) + ->whereDate('punch_time', $attedanceDate) + ->update(['sync_status' => 'synced']); + + return redirect()->back()->with('success', __('Biometric data synced successfully.')); } } else { - return redirect()->back()->with('error', __('Permission Denied.')); + return redirect()->back()->with('error', __('Employee not found')); } } diff --git a/app/Models/BiometricAttendance.php b/app/Models/BiometricAttendance.php new file mode 100644 index 000000000..90940ae77 --- /dev/null +++ b/app/Models/BiometricAttendance.php @@ -0,0 +1,30 @@ + 'datetime', + 'punch_type' => 'integer', + ]; + + public function branch() + { + return $this->belongsTo(Branch::class); + } +} diff --git a/bootstrap/cache/.gitignore b/bootstrap/cache/.gitignore old mode 100755 new mode 100644 diff --git a/database/migrations/2026_05_19_090919_create_biometric_attendances_table.php b/database/migrations/2026_05_19_090919_create_biometric_attendances_table.php new file mode 100644 index 000000000..04f8bb91f --- /dev/null +++ b/database/migrations/2026_05_19_090919_create_biometric_attendances_table.php @@ -0,0 +1,38 @@ +id(); + $table->foreignId('branch_id')->nullable()->constrained()->onDelete('cascade'); + $table->string('biometric_emp_id'); + $table->dateTime('punch_time'); + $table->integer('punch_type')->default(0); // 0 = Clock In, 1 = Clock Out, etc + $table->string('terminal_alias')->nullable(); + $table->enum('sync_status', ['pending', 'synced', 'ignored'])->default('pending'); + $table->timestamps(); + + // Indexes for fast querying + $table->index(['biometric_emp_id', 'punch_time']); + $table->index('branch_id'); + $table->index('sync_status'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('biometric_attendances'); + } +}; diff --git a/docs/PLAN-biometric-db-rebuild.md b/docs/PLAN-biometric-db-rebuild.md new file mode 100644 index 000000000..5dac9b432 --- /dev/null +++ b/docs/PLAN-biometric-db-rebuild.md @@ -0,0 +1,42 @@ +# Biometric Attendance System Database Rebuild + +**Context Check**: The current `/hr/biometric-attendance` dashboard relies on directly querying ZKTeco hardware IPs (which causes extreme lag if offline) and reading from a flat JSON cache file for Windows Agent syncs. The user requested rebuilding this page so that data from the `exe sync` reliably appears, implying the current JSON-based pipeline is either failing to load, too slow, or brittle. + +## Socratic Gate / Open Questions + +> [!WARNING] +> Before we write any code, we need to clarify a few architectural decisions. + +1. **Hardware Polling Deprecation**: Are we completely moving away from the server directly querying ZKTeco IP addresses (which causes slow page loads), relying 100% on the Windows Agent pushing data to the API? +2. **Data Retention**: If the Windows Agent pushes punches every minute, the table will grow rapidly. Do you want a scheduled task to automatically clear `biometric_attendances` logs older than 30 or 60 days to keep the database light? +3. **Auto-Sync vs Manual**: Currently, HR has to click "Sync" to convert biometric logs into actual attendance records. Do you eventually want this process to be fully automated when the exe agent pushes the data? + +## Implementation Plan + +### Phase 1: Database Architecture +- Create migration `create_biometric_attendances_table` + - Columns: `id`, `branch_id`, `biometric_emp_id`, `punch_time` (datetime), `punch_type` (integer), `terminal_alias` (string), `sync_status` (enum: pending, synced, error) +- Create `BiometricAttendance` Eloquent Model. + +### Phase 2: API Ingestion Update +- Refactor `Api\AttendanceSyncController@sync`: + - Completely replace the JSON cache writing logic. + - Insert incoming agent payloads directly into the `biometric_attendances` table. + - Use `updateOrCreate` or `insertOrIgnore` using `biometric_emp_id` + `punch_time` to prevent duplicate punch entries when the agent re-sends logs. + +### Phase 3: Dashboard Controller Refactor +- Refactor `BiometricAttendanceController@index`: + - Remove all synchronous ZKTeco IP connection attempts (to fix the page loading delay). + - Query the `BiometricAttendance` database table directly. + - Implement native Laravel pagination and date filtering using Eloquent instead of Collection array sorting. + - Re-map the output to perfectly match the existing frontend structure so the React UI doesn't break. + +### Phase 4: Sync Action Refactor +- Refactor `BiometricAttendanceController@sync` and `syncAll`: + - Update the logic to update the `sync_status` column in the database from `pending` to `synced` once successfully converted to an `AttendanceRecord`. + +## Verification Plan +1. Send a mock payload via Postman to `api/zkteco/sync`. +2. Verify it appears instantly in the `biometric_attendances` table. +3. Load `/hr/biometric-attendance` and ensure the dashboard is lightning fast and displays the mock data accurately. +4. Click "Sync" on the UI and ensure it writes to the actual `attendance_records` table and disappears/marks as synced on the biometric dashboard. diff --git a/public/.DS_Store b/public/.DS_Store index 0c7aec247..bf242b320 100755 Binary files a/public/.DS_Store and b/public/.DS_Store differ diff --git a/storage/logs/laravel.log b/storage/logs/laravel.log index 7465f3cc0..e543bd11e 100755 --- a/storage/logs/laravel.log +++ b/storage/logs/laravel.log @@ -6133,3 +6133,279 @@ Error: proc_open(/dev/tty): Failed to open stream: Device not configured at /Use #19 /Users/dvapp/Documents/HRM/artisan(16): Illuminate\\Foundation\\Application->handleCommand(Object(Symfony\\Component\\Console\\Input\\ArgvInput)) #20 {main} "} +[2026-05-19 08:55:07] local.ERROR: Call to undefined relationship [branch] on model [App\Models\User]. {"userId":1,"exception":"[object] (Illuminate\\Database\\Eloquent\\RelationNotFoundException(code: 0): Call to undefined relationship [branch] on model [App\\Models\\User]. at /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/RelationNotFoundException.php:35) +[stacktrace] +#0 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(939): Illuminate\\Database\\Eloquent\\RelationNotFoundException::make(Object(App\\Models\\User), 'branch') +#1 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php(119): Illuminate\\Database\\Eloquent\\Builder->{closure:Illuminate\\Database\\Eloquent\\Builder::getRelation():935}() +#2 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(935): Illuminate\\Database\\Eloquent\\Relations\\Relation::noConstraints(Object(Closure)) +#3 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(909): Illuminate\\Database\\Eloquent\\Builder->getRelation('branch') +#4 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(889): Illuminate\\Database\\Eloquent\\Builder->eagerLoadRelation(Array, 'branch', Object(Closure)) +#5 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(855): Illuminate\\Database\\Eloquent\\Builder->eagerLoadRelations(Array) +#6 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php(212): Illuminate\\Database\\Eloquent\\Builder->get(Array) +#7 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php(175): Illuminate\\Database\\Eloquent\\Relations\\Relation->get() +#8 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(920): Illuminate\\Database\\Eloquent\\Relations\\Relation->getEager() +#9 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(889): Illuminate\\Database\\Eloquent\\Builder->eagerLoadRelation(Array, 'employee', Object(Closure)) +#10 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(855): Illuminate\\Database\\Eloquent\\Builder->eagerLoadRelations(Array) +#11 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(1095): Illuminate\\Database\\Eloquent\\Builder->get(Array) +#12 /Users/dvapp/Documents/HRM/app/Http/Controllers/AttendanceRecordController.php(93): Illuminate\\Database\\Eloquent\\Builder->paginate(9) +#13 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(46): App\\Http\\Controllers\\AttendanceRecordController->index(Object(Illuminate\\Http\\Request)) +#14 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Route.php(265): Illuminate\\Routing\\ControllerDispatcher->dispatch(Object(Illuminate\\Routing\\Route), Object(App\\Http\\Controllers\\AttendanceRecordController), 'index') +#15 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Route.php(211): Illuminate\\Routing\\Route->runController() +#16 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Router.php(808): Illuminate\\Routing\\Route->run() +#17 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(169): Illuminate\\Routing\\Router->{closure:Illuminate\\Routing\\Router::runRouteWithinStack():807}(Object(Illuminate\\Http\\Request)) +#18 /Users/dvapp/Documents/HRM/vendor/spatie/laravel-permission/src/Middleware/PermissionMiddleware.php(37): Illuminate\\Pipeline\\Pipeline->{closure:Illuminate\\Pipeline\\Pipeline::prepareDestination():167}(Object(Illuminate\\Http\\Request)) +#19 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Spatie\\Permission\\Middleware\\PermissionMiddleware->handle(Object(Illuminate\\Http\\Request), Object(Closure), 'manage-attendan...') +#20 /Users/dvapp/Documents/HRM/app/Http/Middleware/CheckPlanAccess.php(58): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#21 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\CheckPlanAccess->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#22 /Users/dvapp/Documents/HRM/app/Http/Middleware/SettingMiddleware.php(20): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#23 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\SettingMiddleware->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#24 /Users/dvapp/Documents/HRM/app/Http/Middleware/EnsureEmailIsVerified.php(22): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#25 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\EnsureEmailIsVerified->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#26 /Users/dvapp/Documents/HRM/vendor/barryvdh/laravel-debugbar/src/Middleware/InjectDebugbar.php(66): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#27 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Barryvdh\\Debugbar\\Middleware\\InjectDebugbar->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#28 /Users/dvapp/Documents/HRM/app/Http/Middleware/DemoModeMiddleware.php(17): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#29 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\DemoModeMiddleware->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#30 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Http/Middleware/AddLinkHeadersForPreloadedAssets.php(32): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#31 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Http\\Middleware\\AddLinkHeadersForPreloadedAssets->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#32 /Users/dvapp/Documents/HRM/vendor/inertiajs/inertia-laravel/src/Middleware.php(100): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#33 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Inertia\\Middleware->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#34 /Users/dvapp/Documents/HRM/app/Http/Middleware/ShareGlobalSettings.php(28): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#35 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\ShareGlobalSettings->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#36 /Users/dvapp/Documents/HRM/app/Http/Middleware/HandleAppearance.php(21): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#37 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\HandleAppearance->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#38 /Users/dvapp/Documents/HRM/app/Http/Middleware/CheckInstallation.php(30): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#39 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\CheckInstallation->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#40 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(50): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#41 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Routing\\Middleware\\SubstituteBindings->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#42 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php(63): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#43 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Auth\\Middleware\\Authenticate->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#44 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(87): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#45 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#46 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(48): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#47 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\View\\Middleware\\ShareErrorsFromSession->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#48 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(120): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#49 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(63): Illuminate\\Session\\Middleware\\StartSession->handleStatefulRequest(Object(Illuminate\\Http\\Request), Object(Illuminate\\Session\\Store), Object(Closure)) +#50 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Session\\Middleware\\StartSession->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#51 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(36): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#52 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#53 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(74): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#54 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#55 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(126): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#56 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Router.php(807): Illuminate\\Pipeline\\Pipeline->then(Object(Closure)) +#57 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Router.php(786): Illuminate\\Routing\\Router->runRouteWithinStack(Object(Illuminate\\Routing\\Route), Object(Illuminate\\Http\\Request)) +#58 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Router.php(750): Illuminate\\Routing\\Router->runRoute(Object(Illuminate\\Http\\Request), Object(Illuminate\\Routing\\Route)) +#59 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Router.php(739): Illuminate\\Routing\\Router->dispatchToRoute(Object(Illuminate\\Http\\Request)) +#60 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(200): Illuminate\\Routing\\Router->dispatch(Object(Illuminate\\Http\\Request)) +#61 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(169): Illuminate\\Foundation\\Http\\Kernel->{closure:Illuminate\\Foundation\\Http\\Kernel::dispatchToRouter():197}(Object(Illuminate\\Http\\Request)) +#62 /Users/dvapp/Documents/HRM/vendor/barryvdh/laravel-debugbar/src/Middleware/InjectDebugbar.php(66): Illuminate\\Pipeline\\Pipeline->{closure:Illuminate\\Pipeline\\Pipeline::prepareDestination():167}(Object(Illuminate\\Http\\Request)) +#63 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Barryvdh\\Debugbar\\Middleware\\InjectDebugbar->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#64 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#65 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php(31): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#66 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#67 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#68 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(51): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#69 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#70 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#71 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Http\\Middleware\\ValidatePostSize->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#72 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(109): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#73 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#74 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Http/Middleware/HandleCors.php(48): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#75 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Http\\Middleware\\HandleCors->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#76 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(58): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#77 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Http\\Middleware\\TrustProxies->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#78 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/InvokeDeferredCallbacks.php(22): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#79 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Foundation\\Http\\Middleware\\InvokeDeferredCallbacks->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#80 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePathEncoding.php(26): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#81 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Http\\Middleware\\ValidatePathEncoding->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#82 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(126): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#83 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(175): Illuminate\\Pipeline\\Pipeline->then(Object(Closure)) +#84 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(144): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter(Object(Illuminate\\Http\\Request)) +#85 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(1219): Illuminate\\Foundation\\Http\\Kernel->handle(Object(Illuminate\\Http\\Request)) +#86 /Users/dvapp/Documents/HRM/public/index.php(20): Illuminate\\Foundation\\Application->handleRequest(Object(Illuminate\\Http\\Request)) +#87 /Applications/Herd.app/Contents/Resources/valet/server.php(167): require('/Users/dvapp/Do...') +#88 {main} +"} +[2026-05-19 08:56:12] local.ERROR: Call to undefined relationship [branch] on model [App\Models\User]. {"userId":1,"exception":"[object] (Illuminate\\Database\\Eloquent\\RelationNotFoundException(code: 0): Call to undefined relationship [branch] on model [App\\Models\\User]. at /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/RelationNotFoundException.php:35) +[stacktrace] +#0 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(939): Illuminate\\Database\\Eloquent\\RelationNotFoundException::make(Object(App\\Models\\User), 'branch') +#1 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php(119): Illuminate\\Database\\Eloquent\\Builder->{closure:Illuminate\\Database\\Eloquent\\Builder::getRelation():935}() +#2 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(935): Illuminate\\Database\\Eloquent\\Relations\\Relation::noConstraints(Object(Closure)) +#3 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(909): Illuminate\\Database\\Eloquent\\Builder->getRelation('branch') +#4 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(889): Illuminate\\Database\\Eloquent\\Builder->eagerLoadRelation(Array, 'branch', Object(Closure)) +#5 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(855): Illuminate\\Database\\Eloquent\\Builder->eagerLoadRelations(Array) +#6 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php(212): Illuminate\\Database\\Eloquent\\Builder->get(Array) +#7 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php(175): Illuminate\\Database\\Eloquent\\Relations\\Relation->get() +#8 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(920): Illuminate\\Database\\Eloquent\\Relations\\Relation->getEager() +#9 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(889): Illuminate\\Database\\Eloquent\\Builder->eagerLoadRelation(Array, 'employee', Object(Closure)) +#10 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(855): Illuminate\\Database\\Eloquent\\Builder->eagerLoadRelations(Array) +#11 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(1095): Illuminate\\Database\\Eloquent\\Builder->get(Array) +#12 /Users/dvapp/Documents/HRM/app/Http/Controllers/AttendanceRecordController.php(93): Illuminate\\Database\\Eloquent\\Builder->paginate(9) +#13 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(46): App\\Http\\Controllers\\AttendanceRecordController->index(Object(Illuminate\\Http\\Request)) +#14 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Route.php(265): Illuminate\\Routing\\ControllerDispatcher->dispatch(Object(Illuminate\\Routing\\Route), Object(App\\Http\\Controllers\\AttendanceRecordController), 'index') +#15 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Route.php(211): Illuminate\\Routing\\Route->runController() +#16 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Router.php(808): Illuminate\\Routing\\Route->run() +#17 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(169): Illuminate\\Routing\\Router->{closure:Illuminate\\Routing\\Router::runRouteWithinStack():807}(Object(Illuminate\\Http\\Request)) +#18 /Users/dvapp/Documents/HRM/vendor/spatie/laravel-permission/src/Middleware/PermissionMiddleware.php(37): Illuminate\\Pipeline\\Pipeline->{closure:Illuminate\\Pipeline\\Pipeline::prepareDestination():167}(Object(Illuminate\\Http\\Request)) +#19 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Spatie\\Permission\\Middleware\\PermissionMiddleware->handle(Object(Illuminate\\Http\\Request), Object(Closure), 'manage-attendan...') +#20 /Users/dvapp/Documents/HRM/app/Http/Middleware/CheckPlanAccess.php(58): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#21 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\CheckPlanAccess->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#22 /Users/dvapp/Documents/HRM/app/Http/Middleware/SettingMiddleware.php(20): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#23 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\SettingMiddleware->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#24 /Users/dvapp/Documents/HRM/app/Http/Middleware/EnsureEmailIsVerified.php(22): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#25 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\EnsureEmailIsVerified->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#26 /Users/dvapp/Documents/HRM/vendor/barryvdh/laravel-debugbar/src/Middleware/InjectDebugbar.php(66): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#27 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Barryvdh\\Debugbar\\Middleware\\InjectDebugbar->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#28 /Users/dvapp/Documents/HRM/app/Http/Middleware/DemoModeMiddleware.php(17): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#29 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\DemoModeMiddleware->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#30 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Http/Middleware/AddLinkHeadersForPreloadedAssets.php(32): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#31 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Http\\Middleware\\AddLinkHeadersForPreloadedAssets->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#32 /Users/dvapp/Documents/HRM/vendor/inertiajs/inertia-laravel/src/Middleware.php(100): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#33 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Inertia\\Middleware->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#34 /Users/dvapp/Documents/HRM/app/Http/Middleware/ShareGlobalSettings.php(28): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#35 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\ShareGlobalSettings->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#36 /Users/dvapp/Documents/HRM/app/Http/Middleware/HandleAppearance.php(21): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#37 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\HandleAppearance->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#38 /Users/dvapp/Documents/HRM/app/Http/Middleware/CheckInstallation.php(30): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#39 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\CheckInstallation->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#40 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(50): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#41 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Routing\\Middleware\\SubstituteBindings->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#42 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php(63): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#43 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Auth\\Middleware\\Authenticate->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#44 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(87): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#45 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#46 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(48): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#47 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\View\\Middleware\\ShareErrorsFromSession->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#48 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(120): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#49 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(63): Illuminate\\Session\\Middleware\\StartSession->handleStatefulRequest(Object(Illuminate\\Http\\Request), Object(Illuminate\\Session\\Store), Object(Closure)) +#50 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Session\\Middleware\\StartSession->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#51 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(36): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#52 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#53 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(74): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#54 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#55 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(126): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#56 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Router.php(807): Illuminate\\Pipeline\\Pipeline->then(Object(Closure)) +#57 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Router.php(786): Illuminate\\Routing\\Router->runRouteWithinStack(Object(Illuminate\\Routing\\Route), Object(Illuminate\\Http\\Request)) +#58 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Router.php(750): Illuminate\\Routing\\Router->runRoute(Object(Illuminate\\Http\\Request), Object(Illuminate\\Routing\\Route)) +#59 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Router.php(739): Illuminate\\Routing\\Router->dispatchToRoute(Object(Illuminate\\Http\\Request)) +#60 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(200): Illuminate\\Routing\\Router->dispatch(Object(Illuminate\\Http\\Request)) +#61 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(169): Illuminate\\Foundation\\Http\\Kernel->{closure:Illuminate\\Foundation\\Http\\Kernel::dispatchToRouter():197}(Object(Illuminate\\Http\\Request)) +#62 /Users/dvapp/Documents/HRM/vendor/barryvdh/laravel-debugbar/src/Middleware/InjectDebugbar.php(66): Illuminate\\Pipeline\\Pipeline->{closure:Illuminate\\Pipeline\\Pipeline::prepareDestination():167}(Object(Illuminate\\Http\\Request)) +#63 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Barryvdh\\Debugbar\\Middleware\\InjectDebugbar->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#64 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#65 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php(31): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#66 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#67 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#68 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(51): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#69 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#70 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#71 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Http\\Middleware\\ValidatePostSize->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#72 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(109): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#73 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#74 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Http/Middleware/HandleCors.php(48): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#75 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Http\\Middleware\\HandleCors->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#76 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(58): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#77 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Http\\Middleware\\TrustProxies->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#78 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/InvokeDeferredCallbacks.php(22): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#79 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Foundation\\Http\\Middleware\\InvokeDeferredCallbacks->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#80 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePathEncoding.php(26): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#81 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Http\\Middleware\\ValidatePathEncoding->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#82 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(126): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#83 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(175): Illuminate\\Pipeline\\Pipeline->then(Object(Closure)) +#84 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(144): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter(Object(Illuminate\\Http\\Request)) +#85 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(1219): Illuminate\\Foundation\\Http\\Kernel->handle(Object(Illuminate\\Http\\Request)) +#86 /Users/dvapp/Documents/HRM/public/index.php(20): Illuminate\\Foundation\\Application->handleRequest(Object(Illuminate\\Http\\Request)) +#87 /Applications/Herd.app/Contents/Resources/valet/server.php(167): require('/Users/dvapp/Do...') +#88 {main} +"} +[2026-05-19 08:56:33] local.ERROR: Call to undefined relationship [branch] on model [App\Models\User]. {"userId":1,"exception":"[object] (Illuminate\\Database\\Eloquent\\RelationNotFoundException(code: 0): Call to undefined relationship [branch] on model [App\\Models\\User]. at /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/RelationNotFoundException.php:35) +[stacktrace] +#0 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(939): Illuminate\\Database\\Eloquent\\RelationNotFoundException::make(Object(App\\Models\\User), 'branch') +#1 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php(119): Illuminate\\Database\\Eloquent\\Builder->{closure:Illuminate\\Database\\Eloquent\\Builder::getRelation():935}() +#2 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(935): Illuminate\\Database\\Eloquent\\Relations\\Relation::noConstraints(Object(Closure)) +#3 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(909): Illuminate\\Database\\Eloquent\\Builder->getRelation('branch') +#4 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(889): Illuminate\\Database\\Eloquent\\Builder->eagerLoadRelation(Array, 'branch', Object(Closure)) +#5 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(855): Illuminate\\Database\\Eloquent\\Builder->eagerLoadRelations(Array) +#6 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php(212): Illuminate\\Database\\Eloquent\\Builder->get(Array) +#7 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/Relation.php(175): Illuminate\\Database\\Eloquent\\Relations\\Relation->get() +#8 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(920): Illuminate\\Database\\Eloquent\\Relations\\Relation->getEager() +#9 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(889): Illuminate\\Database\\Eloquent\\Builder->eagerLoadRelation(Array, 'employee', Object(Closure)) +#10 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(855): Illuminate\\Database\\Eloquent\\Builder->eagerLoadRelations(Array) +#11 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(1095): Illuminate\\Database\\Eloquent\\Builder->get(Array) +#12 /Users/dvapp/Documents/HRM/app/Http/Controllers/AttendanceRecordController.php(93): Illuminate\\Database\\Eloquent\\Builder->paginate(9) +#13 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(46): App\\Http\\Controllers\\AttendanceRecordController->index(Object(Illuminate\\Http\\Request)) +#14 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Route.php(265): Illuminate\\Routing\\ControllerDispatcher->dispatch(Object(Illuminate\\Routing\\Route), Object(App\\Http\\Controllers\\AttendanceRecordController), 'index') +#15 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Route.php(211): Illuminate\\Routing\\Route->runController() +#16 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Router.php(808): Illuminate\\Routing\\Route->run() +#17 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(169): Illuminate\\Routing\\Router->{closure:Illuminate\\Routing\\Router::runRouteWithinStack():807}(Object(Illuminate\\Http\\Request)) +#18 /Users/dvapp/Documents/HRM/vendor/spatie/laravel-permission/src/Middleware/PermissionMiddleware.php(37): Illuminate\\Pipeline\\Pipeline->{closure:Illuminate\\Pipeline\\Pipeline::prepareDestination():167}(Object(Illuminate\\Http\\Request)) +#19 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Spatie\\Permission\\Middleware\\PermissionMiddleware->handle(Object(Illuminate\\Http\\Request), Object(Closure), 'manage-attendan...') +#20 /Users/dvapp/Documents/HRM/app/Http/Middleware/CheckPlanAccess.php(58): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#21 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\CheckPlanAccess->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#22 /Users/dvapp/Documents/HRM/app/Http/Middleware/SettingMiddleware.php(20): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#23 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\SettingMiddleware->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#24 /Users/dvapp/Documents/HRM/app/Http/Middleware/EnsureEmailIsVerified.php(22): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#25 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\EnsureEmailIsVerified->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#26 /Users/dvapp/Documents/HRM/vendor/barryvdh/laravel-debugbar/src/Middleware/InjectDebugbar.php(66): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#27 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Barryvdh\\Debugbar\\Middleware\\InjectDebugbar->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#28 /Users/dvapp/Documents/HRM/app/Http/Middleware/DemoModeMiddleware.php(17): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#29 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\DemoModeMiddleware->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#30 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Http/Middleware/AddLinkHeadersForPreloadedAssets.php(32): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#31 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Http\\Middleware\\AddLinkHeadersForPreloadedAssets->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#32 /Users/dvapp/Documents/HRM/vendor/inertiajs/inertia-laravel/src/Middleware.php(100): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#33 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Inertia\\Middleware->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#34 /Users/dvapp/Documents/HRM/app/Http/Middleware/ShareGlobalSettings.php(28): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#35 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\ShareGlobalSettings->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#36 /Users/dvapp/Documents/HRM/app/Http/Middleware/HandleAppearance.php(21): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#37 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\HandleAppearance->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#38 /Users/dvapp/Documents/HRM/app/Http/Middleware/CheckInstallation.php(30): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#39 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): App\\Http\\Middleware\\CheckInstallation->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#40 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(50): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#41 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Routing\\Middleware\\SubstituteBindings->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#42 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php(63): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#43 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Auth\\Middleware\\Authenticate->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#44 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(87): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#45 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#46 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(48): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#47 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\View\\Middleware\\ShareErrorsFromSession->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#48 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(120): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#49 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(63): Illuminate\\Session\\Middleware\\StartSession->handleStatefulRequest(Object(Illuminate\\Http\\Request), Object(Illuminate\\Session\\Store), Object(Closure)) +#50 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Session\\Middleware\\StartSession->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#51 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(36): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#52 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Cookie\\Middleware\\AddQueuedCookiesToResponse->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#53 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(74): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#54 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#55 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(126): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#56 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Router.php(807): Illuminate\\Pipeline\\Pipeline->then(Object(Closure)) +#57 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Router.php(786): Illuminate\\Routing\\Router->runRouteWithinStack(Object(Illuminate\\Routing\\Route), Object(Illuminate\\Http\\Request)) +#58 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Router.php(750): Illuminate\\Routing\\Router->runRoute(Object(Illuminate\\Http\\Request), Object(Illuminate\\Routing\\Route)) +#59 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Routing/Router.php(739): Illuminate\\Routing\\Router->dispatchToRoute(Object(Illuminate\\Http\\Request)) +#60 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(200): Illuminate\\Routing\\Router->dispatch(Object(Illuminate\\Http\\Request)) +#61 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(169): Illuminate\\Foundation\\Http\\Kernel->{closure:Illuminate\\Foundation\\Http\\Kernel::dispatchToRouter():197}(Object(Illuminate\\Http\\Request)) +#62 /Users/dvapp/Documents/HRM/vendor/barryvdh/laravel-debugbar/src/Middleware/InjectDebugbar.php(66): Illuminate\\Pipeline\\Pipeline->{closure:Illuminate\\Pipeline\\Pipeline::prepareDestination():167}(Object(Illuminate\\Http\\Request)) +#63 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Barryvdh\\Debugbar\\Middleware\\InjectDebugbar->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#64 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#65 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php(31): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#66 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#67 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#68 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php(51): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#69 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#70 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#71 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Http\\Middleware\\ValidatePostSize->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#72 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(109): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#73 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#74 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Http/Middleware/HandleCors.php(48): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#75 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Http\\Middleware\\HandleCors->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#76 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php(58): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#77 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Http\\Middleware\\TrustProxies->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#78 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/InvokeDeferredCallbacks.php(22): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#79 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Foundation\\Http\\Middleware\\InvokeDeferredCallbacks->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#80 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Http/Middleware/ValidatePathEncoding.php(26): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#81 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(208): Illuminate\\Http\\Middleware\\ValidatePathEncoding->handle(Object(Illuminate\\Http\\Request), Object(Closure)) +#82 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(126): Illuminate\\Pipeline\\Pipeline->{closure:{closure:Illuminate\\Pipeline\\Pipeline::carry():183}:184}(Object(Illuminate\\Http\\Request)) +#83 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(175): Illuminate\\Pipeline\\Pipeline->then(Object(Closure)) +#84 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(144): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter(Object(Illuminate\\Http\\Request)) +#85 /Users/dvapp/Documents/HRM/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(1219): Illuminate\\Foundation\\Http\\Kernel->handle(Object(Illuminate\\Http\\Request)) +#86 /Users/dvapp/Documents/HRM/public/index.php(20): Illuminate\\Foundation\\Application->handleRequest(Object(Illuminate\\Http\\Request)) +#87 /Applications/Herd.app/Contents/Resources/valet/server.php(167): require('/Users/dvapp/Do...') +#88 {main} +"}