feat: add patient appointment interface and endpoints

- Introduced `PatientAppointment` interface to define appointment structure.
- Implemented `findByUserAndDoctorIds` method in `AppointmentRepository` to retrieve appointments for a user filtered by doctor IDs.
- Added `acceptedDoctorIdsByClinic` method in `ClinicDoctorInvitationRepository` to get accepted doctor IDs for a clinic.
- Created new endpoint in `PatientController` to fetch appointments for a patient, ensuring only relevant doctors' appointments are displayed.
This commit is contained in:
hamed
2026-07-13 10:15:44 +03:30
parent 5c09fe8ac3
commit a4a17bf8c7
5 changed files with 564 additions and 370 deletions
@@ -47,6 +47,8 @@ class PatientController extends BaseController
private readonly InvoiceService $invoiceService,
private readonly ClaimService $claimService,
private readonly InvoiceRepository $invoiceRepo,
private readonly \App\Appointment\Repository\AppointmentRepository $appointmentRepo,
private readonly \App\ClinicInvitation\Repository\ClinicDoctorInvitationRepository $invitationRepo,
private readonly LoggerInterface $logger,
) {}
@@ -318,6 +320,37 @@ class PatientController extends BaseController
);
}
#[Route('/api/v1/patient/{uuid}/appointments', methods: ['GET'])]
public function appointments(string $uuid, #[CurrentUser] User $user): JsonResponse
{
[$entityType, $entityId] = $this->resolveEntity($user);
$this->assertPatientGate($entityType, $entityId);
$record = $this->recordRepo->findByUuid($uuid);
if ($record === null || !$this->ownsRecord($record, $entityType, $entityId)) {
return $this->error(ErrorCodes::ERR_PATIENT_NOT_FOUND, ErrorCodes::message(ErrorCodes::ERR_PATIENT_NOT_FOUND), 404);
}
// نوبت‌های این بیمار فقط با پزشک(های) همین ارائه‌دهنده نمایش داده می‌شوند تا
// نوبت‌های او با کلینیک‌های دیگر نشت نکند.
$doctorIds = $entityType === 'doctor'
? [$entityId]
: $this->invitationRepo->acceptedDoctorIdsByClinic($entityId);
$appointments = $this->appointmentRepo->findByUserAndDoctorIds($record->getUser(), $doctorIds);
return $this->success(array_map(fn(\App\Appointment\Entity\Appointment $a) => [
'uuid' => $a->getUuid(),
'starts_at' => $a->getSlotStart(),
'ends_at' => $a->getSlotEnd(),
'status' => $a->getStatus(),
'doctor_name' => $a->getDoctor()->getName(),
'service_name' => null,
'price_rials' => null,
'created_at' => $a->getSlotStart(),
], $appointments));
}
/**
* خروجی session به‌همراه خلاصه‌ی صورتحساب: uuid فاکتور (در صورت وجود) و
* مانده‌ی بدهیِ سهم بیمار. اگر session تسویه شده باشد (payment_method != pending)