Merge branch 'dev' into main
# Conflicts: # docs/api/doctor.md
This commit is contained in:
@@ -138,6 +138,88 @@ class DoctorRepository extends ServiceEntityRepository
|
||||
*
|
||||
* @return int[]
|
||||
*/
|
||||
/**
|
||||
* شهر/استان دستهای پزشکان برای پاسخ لیست — دو کوئری ثابت، نه یکی بهازای هر پزشک.
|
||||
*
|
||||
* همان قاعدهای که فیلتر city_id/state_id در findWithFilters اعمال میکند اینجا هم
|
||||
* برقرار است: اول آدرس شخصی خود پزشک، و اگر نداشت آدرس کلینیکی که عضو آن است
|
||||
* (آدرس کلینیک ردیفی از DoctorAddress با doctor IS NULL و clinicId پرشده است).
|
||||
* بدون این fallback، پزشکی که فقط از طریق کلینیک مکان دارد در فیلتر city_id
|
||||
* میآمد ولی در پاسخ شهرش خالی بود.
|
||||
*
|
||||
* @param Doctor[] $doctors
|
||||
* @return array<int, array{city: ?array, province: ?array}>
|
||||
*/
|
||||
public function findLocationsByDoctors(array $doctors): array
|
||||
{
|
||||
$ids = array_values(array_filter(array_map(fn(Doctor $d) => $d->getId(), $doctors)));
|
||||
if (!$ids) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$locationFields = [
|
||||
'c.id AS cityId', 'c.uuid AS cityUuid', 'c.name AS cityName',
|
||||
'p.id AS provinceId', 'p.uuid AS provinceUuid', 'p.name AS provinceName',
|
||||
];
|
||||
|
||||
$ownRows = $this->getEntityManager()->createQueryBuilder()
|
||||
->select('IDENTITY(da.doctor) AS doctorId', ...$locationFields)
|
||||
->from(DoctorAddress::class, 'da')
|
||||
->join('da.city', 'c')
|
||||
->leftJoin('da.province', 'p')
|
||||
->where('da.doctor IN (:ids)')
|
||||
->setParameter('ids', $ids)
|
||||
->getQuery()
|
||||
->getArrayResult();
|
||||
|
||||
$map = $this->indexLocationRows($ownRows, []);
|
||||
|
||||
$missing = array_values(array_diff($ids, array_keys($map)));
|
||||
if ($missing) {
|
||||
$clinicRows = $this->getEntityManager()->createQueryBuilder()
|
||||
->select('cd.id AS doctorId', ...$locationFields)
|
||||
->from(Clinic::class, 'cl')
|
||||
->join('cl.doctors', 'cd')
|
||||
->join(DoctorAddress::class, 'ca', Join::WITH, 'ca.clinicId = cl.id AND ca.doctor IS NULL')
|
||||
->join('ca.city', 'c')
|
||||
->leftJoin('ca.province', 'p')
|
||||
->where('cd.id IN (:ids)')
|
||||
->setParameter('ids', $missing)
|
||||
->getQuery()
|
||||
->getArrayResult();
|
||||
|
||||
$map = $this->indexLocationRows($clinicRows, $map);
|
||||
}
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
||||
/** اولین مکانِ هر پزشک برنده است — پزشک چند-مطبی یک شهر اصلی میگیرد. */
|
||||
private function indexLocationRows(array $rows, array $map): array
|
||||
{
|
||||
foreach ($rows as $row) {
|
||||
$doctorId = (int) $row['doctorId'];
|
||||
if (isset($map[$doctorId])) {
|
||||
continue;
|
||||
}
|
||||
$map[$doctorId] = [
|
||||
'city' => [
|
||||
'uuid' => $row['cityUuid'],
|
||||
'id' => (string) $row['cityId'],
|
||||
'name' => $row['cityName'],
|
||||
'parent' => $row['provinceId'] !== null ? (string) $row['provinceId'] : null,
|
||||
],
|
||||
'province' => $row['provinceId'] !== null ? [
|
||||
'uuid' => $row['provinceUuid'],
|
||||
'id' => (string) $row['provinceId'],
|
||||
'name' => $row['provinceName'],
|
||||
] : null,
|
||||
];
|
||||
}
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
||||
private function doctorIdsViaClinicLocation(string $field, int $locationId): array
|
||||
{
|
||||
$column = $field === 'city' ? 'ca.city' : 'ca.province';
|
||||
|
||||
Reference in New Issue
Block a user