attendance calendar fix

This commit is contained in:
2026-04-20 09:14:47 +08:00
parent 5ead32031d
commit 4135d14b96
494 changed files with 16547 additions and 15531 deletions

View File

@@ -200,4 +200,117 @@ class ShiftController extends Controller
return redirect()->back()->with('error', __('Shift Not Found.'));
}
}
public function calendar(Request $request)
{
if (Auth::user()->can('manage-shifts')) {
$month = $request->input('month', date('n'));
$year = $request->input('year', date('Y'));
$department_id = $request->input('department_id');
$search = $request->input('search');
$startDate = \Carbon\Carbon::createFromDate($year, $month, 1)->startOfMonth();
$endDate = \Carbon\Carbon::createFromDate($year, $month, 1)->endOfMonth();
// Setup dates header correctly (1 -> 31)
$dates = [];
for ($date = $startDate->copy(); $date->lte($endDate); $date->addDay()) {
$dates[] = [
'date' => $date->format('Y-m-d'),
'day' => $date->format('d'),
'day_name' => $date->format('D'),
];
}
$query = \App\Models\User::with(['employee.department', 'employee.shift'])
->whereHas('employee', function($q) {
$q->where('employee_status', 'active');
});
if ($department_id) {
$query->whereHas('employee', function($q) use ($department_id) {
$q->where('department_id', $department_id);
});
}
if ($search) {
$query->where('name', 'like', "%{$search}%");
}
$usersRaw = $query->get();
// Fetch daily shifts and REST DAY overrides dynamically directly from the Attendance engine records!
$dailyShifts = \Illuminate\Support\Facades\DB::table('attendance_records')
->leftJoin('shifts', 'attendance_records.shift_id', '=', 'shifts.id')
->whereBetween('attendance_records.date', [$startDate->format('Y-m-d'), $endDate->format('Y-m-d')])
->select(
'attendance_records.employee_id as user_id',
'attendance_records.date',
'attendance_records.is_rest_day',
'shifts.name as shift_name'
)
->get()
->groupBy('user_id');
$users = $usersRaw->map(function($user) use ($dates, $dailyShifts) {
$grid = [];
$userShifts = $dailyShifts->has($user->id) ? $dailyShifts[$user->id]->keyBy('date') : collect();
foreach ($dates as $d) {
$dateKey = $d['date'];
// Default to Rest Day as per user's Socratic resolution
$status = 'RD';
$shiftName = 'Rest Day';
if ($userShifts->has($dateKey)) {
$record = $userShifts[$dateKey];
// If attendance record specifically marks it as a globally tracked Rest Day
if ($record->is_rest_day) {
$status = 'RD';
} else if ($record->shift_name) {
// Extract shift safely
$status = strtoupper(substr($record->shift_name, 0, 1));
} else if ($user->employee && $user->employee->shift) {
// Record exists, but shift mapping is blank. Fallback to employee profile shift.
$status = strtoupper(substr($user->employee->shift->name, 0, 1));
}
} else if ($user->employee && $user->employee->shift) {
// Completely blank record; safely map to their default assigned Employee Shift!
// Removed hardcoded Sat/Sun filters because `attendance_records` strictly dictates actual weekend behavior now!
$status = strtoupper(substr($user->employee->shift->name, 0, 1));
}
$grid[$dateKey] = [
'status' => $status,
'shift_name' => $shiftName
];
}
return [
'id' => $user->id,
'name' => $user->name,
'employee_code' => $user->employee ? $user->employee->employee_id : '',
'designation' => ($user->employee && $user->employee->designation) ? $user->employee->designation->name : '',
'department' => ($user->employee && $user->employee->department) ? $user->employee->department->name : '',
'shifts' => $grid
];
});
$departments = \App\Models\Department::select('id', 'name')->get();
return Inertia::render('hr/shifts/calendar', [
'users' => $users,
'dates' => $dates,
'departments' => $departments,
'filters' => [
'month' => $month,
'year' => $year,
'department_id' => $department_id,
'search' => $search
]
]);
}
return redirect()->back()->with('error', __('Permission Denied.'));
}
}