service->getAll(); return $this->successResponse(payload: AppointmentResource::collection($items)); } public function myAppointments(): JsonResponse { $items = $this->service->getAllByUser(Auth::id()); return $this->successResponse(payload: AppointmentResource::collection($items)); } public function partnerAppointments(): JsonResponse { $items = $this->service->getAllByPartnerUser(Auth::id()); return $this->successResponse(payload: AppointmentResource::collection($items)); } public function getByUser(int $id): JsonResponse { $items = $this->service->getAllByUser($id); return $this->successResponse(payload: AppointmentResource::collection($items)); } public function store(AppointmentRequest $request): JsonResponse { $item = $this->service->createConsulta($request->validated(), Auth::user()); return $this->successResponse( payload: new AppointmentResource($item), message: __('messages.created'), code: 201, ); } public function show(int $id): JsonResponse { $item = $this->service->findById($id); return $this->successResponse(payload: new AppointmentResource($item)); } public function update(AppointmentRequest $request, int $id): JsonResponse { if ($blocked = $this->guardFrozen($id)) { return $blocked; } $item = $this->service->update($id, $request->validated(), Auth::id()); return $this->successResponse( payload: new AppointmentResource($item), message: __('messages.updated'), ); } public function destroy(int $id): JsonResponse { if ($blocked = $this->guardFrozen($id)) { return $blocked; } $this->service->delete($id); return $this->successResponse(message: __('messages.deleted'), code: 204); } private function guardFrozen(int $id): ?JsonResponse { $appointment = $this->service->findById($id); if ($appointment && $this->service->isFrozen($appointment)) { return $this->errorResponse(message: __('messages.appointment_frozen'), code: 422); } return null; } public function getAdminCounters(): JsonResponse { return $this->successResponse(payload: $this->service->getAdminCounters()); } public function getAdminAppointmentsPaginated(Request $request): JsonResponse { $filters = $request->only(['status', 'search', 'type']); $perPage = (int) $request->input('per_page', 10); $paginator = $this->service->getAllPaginated($filters, $perPage); $items = collect($paginator->items())->map(fn($a) => [ 'id' => $a->id, 'order_number' => $a->order_number, 'type' => $a->type?->value, 'registration' => $a->user?->registration, 'user_name' => $a->user?->name, 'dependent_name' => $a->userDependent?->name, 'is_for_dependent' => $a->user_dependent_id !== null, 'partner_name' => $a->partnerAgreement?->company_name, 'service_name' => $a->isExame() ? $a->exams->map(fn($e) => $e->partnerAgreementService?->name)->filter()->implode(', ') : $a->partnerAgreementService?->name, 'exams_count' => $a->exams->count(), 'requested_at' => $a->requested_at?->format('d/m/Y'), 'status' => $a->status?->value, 'refusal_reason' => $a->refusal_reason, 'can_issue_guide' => $this->guideService->canIssue($a), ]); return $this->successResponse(payload: [ 'data' => $items, 'total' => $paginator->total(), 'per_page' => $paginator->perPage(), 'current_page' => $paginator->currentPage(), 'from' => $paginator->firstItem(), 'to' => $paginator->lastItem(), ]); } public function approve(AppointmentApproveRequest $request, int $id): JsonResponse { $item = $this->service->approve($id, $request->date, $request->time, Auth::id()); return $this->successResponse(payload: new AppointmentResource($item), message: __('messages.updated')); } public function reject(int $id): JsonResponse { $item = $this->service->reject($id); return $this->successResponse(payload: new AppointmentResource($item), message: __('messages.updated')); } public function approveByPartner(AppointmentApproveRequest $request, int $id): JsonResponse { $item = $this->service->approveByPartner($id, Auth::id(), $request->date, $request->time); if (!$item) return $this->errorResponse(message: __('messages.not_found'), code: 404); return $this->successResponse(payload: new AppointmentResource($item), message: __('messages.updated')); } public function rejectByPartner(int $id): JsonResponse { $item = $this->service->rejectByPartner($id, Auth::id()); if (!$item) return $this->errorResponse(message: __('messages.not_found'), code: 404); return $this->successResponse(payload: new AppointmentResource($item), message: __('messages.updated')); } // ------------------------------------------------------------------ // Exames // ------------------------------------------------------------------ public function partnerExams(): JsonResponse { if ($blocked = $this->guardConvenioMedico()) { return $blocked; } $items = $this->service->getExamsByPartnerUser(Auth::id()); return $this->successResponse(payload: AppointmentResource::collection($items)); } public function showPartnerExam(int $id): JsonResponse { if ($blocked = $this->guardConvenioMedico()) { return $blocked; } $item = $this->service->findExamForPartnerUser($id, Auth::id()); if (!$item) { return $this->errorResponse(message: __('messages.not_found'), code: 404); } return $this->successResponse(payload: new AppointmentResource($item)); } public function partnerExamAssociados(Request $request): JsonResponse { if ($blocked = $this->guardConvenioMedico()) { return $blocked; } $perPage = min((int) $request->get('per_page', 20), 100); $paginator = $this->userService->getAssociadosForSelect($request->get('search'), $perPage); return $this->successResponse(payload: [ 'data' => collect($paginator->items())->map(fn($user) => [ 'id' => $user->id, 'name' => $user->name, 'registration' => $user->registration, ]), 'total' => $paginator->total(), 'from' => $paginator->firstItem() ?? 0, 'to' => $paginator->lastItem() ?? 0, ]); } public function partnerExamDependentes(int $userId): JsonResponse { if ($blocked = $this->guardConvenioMedico()) { return $blocked; } return $this->successResponse( payload: $this->dependentService->getApprovedByUserForSelect($userId), ); } public function storePartnerExam(AppointmentExamRequest $request): JsonResponse { if ($blocked = $this->guardConvenioMedico()) { return $blocked; } $data = $request->validated(); if ((int) $data['partner_agreement_id'] !== (int) Auth::user()->partnerAgreement?->id) { return $this->errorResponse(message: __('messages.unauthorized'), code: 403); } return $this->createExamResponse($data); } public function storeExam(AppointmentExamRequest $request): JsonResponse { return $this->createExamResponse($request->validated()); } private function createExamResponse(array $data): JsonResponse { $item = $this->service->createExam($data); return $this->successResponse( payload: new AppointmentResource($item), message: __('messages.created'), code: 201, ); } public function acceptExam(int $id): JsonResponse { $item = $this->service->acceptExam($id, Auth::id()); if (!$item) { return $this->errorResponse(message: __('messages.exam_decision_unavailable'), code: 422); } return $this->successResponse( payload: new AppointmentResource($item), message: __('messages.exam_accepted'), ); } public function refuseExam(AppointmentRefusalRequest $request, int $id): JsonResponse { $item = $this->service->refuseExam($id, Auth::id(), $request->input('refusal_reason')); if (!$item) { return $this->errorResponse(message: __('messages.exam_decision_unavailable'), code: 422); } return $this->successResponse( payload: new AppointmentResource($item), message: __('messages.exam_refused'), ); } private function guardConvenioMedico(): ?JsonResponse { if (!Auth::user()->isConvenioMedico()) { return $this->errorResponse(message: __('messages.unauthorized'), code: 403); } return null; } public function guide(int $id): Response|JsonResponse { return $this->buildGuide($this->service->findById($id)); } public function myGuide(int $id): Response|JsonResponse { $item = $this->service->findById($id); if ($item && $item->user_id !== Auth::id()) { return $this->errorResponse(message: __('messages.unauthorized'), code: 403); } return $this->buildGuide($item); } public function partnerGuide(int $id): Response|JsonResponse { $item = $this->service->findByIdForPartnerUser($id, Auth::id()); return $this->buildGuide($item); } private function buildGuide(?Appointment $appointment): Response|JsonResponse { if (!$appointment) { return $this->errorResponse(message: __('messages.not_found'), code: 404); } if (!$this->guideService->canIssue($appointment)) { return $this->errorResponse(message: __('messages.guide_unavailable'), code: 422); } return $this->guideService ->pdf($appointment, Auth::id()) ->download($this->guideService->fileName($appointment)); } }