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

182 lines
6.1 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\LeaveApplication;
use App\Models\User;
use App\Services\EmployeeService;
use App\Services\LeaveService;
use Illuminate\Http\Request;
use Exception;
class LeaveApiController extends Controller
{
protected EmployeeService $employeeService;
protected LeaveService $leaveService;
public function __construct(EmployeeService $employeeService, LeaveService $leaveService)
{
$this->employeeService = $employeeService;
$this->leaveService = $leaveService;
}
public function balances(Request $request)
{
try {
$employee = $this->employeeService->resolveEmployee($request->user());
} catch (Exception $e) {
return response()->json([
'success' => false,
'data' => [],
'message' => 'Employee profile not found',
'errors' => null,
], 403);
}
$balances = $this->leaveService->getBalances($employee);
return response()->json([
'success' => true,
'data' => $balances,
'message' => null,
'errors' => null,
]);
}
public function applications(Request $request)
{
try {
$employee = $this->employeeService->resolveEmployee($request->user());
} catch (Exception $e) {
return response()->json([
'success' => false,
'data' => [],
'message' => 'Employee profile not found',
'errors' => null,
], 403);
}
$applications = LeaveApplication::where('employee_id', $request->user()->id)
->orderBy('created_at', 'desc')
->get();
return response()->json([
'success' => true,
'data' => $applications,
'message' => null,
'errors' => null,
]);
}
public function apply(Request $request)
{
$request->validate([
'leave_type' => 'nullable|string',
'leave_type_id' => 'nullable|integer',
'start_date' => 'required|date',
'end_date' => 'required|date|after_or_equal:start_date',
'reason' => 'required|string',
]);
try {
$employee = $this->employeeService->resolveEmployee($request->user());
} catch (Exception $e) {
return response()->json([
'success' => false,
'data' => null,
'message' => 'Employee profile not found',
'errors' => null,
], 403);
}
$application = $this->leaveService->submitApplication($request->user(), $employee, $request->all());
return response()->json([
'success' => true,
'message' => 'Leave application submitted successfully',
'data' => $application,
'errors' => null,
], 201);
}
public function updateStatus(Request $request, $id)
{
$request->validate([
'status' => 'required|string|in:approved,rejected,cancelled,pending',
]);
$user = $request->user();
$application = LeaveApplication::find($id);
if (!$application) {
return response()->json([
'success' => false,
'data' => null,
'message' => 'Leave application not found',
'errors' => null,
], 404);
}
$employee = $this->employeeService->resolveEmployee($user);
// Scoping & authorization checks
if ($request->status === 'cancelled') {
$isOwner = in_array($application->employee_id, [$employee->id, $user->id]) || $application->created_by === $user->id;
if (!$isOwner && !in_array($user->type, ['company', 'hr', 'superadmin', 'manager'])) {
return response()->json([
'success' => false,
'data' => null,
'message' => 'Unauthorized to cancel this leave application',
'errors' => null,
], 403);
}
} else {
// Approval or Rejection requires manager / HR role within same company tenant
$userType = strtolower($user->type ?? '');
$isElevatedRole = in_array($userType, ['company', 'hr', 'superadmin', 'manager']);
if (!$isElevatedRole) {
try {
$isElevatedRole = $user->hasAnyRole(['company', 'hr', 'superadmin', 'manager']);
} catch (\Throwable $e) {
$isElevatedRole = false;
}
}
$empUser = User::find($application->employee_id)
?? Employee::find($application->employee_id)?->user
?? User::find($application->created_by);
$appCompanyId = $empUser ? ($empUser->type === 'company' ? $empUser->id : ($empUser->created_by ?: $empUser->id)) : null;
$approverCompanyId = $user->type === 'company' ? $user->id : ($user->created_by ?: $user->id);
$isSuperAdmin = in_array($userType, ['superadmin']);
$isSameCompany = ($appCompanyId !== null && $approverCompanyId !== null && (int)$appCompanyId === (int)$approverCompanyId);
if (!$isElevatedRole || (!$isSameCompany && !$isSuperAdmin)) {
return response()->json([
'success' => false,
'data' => null,
'message' => 'Unauthorized to review this leave application. Approval requires authorized manager or HR within the same organization.',
'errors' => null,
], 403);
}
}
$application->update(['status' => $request->status]);
return response()->json([
'success' => true,
'message' => 'Leave application status updated to ' . $request->status,
'data' => $application,
'errors' => null,
]);
}
public function cancel(Request $request, $id)
{
return $this->updateStatus($request->merge(['status' => 'cancelled']), $id);
}
}