Files
HRM-System/app/Http/Controllers/OvertimeApplicationController.php

178 lines
6.0 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\OvertimeApplication;
use App\Models\AttendanceRecord;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Illuminate\Support\Facades\Auth;
class OvertimeApplicationController extends Controller
{
public function getAttendanceDetails(Request $request)
{
$request->validate([
'date' => 'required|date',
'user_id' => 'nullable|exists:users,id'
]);
$userId = $request->user_id ?: Auth::id();
// If not admin/hr, cannot query other users
if ($request->user_id && $request->user_id != Auth::id()) {
if (!in_array(Auth::user()->type, ['admin', 'hr', 'company'])) {
abort(403);
}
}
$record = AttendanceRecord::with('employee.user', 'employee.shift')
->whereHas('employee', function($q) use ($userId) {
$q->where('user_id', $userId);
})
->where('date', $request->date)
->first();
if (!$record) {
return response()->json(['message' => 'No attendance record found for this date.']);
}
if (!$record->clock_in || !$record->clock_out) {
return response()->json(['message' => 'Attendance record is incomplete (missing clock in/out).']);
}
$emp = $record->employee;
$shiftStart = $record->shift_start_time ?: ($emp->shift->start_time ?? null);
$shiftEnd = $record->shift_end_time ?: ($emp->shift->end_time ?? null);
if (!$shiftStart || !$shiftEnd) {
return response()->json(['message' => 'No shift assigned for this record.']);
}
$parseTime = function($timeStr) {
if (!$timeStr) return 0;
$parts = explode(':', $timeStr);
return ($parts[0] * 60) + ($parts[1] ?? 0);
};
$outMins = $parseTime($record->clock_out);
$sStart = $parseTime($shiftStart);
$sEnd = $parseTime($shiftEnd);
// Night shift logic
if ($sEnd <= $sStart) {
$sEnd += 1440;
if ($outMins < $sStart) $outMins += 1440;
}
$overtimeMins = $outMins - $sEnd;
if ($overtimeMins >= 60) {
$otHours = round($overtimeMins / 60, 1);
return response()->json([
'has_overtime' => true,
'suggested_hours' => $otHours,
'message' => "Shift ended at {$shiftEnd}, clocked out at {$record->clock_out}. Auto-calculated: {$otHours} hours."
]);
}
return response()->json([
'has_overtime' => false,
'message' => "Shift ended at {$shiftEnd}, clocked out at {$record->clock_out}. No significant overtime detected."
]);
}
public function index()
{
$user = Auth::user();
$query = OvertimeApplication::with('user.employee');
// If not admin/hr, only show own requests
if (!in_array($user->type, ['admin', 'hr', 'company'])) {
$query->where('user_id', $user->id);
}
$applications = $query->orderBy('date', 'desc')->get();
$users = [];
if (in_array($user->type, ['admin', 'hr', 'company'])) {
$users = \App\Models\User::where('type', 'employee')->select('id', 'name')->get();
}
return Inertia::render('hr/overtime/index', [
'applications' => $applications,
'can_approve' => in_array($user->type, ['admin', 'hr', 'company']),
'users' => $users
]);
}
public function store(Request $request)
{
$request->validate([
'date' => 'required|date',
'requested_hours' => 'required|numeric|min:0.1',
'reason' => 'nullable|string',
'user_id' => 'nullable|exists:users,id'
]);
$userId = Auth::id();
// If an admin/hr specifies a user_id, use it.
if ($request->has('user_id') && $request->user_id != Auth::id()) {
if (in_array(Auth::user()->type, ['admin', 'hr', 'company'])) {
$userId = $request->user_id;
} else {
abort(403, 'Unauthorized to apply overtime for another employee.');
}
}
// Check if already requested for this date
$exists = OvertimeApplication::where('user_id', $userId)
->where('date', $request->date)
->whereIn('status', ['pending', 'approved'])
->exists();
if ($exists) {
if ($request->wantsJson()) {
return response()->json(['message' => 'You already have a pending or approved overtime request for this date.'], 422);
}
return back()->with('error', 'You already have a pending or approved overtime request for this date.');
}
OvertimeApplication::create([
'user_id' => $userId,
'date' => $request->date,
'requested_hours' => $request->requested_hours,
'reason' => $request->reason,
'status' => 'pending'
]);
if ($request->wantsJson()) {
return response()->json(['message' => 'Overtime application submitted successfully.']);
}
return back()->with('success', 'Overtime application submitted successfully.');
}
public function updateStatus(Request $request, OvertimeApplication $overtimeApplication)
{
if (!in_array(Auth::user()->type, ['admin', 'hr', 'company'])) {
abort(403);
}
$request->validate([
'status' => 'required|in:approved,rejected',
'approved_hours' => 'nullable|required_if:status,approved|numeric|min:0',
'admin_remarks' => 'nullable|string'
]);
$overtimeApplication->update([
'status' => $request->status,
'approved_hours' => $request->status === 'approved' ? $request->approved_hours : null,
'admin_remarks' => $request->admin_remarks
]);
return back()->with('success', 'Overtime application ' . $request->status . ' successfully.');
}
}