- Add SendSmsMessage class for encapsulating SMS message data. - Create KavehNegarProvider and RanginehProvider classes implementing SmsProviderInterface for sending SMS. - Implement SmsLogRepository and SmsTemplateRepository for managing SMS logs and templates. - Develop SendSmsHandler for handling SMS sending messages. - Create SmsService to manage SMS dispatching and logging. - Add UserProfileController for managing user profiles with CRUD operations. - Implement UserProfile entity and repository for user profile data management. - Update symfony.lock and bootstrap.php for project dependencies and environment setup.
4.7 KiB
4.7 KiB
نکات پیادهسازی — تسک ۱۶: ماژول Representation (داشبورد دکتر)
مهم: این ماژول دو نقش دارد
۱. مدیریت نمایندگی (Multi-tenant) — هر نماینده یک دامنه دارد ۲. داشبورد دکتر — آمار نوبتها، درآمد، بیماران
ساختار Representation در Drupal
// فیلدهای 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
// در زمان ثبت نوبت:
$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 برای تعیین ماه جاری شمسی استفاده میکند
// محاسبه بازه ماه جاری شمسی:
$persianMonthRange = $jalaliService->getCurrentPersianMonthRange($timestamp);
$startTimestamp = $persianMonthRange['start'];
// آمار پرداختها در این ماه:
// field_status = 'received' AND field_representation = $id AND created >= $startTimestamp
Response:
{
"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 از تقویم شمسی (جلالی) استفاده میکند:
// محاسبه بازه سال شمسی:
$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:
{
"year": 1403,
"monthly_income": [
{ "month": 1, "income": 8500000 },
{ "month": 2, "income": 9200000 },
...
{ "month": 12, "income": 0 }
]
}
JalaliDateService پیادهسازی در Symfony
از کد custom_service/src/jalali/JalaliDateService.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 دقیقه):
$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