# غنی‌سازی پاسخ نوبت با تخصص و آدرس مطب پزشک

## پروژه

`clinicpro` (Backend — منبع حقیقت).

> **Cross-repo:** صفحه‌ی «جزئیات نوبت» در `nobat724_front` (داشبورد → نوبت‌های من → مشاهده جزئیات) این فیلدها را مصرف می‌کند (پرامپت همتا: `nobat724_front/.claude/prompt/appointment-detail-fields-fix.md`). این پرامپت **اول** اجرا شود.

## زمینه

`Appointment::toArray()` فقط `doctor:{uuid,name}`, `slot_start/slot_end`, `status`, `note`, `patient_*` را برمی‌گرداند. اما صفحه‌ی جزئیات نوبت در فرانت می‌خواهد **تخصص پزشک، آدرس مطب، تلفن و مختصات نقشه** را هم نشان دهد. چون این داده‌ها در پاسخ نیستند، آن بخش‌ها خالی می‌مانند.

`Doctor` این روابط را دارد: `getSpecialties()` (ManyToMany به `Specialty`)، `getAddresses()` (OneToMany به `DoctorAddress`). `DoctorAddress::toArray()` شکل `{address, telephone, map:{latitude,longitude}, name, ...}` می‌دهد. نوبت آدرس مشخصی ذخیره نمی‌کند، پس **اولین آدرس پزشک** به‌عنوان آدرس مطب استفاده می‌شود.

## مشکل / هدف

`Appointment::toArray()` گسترش یابد تا `doctor` شامل `specialties` و `address` (اولین آدرس پزشک با `address/telephone/map`) باشد — بدون شکستن مصرف‌کننده‌های فعلی.

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

| فایل | نقش |
|------|-----|
| `src/Appointment/Entity/Appointment.php` | `toArray()` — افزودن specialties + address زیر `doctor` |
| `src/Doctor/Entity/Doctor.php` | `getSpecialties()`, `getAddresses()` (موجود) |
| `src/Doctor/Entity/DoctorAddress.php` | `toArray()` → `{address, telephone, map, ...}` (موجود) |
| `src/Specialty/Entity/Specialty.php` | `getUuid()/getName()` (موجود) |

## وضعیت فعلی (کد واقعی)

```php
// Appointment::toArray()
'doctor' => [
    'uuid' => $this->doctor->getUuid(),
    'name' => $this->doctor->getName(),
],
'slot_start' => $this->slotStart,
'slot_end'   => $this->slotEnd,
// ... بدون specialties / address
```

`DoctorAddress::toArray()` (مرجع شکل):
```php
'map'       => ['latitude' => (string)…, 'longitude' => (string)…],
'address'   => $this->address,
'telephone' => $this->telephone,
'name'      => $this->name,
```

## وظایف

### ۱. افزودن specialties و address به `doctor` در `Appointment::toArray()`
```php
$doctor = $this->doctor;
$firstAddress = $doctor->getAddresses()->first() ?: null;

// ...
'doctor' => [
    'uuid'        => $doctor->getUuid(),
    'name'        => $doctor->getName(),
    'specialties' => array_map(
        fn($s) => ['uuid' => $s->getUuid(), 'name' => $s->getName()],
        $doctor->getSpecialties()->toArray()
    ),
],
'address' => $firstAddress ? $firstAddress->toArray() : null,
```
- `address` را در سطح بالای آرایه‌ی نوبت بگذار (نه داخل doctor) تا فرانت `appointmentData.address.{address,telephone,map}` را مستقیم بخواند.
- `getAddresses()->first()` ممکن است `false` برگرداند (Doctrine Collection) → با `?: null` ایمن کن.
- بقیه‌ی کلیدهای موجود (`slot_start`, `status`, ...) بدون تغییر بمانند.

### ۲. مستندسازی `docs/api/appointment.md`
شکل جدید `doctor.specialties` و `address` را در response نمونه‌ی `GET /api/v1/appointments/user` (و `GET /api/v1/appointment/{uuid}`) اضافه کن.

## نکات مهم

- **بدون شکستن مصرف‌کننده‌ها:** فقط کلید اضافه می‌شود؛ کلیدهای فعلی دست‌نخورده. (پنل ادمین/جاهای دیگری که `toArray` نوبت را می‌خوانند نباید بشکنند.)
- تخصص ممکن است خالی باشد (آرایه‌ی خالی) و آدرس ممکن است `null` باشد (پزشک بدون آدرس) — فرانت باید این‌ها را تحمل کند (در پرامپت فرانت لحاظ شده).
- نوبت آدرس اختصاصی ذخیره نمی‌کند؛ «اولین آدرس پزشک» یک تقریب منطقی است. اگر بعداً نوبت به آدرس مشخص گره خورد، اینجا باید آن را ترجیح داد.
- `slot_start`/`slot_end` Unix‌اند (فرانت تاریخ و ساعت را از `slot_start` می‌سازد).
- پاسخ‌ها از `BaseController`؛ migration لازم نیست.
- تست: `GET /api/v1/appointments/user` برای کاربری با نوبت → آیتم باید `doctor.specialties[]` و `address.{address,telephone,map}` داشته باشد.
