feat(doctors): enhance doctor listing with bookable sorting and filtering, add JSON_EXTRACT DQL function

This commit is contained in:
hamed
2026-07-14 11:25:39 +03:30
parent d2372d4d21
commit 34d8a400b7
6 changed files with 189 additions and 7 deletions
+25 -6
View File
@@ -2,6 +2,7 @@
namespace App\Doctor\Repository;
use App\Appointment\Entity\WeeklySchedule;
use App\Auth\Entity\User;
use App\Clinic\Entity\Clinic;
use App\Doctor\Entity\Doctor;
@@ -88,13 +89,31 @@ class DoctorRepository extends ServiceEntityRepository
if (!empty($filters['name'])) {
$qb->andWhere('d.name LIKE :name')->setParameter('name', '%' . $filters['name'] . '%');
}
// Public list shows only doctors with appointment enabled unless the
// caller explicitly asks otherwise (e.g. admin passing active=0).
$active = isset($filters['active']) ? (bool) $filters['active'] : true;
$qb->andWhere('d.activeDoctorAppointment = :active')
->setParameter('active', $active);
// "دارای نوبت" = appointment flag on AND a weekly schedule exists with
// online booking not disabled AND at least one active session — same
// definition as the `active` field in Doctor::toListArray(), so
// filter/sort match what the doctor card shows.
$bookable = fn(string $alias): string => sprintf(
'd.activeDoctorAppointment = true AND EXISTS(SELECT %1$s.id FROM %2$s %1$s WHERE %1$s.doctor = d'
. ' AND (JSON_EXTRACT(%1$s.setting, \'$.meta.online_booking_enabled\') IS NULL OR JSON_EXTRACT(%1$s.setting, \'$.meta.online_booking_enabled\') != \'false\')'
. ' AND JSON_CONTAINS(JSON_EXTRACT(%1$s.setting, \'$**.sessions[*].active\'), \'true\') = 1)',
$alias,
WeeklySchedule::class
);
$qb->orderBy('d.doctorRate', $sort);
if (isset($filters['active'])) {
if ((bool) $filters['active']) {
$qb->andWhere($bookable('wsf'));
} else {
// Legacy admin escape hatch: active=0 → flag explicitly off.
$qb->andWhere('d.activeDoctorAppointment = false');
}
}
// Bookable doctors always rank above non-bookable ones.
$qb->addSelect('(CASE WHEN ' . $bookable('wss') . ' THEN 1 ELSE 0 END) AS HIDDEN bookableRank')
->orderBy('bookableRank', 'DESC')
->addOrderBy('d.doctorRate', $sort);
$total = (new Paginator($qb))->count();
$results = $qb->setFirstResult(($page - 1) * $limit)