feat(representation): add representation management for doctors, including attach and update functionality
This commit is contained in:
@@ -228,6 +228,7 @@ class AdminApiController extends BaseController
|
||||
'doctor' => $qb->andWhere("u.roles LIKE :role AND u.roles NOT LIKE :notRole")
|
||||
->setParameter('role', '%ROLE_DOCTOR%')->setParameter('notRole', '%ROLE_ADMIN%'),
|
||||
'secretary' => $qb->andWhere("u.roles LIKE :role")->setParameter('role', '%ROLE_SECRETARY%'),
|
||||
'representation' => $qb->andWhere("u.roles LIKE :role")->setParameter('role', '%ROLE_REPRESENTATION%'),
|
||||
'clinic' => $qb->andWhere("u.roles LIKE :role AND u.roles NOT LIKE :notRole")
|
||||
->setParameter('role', '%ROLE_CLINIC%')->setParameter('notRole', '%ROLE_ADMIN%'),
|
||||
'patient' => $qb->andWhere("u.roles NOT LIKE :d AND u.roles NOT LIKE :a")
|
||||
@@ -297,6 +298,37 @@ class AdminApiController extends BaseController
|
||||
return $this->success(['is_active' => $doctor->isActiveDoctorAppointment()]);
|
||||
}
|
||||
|
||||
#[Route('/api/v1/admin/doctors/{uuid}/representation', methods: ['PUT'])]
|
||||
public function setDoctorRepresentation(string $uuid, Request $request, RepresentationRepository $repRepo): JsonResponse
|
||||
{
|
||||
$doctor = $this->em->getRepository(Doctor::class)->findOneBy(['uuid' => $uuid]);
|
||||
if ($doctor === null) {
|
||||
return $this->error(ErrorCodes::DOCTOR_NOT_FOUND, 'پزشک یافت نشد', 404);
|
||||
}
|
||||
|
||||
$body = json_decode($request->getContent(), true) ?? [];
|
||||
$repId = $body['representation_id'] ?? null;
|
||||
|
||||
if ($repId === null || $repId === '') {
|
||||
$doctor->setRepresentationId(null);
|
||||
$this->em->flush();
|
||||
return $this->success(['message' => 'نماینده حذف شد', 'representation' => null]);
|
||||
}
|
||||
|
||||
$rep = $repRepo->find((int) $repId);
|
||||
if ($rep === null) {
|
||||
return $this->error(ErrorCodes::ERR_NOT_FOUND_001, 'نماینده یافت نشد', 404);
|
||||
}
|
||||
|
||||
$doctor->setRepresentationId($rep->getId());
|
||||
$this->em->flush();
|
||||
|
||||
return $this->success([
|
||||
'message' => 'نماینده ثبت شد',
|
||||
'representation' => ['id' => $rep->getId(), 'uuid' => $rep->getUuid(), 'full_name' => $rep->getFullName()],
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/api/v1/admin/doctors', methods: ['GET'])]
|
||||
public function doctorsList(Request $request): JsonResponse
|
||||
{
|
||||
@@ -1130,26 +1162,104 @@ class AdminApiController extends BaseController
|
||||
$conn = $this->em->getConnection();
|
||||
$total = (int) $conn->fetchOne('SELECT COUNT(*) FROM doctors WHERE representation_id = ?', [$repId]);
|
||||
|
||||
$now = time();
|
||||
$offset = ($page - 1) * $limit;
|
||||
$rows = $conn->fetchAllAssociative(
|
||||
"SELECT d.id, d.uuid, d.name, d.gender, d.medical_system_code,
|
||||
d.active_doctor_appointment, d.owner_status, d.created_at,
|
||||
(SELECT COUNT(*) FROM appointments a WHERE a.doctor_id = d.id) AS appointment_count
|
||||
(SELECT COUNT(*) FROM appointments a WHERE a.doctor_id = d.id AND a.slot_start < $now) AS past_count,
|
||||
(SELECT COUNT(*) FROM appointments a WHERE a.doctor_id = d.id AND a.slot_start >= $now) AS upcoming_count
|
||||
FROM doctors d
|
||||
WHERE d.representation_id = ? ORDER BY d.created_at DESC LIMIT $limit OFFSET $offset",
|
||||
[$repId]
|
||||
);
|
||||
|
||||
$items = array_map(fn(array $d): array => [
|
||||
'uuid' => $d['uuid'],
|
||||
'id' => (int) $d['id'],
|
||||
'name' => $d['name'],
|
||||
'gender' => $d['gender'],
|
||||
'medical_code' => $d['medical_system_code'],
|
||||
'is_active' => (bool) $d['active_doctor_appointment'],
|
||||
'owner_status' => $d['owner_status'],
|
||||
'appointment_count' => (int) $d['appointment_count'],
|
||||
'created_at' => date('c', (int) $d['created_at']),
|
||||
'uuid' => $d['uuid'],
|
||||
'id' => (int) $d['id'],
|
||||
'name' => $d['name'],
|
||||
'gender' => $d['gender'],
|
||||
'medical_code' => $d['medical_system_code'],
|
||||
'is_active' => (bool) $d['active_doctor_appointment'],
|
||||
'owner_status' => $d['owner_status'],
|
||||
'past_count' => (int) $d['past_count'],
|
||||
'upcoming_count' => (int) $d['upcoming_count'],
|
||||
'created_at' => date('c', (int) $d['created_at']),
|
||||
], $rows);
|
||||
|
||||
return $this->paginated($items, $total, $page, $limit);
|
||||
}
|
||||
|
||||
#[Route('/api/v1/admin/representations/{uuid}/doctors', methods: ['POST'])]
|
||||
public function attachDoctorToRepresentation(string $uuid, Request $request, RepresentationRepository $repRepo): JsonResponse
|
||||
{
|
||||
$rep = $repRepo->findByUuid($uuid);
|
||||
if ($rep === null) {
|
||||
return $this->error(ErrorCodes::ERR_NOT_FOUND_001, 'نماینده یافت نشد', 404);
|
||||
}
|
||||
|
||||
$body = json_decode($request->getContent(), true) ?? [];
|
||||
$doctorUuid = trim((string) ($body['doctor_uuid'] ?? ''));
|
||||
if ($doctorUuid === '') {
|
||||
return $this->error(ErrorCodes::ERR_VALIDATION_001, 'شناسهی پزشک الزامی است', 422);
|
||||
}
|
||||
|
||||
$doctor = $this->em->getRepository(Doctor::class)->findOneBy(['uuid' => $doctorUuid]);
|
||||
if ($doctor === null) {
|
||||
return $this->error(ErrorCodes::ERR_NOT_FOUND_001, 'پزشک یافت نشد', 404);
|
||||
}
|
||||
if ($doctor->getRepresentationId() !== null) {
|
||||
return $this->error(ErrorCodes::ERR_CONFLICT_001, 'این پزشک از قبل به یک نماینده متصل است', 409);
|
||||
}
|
||||
|
||||
$doctor->setRepresentationId($rep->getId());
|
||||
$this->em->flush();
|
||||
|
||||
return $this->success(['message' => 'پزشک به نماینده متصل شد', 'doctor_uuid' => $doctorUuid, 'representation_id' => $rep->getId()]);
|
||||
}
|
||||
|
||||
#[Route('/api/v1/admin/representations/{uuid}/appointments', methods: ['GET'])]
|
||||
public function representationAppointments(string $uuid, Request $request, RepresentationRepository $repRepo): JsonResponse
|
||||
{
|
||||
$rep = $repRepo->findByUuid($uuid);
|
||||
if ($rep === null) {
|
||||
return $this->error(ErrorCodes::ERR_NOT_FOUND_001, 'نماینده یافت نشد', 404);
|
||||
}
|
||||
|
||||
$page = max(1, (int) $request->query->get('page', 1));
|
||||
$limit = min(100, max(1, (int) $request->query->get('limit', 15)));
|
||||
$scope = $request->query->get('scope') === 'past' ? 'past' : 'upcoming';
|
||||
$repId = $rep->getId();
|
||||
$now = time();
|
||||
|
||||
$conn = $this->em->getConnection();
|
||||
$cmp = $scope === 'past' ? '<' : '>=';
|
||||
$order = $scope === 'past' ? 'DESC' : 'ASC';
|
||||
|
||||
$total = (int) $conn->fetchOne(
|
||||
"SELECT COUNT(*) FROM appointments a JOIN doctors d ON d.id = a.doctor_id
|
||||
WHERE d.representation_id = ? AND a.slot_start $cmp ?",
|
||||
[$repId, $now]
|
||||
);
|
||||
|
||||
$offset = ($page - 1) * $limit;
|
||||
$rows = $conn->fetchAllAssociative(
|
||||
"SELECT a.uuid, a.slot_start, a.slot_end, a.status, a.patient_name,
|
||||
d.uuid AS doctor_uuid, d.name AS doctor_name
|
||||
FROM appointments a JOIN doctors d ON d.id = a.doctor_id
|
||||
WHERE d.representation_id = ? AND a.slot_start $cmp ?
|
||||
ORDER BY a.slot_start $order LIMIT $limit OFFSET $offset",
|
||||
[$repId, $now]
|
||||
);
|
||||
|
||||
$items = array_map(fn(array $a): array => [
|
||||
'uuid' => $a['uuid'],
|
||||
'slot_start' => (int) $a['slot_start'],
|
||||
'slot_end' => (int) $a['slot_end'],
|
||||
'status' => $a['status'],
|
||||
'patient_name' => $a['patient_name'],
|
||||
'doctor_uuid' => $a['doctor_uuid'],
|
||||
'doctor_name' => $a['doctor_name'],
|
||||
], $rows);
|
||||
|
||||
return $this->paginated($items, $total, $page, $limit);
|
||||
|
||||
Reference in New Issue
Block a user