# فیکس نمایش دکتر در شهر از طریق کلینیک

## پروژه

`clinicpro` (backend)

## زمینه

دکتری که هیچ آدرس و city مستقیمی ندارد اما به یک کلینیک وصل است، در سایت عمومی (`nobat724_front`) در شهر آن کلینیک نمایش داده نمی‌شود. علت: query فیلتر city فقط روی `d.cities` (جدول `doctor_cities`) کار می‌کند و `Clinic.cityId` را نادیده می‌گیرد.

## مشکل

`DoctorRepository::findWithFilters()` فیلتر city:

```php
// clinicpro/src/Doctor/Repository/DoctorRepository.php خط ۵۶-۵۸
if (!empty($filters['city'])) {
    $qb->andWhere('ci.id = :city')->setParameter('city', (int) $filters['city']);
}
```

`ci` از `leftJoin('d.cities', 'ci')` می‌آید — جدول `doctor_cities`. اگر دکتر در این جدول ردیفی نداشته باشد (یعنی هیچ city مستقیم ندارد)، حتی اگر عضو کلینیکی با همان city باشد، از نتایج حذف می‌شود.

## ساختار مرتبط

```php
// Doctor Entity
#[ORM\ManyToMany(targetEntity: City::class)]
#[ORM\JoinTable(name: 'doctor_cities')]
private Collection $cities;  // جدول doctor_cities

// Clinic Entity
#[ORM\Column(name: 'city_id', type: 'integer', nullable: true)]
private ?int $cityId = null;  // FK به categories.id

#[ORM\ManyToMany(targetEntity: Doctor::class)]
#[ORM\JoinTable(name: 'clinic_doctors')]
private Collection $doctors;  // جدول clinic_doctors
```

## فایل‌های مرتبط

| فایل | نقش |
|------|-----|
| `clinicpro/src/Doctor/Repository/DoctorRepository.php` | `findWithFilters()` — باید تغییر کند |
| `clinicpro/src/Doctor/Controller/DoctorController.php` | صدا زننده `findWithFilters` |
| `clinicpro/src/Clinic/Entity/Clinic.php` | `cityId` و `doctors` collection |
| `clinicpro/src/Doctor/Entity/Doctor.php` | `cities` collection |

## وضعیت فعلی

```php
// DoctorRepository.php — findWithFilters()
$qb = $this->createQueryBuilder('d')
    ->leftJoin('d.specialties', 's')
    ->leftJoin('d.provinces', 'pr')
    ->leftJoin('d.cities', 'ci')
    ->distinct();

// ...
if (!empty($filters['city'])) {
    $qb->andWhere('ci.id = :city')->setParameter('city', (int) $filters['city']);
}
```

## وظایف

### ۱. گسترش فیلتر city به clinic city

در `findWithFilters()` join کلینیک را اضافه کن و شرط city را تغییر بده تا هم `doctor_cities` هم `clinic.city_id` را پوشش دهد:

```php
$qb = $this->createQueryBuilder('d')
    ->leftJoin('d.specialties', 's')
    ->leftJoin('d.provinces', 'pr')
    ->leftJoin('d.cities', 'ci')
    ->leftJoin(Clinic::class, 'cl', Join::WITH, 'd MEMBER OF cl.doctors')  // ← اضافه
    ->distinct();

// ...
if (!empty($filters['city'])) {
    $qb->andWhere('ci.id = :city OR cl.cityId = :city')
       ->setParameter('city', (int) $filters['city']);
}
```

همچنین فیلتر `state` را هم بررسی کن — اگر `d.provinces` هم خالی باشد، باید از استان کلینیک گرفته شود. اما برای این باگ، city اولویت دارد.

### ۲. بررسی فیلتر state مشابه

```php
// فعلی:
if (!empty($filters['state'])) {
    $qb->andWhere('pr.id = :state')->setParameter('state', (int) $filters['state']);
}

// باید:
// اگر کلینیک دارد، province آن کلینیک را هم در نظر بگیر
// اما Clinic فقط cityId دارد، نه provinceId مستقیم
// → از category join برای گرفتن province شهر کلینیک استفاده کن یا فعلاً فقط city را فیکس کن
```

### ۳. import لازم

در بالای `DoctorRepository.php` اضافه کن:

```php
use App\Clinic\Entity\Clinic;
use Doctrine\ORM\Query\Expr\Join;
```

(اگر `Join` از قبل import نشده)

### ۴. تست

```bash
ddev exec php bin/console debug:router | grep "api/v1/doctors"
# endpoint: GET /api/v1/doctors?city=<city_id>
# تست: یک دکتر که فقط از طریق کلینیک در شهر X است را با ?city=X جستجو کن
# باید در نتایج ظاهر شود
```

## نکات مهم

- `Clinic.cityId` یک integer FK است به `categories.id` (جدول categories با bundle='city') — نه یک relation object. پس `cl.cityId = :city` درست است (نه `cl.city.id`).
- `leftJoin` برای کلینیک لازم است نه `innerJoin` — دکتری که اصلاً عضو هیچ کلینیکی نیست هم باید در نتایج بماند (اگر city مستقیم دارد).
- `OR cl.cityId = :city` ممکن است با `DISTINCT` مشکل ایجاد کند — اگر دکتر هم city مستقیم دارد هم عضو کلینیک در همان city است، `DISTINCT` آن را یک‌بار نمایش می‌دهد.
- migration لازم نیست — فقط query تغییر می‌کند.
- بعد از تغییر، `docs/api/doctor.md` را update کن (رفتار فیلتر city تغییر کرده).
