# نکات پیاده‌سازی — تسک ۱۶: ماژول 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 ```