get('per_page', 15); $filters = [ 'search' => $request->get('search'), 'active' => $request->get('active'), 'sort_by' => $request->get('sort_by', 'last_name'), 'sort_direction' => $request->get('sort_direction', 'asc'), ]; // Remove null filters $filters = array_filter($filters, function ($value) { return $value !== null && $value !== ''; }); $result = $this->employeeRepository->getPaginated($perPage, $filters); return response()->json([ 'data' => new EmployeeCollection($result['employees']), 'pagination' => $result['pagination'], 'message' => 'Employés récupérés avec succès.', ], 200); } catch (\Exception $e) { Log::error('Error fetching employees: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la récupération des employés.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Display paginated employees. */ public function paginated(Request $request): JsonResponse { try { $perPage = (int) $request->get('per_page', 15); $result = $this->employeeRepository->getPaginated($perPage, []); return response()->json([ 'data' => new EmployeeCollection($result['employees']), 'pagination' => $result['pagination'], 'message' => 'Employés récupérés avec succès.', ], 200); } catch (\Exception $e) { Log::error('Error fetching paginated employees: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la récupération des employés.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Get active employees only. */ public function active(): EmployeeCollection|JsonResponse { try { $employees = $this->employeeRepository->getActive(); return new EmployeeCollection($employees); } catch (\Exception $e) { Log::error('Error fetching active employees: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la récupération des employés actifs.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Get employees with thanatopractitioner data. */ public function withThanatopractitioner(): EmployeeCollection|JsonResponse { try { $employees = $this->employeeRepository->getWithThanatopractitioner(); return new EmployeeCollection($employees); } catch (\Exception $e) { Log::error('Error fetching employees with thanatopractitioner: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la récupération des employés avec données thanatopractitioner.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Get employee statistics. */ public function statistics(): JsonResponse { try { $statistics = $this->employeeRepository->getStatistics(); return response()->json([ 'data' => $statistics, 'message' => 'Statistiques des employés récupérées avec succès.', ], 200); } catch (\Exception $e) { Log::error('Error fetching employee statistics: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la récupération des statistiques.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Store a newly created employee. */ public function store(StoreEmployeeRequest $request): EmployeeResource|JsonResponse { try { $employee = $this->employeeRepository->create($request->validated()); return new EmployeeResource($employee); } catch (\Exception $e) { Log::error('Error creating employee: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'data' => $request->validated(), ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la création de l\'employé.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Display the specified employee. */ public function show(string $id): EmployeeResource|JsonResponse { try { $employee = $this->employeeRepository->find($id); if (!$employee) { return response()->json([ 'message' => 'Employé non trouvé.', ], 404); } return new EmployeeResource($employee); } catch (\Exception $e) { Log::error('Error fetching employee: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'employee_id' => $id, ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la récupération de l\'employé.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Get the intervention agenda for a specific employee. */ public function agenda(Request $request, string $id): JsonResponse { $validator = Validator::make($request->all(), [ 'month' => ['nullable', 'date_format:Y-m'], 'start_date' => ['nullable', 'date'], 'end_date' => ['nullable', 'date', 'after_or_equal:start_date'], 'status' => ['nullable', 'string'], 'type' => ['nullable', 'string'], ]); if ($validator->fails()) { return response()->json([ 'message' => 'Paramètres d\'agenda invalides.', 'errors' => $validator->errors(), ], 422); } try { $employee = $this->employeeRepository->find($id); if (!$employee) { return response()->json([ 'message' => 'Employé non trouvé.', ], 404); } $employee->load('thanatopractitioner'); if (!$employee->thanatopractitioner) { return response()->json([ 'message' => 'Aucun agenda disponible pour cet employé.', 'employee' => [ 'id' => $employee->id, 'full_name' => $employee->full_name, 'job_title' => $employee->job_title, ], 'filters' => [ 'month' => $request->input('month'), 'start_date' => $request->input('start_date'), 'end_date' => $request->input('end_date'), 'status' => $request->input('status'), 'type' => $request->input('type'), ], 'data' => [], 'meta' => [ 'total' => 0, 'status_summary' => [], ], ], 200); } [$startDate, $endDate] = $this->resolveAgendaPeriod( $request->input('month'), $request->input('start_date'), $request->input('end_date') ); $interventions = $employee->thanatopractitioner ->interventions() ->with([ 'client', 'deceased', 'location', 'quote', 'practitioners.employee', ]) ->when($startDate, function ($query) use ($startDate) { $query->where('scheduled_at', '>=', $startDate); }) ->when($endDate, function ($query) use ($endDate) { $query->where('scheduled_at', '<=', $endDate); }) ->when($request->filled('status'), function ($query) use ($request) { $query->where('status', $request->string('status')); }) ->when($request->filled('type'), function ($query) use ($request) { $query->where('type', $request->string('type')); }) ->orderBy('scheduled_at') ->get(); return response()->json([ 'message' => 'Agenda employé récupéré avec succès.', 'employee' => [ 'id' => $employee->id, 'full_name' => $employee->full_name, 'job_title' => $employee->job_title, 'thanatopractitioner_id' => $employee->thanatopractitioner->id, ], 'filters' => [ 'month' => $request->input('month'), 'start_date' => $startDate?->toDateTimeString(), 'end_date' => $endDate?->toDateTimeString(), 'status' => $request->input('status'), 'type' => $request->input('type'), ], 'data' => InterventionResource::collection($interventions)->resolve(), 'meta' => [ 'total' => $interventions->count(), 'status_summary' => $interventions ->groupBy('status') ->map(fn ($group) => $group->count()) ->toArray(), ], ], 200); } catch (\Exception $e) { Log::error('Error fetching employee agenda: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'employee_id' => $id, 'filters' => $request->all(), ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la récupération de l\'agenda employé.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Update the specified employee. */ public function update(UpdateEmployeeRequest $request, string $id): EmployeeResource|JsonResponse { try { $updated = $this->employeeRepository->update($id, $request->validated()); if (!$updated) { return response()->json([ 'message' => 'Employé non trouvé ou échec de la mise à jour.', ], 404); } $employee = $this->employeeRepository->find($id); return new EmployeeResource($employee); } catch (\Exception $e) { Log::error('Error updating employee: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'employee_id' => $id, 'data' => $request->validated(), ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la mise à jour de l\'employé.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Remove the specified employee. */ public function destroy(string $id): JsonResponse { try { $deleted = $this->employeeRepository->delete($id); if (!$deleted) { return response()->json([ 'message' => 'Employé non trouvé ou échec de la suppression.', ], 404); } return response()->json([ 'message' => 'Employé supprimé avec succès.', ], 200); } catch (\Exception $e) { Log::error('Error deleting employee: ' . $e->getMessage(), [ 'exception' => $e, 'trace' => $e->getTraceAsString(), 'employee_id' => $id, ]); return response()->json([ 'message' => 'Une erreur est survenue lors de la suppression de l\'employé.', 'error' => config('app.debug') ? $e->getMessage() : null, ], 500); } } /** * Resolve the requested agenda period. * * Defaults to the current month when no explicit range is provided. * * @return array{0: \Carbon\Carbon, 1: \Carbon\Carbon} */ private function resolveAgendaPeriod(?string $month, ?string $startDate, ?string $endDate): array { if ($month) { $reference = Carbon::createFromFormat('Y-m', $month)->startOfMonth(); return [$reference->copy()->startOfMonth(), $reference->copy()->endOfMonth()]; } if ($startDate || $endDate) { return [ $startDate ? Carbon::parse($startDate)->startOfDay() : Carbon::now()->startOfMonth(), $endDate ? Carbon::parse($endDate)->endOfDay() : Carbon::now()->endOfMonth(), ]; } return [Carbon::now()->startOfMonth(), Carbon::now()->endOfMonth()]; } }