# نکات پیاده‌سازی — تسک ۱۶: ماژول Representation (داشبورد دکتر)

## مهم: این ماژول دو نقش دارد
۱. **مدیریت نمایندگی (Multi-tenant)** — هر نماینده یک دامنه دارد
۲. **داشبورد دکتر** — آمار نوبت‌ها، درآمد، بیماران

## ساختار Representation در Drupal
```php
// فیلدهای entity (clinic_pro, bundle=representation):
field_domain_name      // دامنه سایت نماینده (مثل: http://yasuj-nobat.localhost:3000/)
field_city             // entity reference به category (شهر)
field_active           // boolean
field_commission_percent // درصد کمیسیون

// دکتر به نماینده از طریق field_representation لینک می‌شود
// نوبت هم با field_representation لینک می‌شود (از HTTP Host)
```

## شناسایی نماینده از Host
```php
// در زمان ثبت نوبت:
$host = 'http://yasuj-nobat.localhost:3000/';
$representation = $this->representationRepo->findByDomainName($host);
// در Symfony: $request->getSchemeAndHttpHost() . '/'
```

## endpoint: my-doctor (برای بیمار)
```
GET /api/v1/representation/my-doctor/{userId}
```
→ لیست دکترهایی که این کاربر نوبت گرفته را برمی‌گرداند.
فیلد search: `field_representation = $representationId`

## endpoint: my-appointments (برای نماینده)
```
GET /api/v1/representation/my-appointments/{representationId}
```
→ تمام نوبت‌های مرتبط با این نماینده
کوئری روی `appointment.field_representation = $id`

## endpoint: filter (داشبورد ماهانه)
```
GET /api/v1/representation/filter/{representationId}?timestamp=...
```
→ از `timestamp` برای تعیین ماه جاری شمسی استفاده می‌کند

```php
// محاسبه بازه ماه جاری شمسی:
$persianMonthRange = $jalaliService->getCurrentPersianMonthRange($timestamp);
$startTimestamp = $persianMonthRange['start'];

// آمار پرداخت‌ها در این ماه:
// field_status = 'received' AND field_representation = $id AND created >= $startTimestamp
```

Response:
```json
{
  "payments_total": { "total_price": 12500000, "count": 25 },
  "total_patients": 142,
  "today_appointments": 8
}
```

## endpoint: yearly-income (درآمد سالانه)
```
GET /api/v1/representation/yearly-income/{id}?timestamp=...
```

این endpoint از تقویم **شمسی (جلالی)** استفاده می‌کند:
```php
// محاسبه بازه سال شمسی:
$persianYearRange = $jalaliService->getPersianYearRange($timestamp);
$jalaliYear = $persianYearRange['year'];

// Loop از ماه ۱ تا ۱۲ شمسی:
for ($month = 1; $month <= 12; $month++) {
    $monthRange = $this->getMonthRangeByYearAndMonth($jalaliYear, $month);
    $income = $this->getMonthIncome($representationId, $monthRange['start'], $monthRange['end']);
    // income = SUM(payment.amount) WHERE status='received' AND representation=$id AND created BETWEEN start AND end
}
```

Response:
```json
{
  "year": 1403,
  "monthly_income": [
    { "month": 1, "income": 8500000 },
    { "month": 2, "income": 9200000 },
    ...
    { "month": 12, "income": 0 }
  ]
}
```

## JalaliDateService پیاده‌سازی در Symfony
از کد `custom_service/src/jalali/JalaliDateService.php` برای پیاده‌سازی استفاده کن.
توابع مورد نیاز:
```php
class JalaliDateService {
    public function getCurrentPersianMonthRange(?int $timestamp): array;
    // return: ['start' => timestamp, 'end' => timestamp]

    public function getPersianYearRange(?int $timestamp): array;
    // return: ['year' => int, 'start' => timestamp, 'end' => timestamp]

    public function getMonthRangeByYearAndMonth(int $year, int $month): array;
    // return: ['start' => timestamp, 'end' => timestamp]

    public function gregorianToPersian(int $gy, int $gm, int $gd): array;
    // return: [$jy, $jm, $jd]

    public function persianToGregorian(int $jy, int $jm, int $jd): array;
    // return: [$gy, $gm, $gd]
}
```

## کشینگ آمار داشبورد
آمار داشبورد را با Redis کش کن (TTL = 5 دقیقه):
```php
$cacheKey = "dashboard_representation_{$representation->getId()}";
// بعد از هر payment جدید → cache invalidate
```

## مجوزها
```
GET /representation/{uuid}              → دکتر مرتبط یا ROLE_ADMIN
GET /representation/my-appointments/{id} → دکتر/نماینده یا ROLE_ADMIN
GET /representation/my-doctor/{userId}  → کاربر خودش
GET /representation/filter/{id}         → دکتر/نماینده یا ROLE_ADMIN
GET /representation/yearly-income/{id} → دکتر/نماینده یا ROLE_ADMIN
```
