Files
hamed de1a78a235 feat: Implement SMS sending functionality with KavehNegar and Rangineh providers
- 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.
2026-06-09 22:00:34 +03:30

1.9 KiB

معماری — تسک ۱۶: ماژول داشبورد دکتر

ساختار فایل‌ها

src/Module/Representation/
├── Controller/
│   └── RepresentationController.php
├── Service/
│   ├── DashboardService.php        ← آمار کلی
│   ├── IncomeService.php           ← محاسبه درآمد
│   └── AppointmentReportService.php ← گزارش نوبت‌ها
├── Repository/
│   └── RepresentationRepository.php  ← کوئری‌های پیچیده آماری
└── DTO/
    └── Response/
        ├── DashboardResponse.php
        ├── YearlyIncomeResponse.php
        └── AppointmentListResponse.php

نمودار جریان

GET /representation/{uuid}
          │
          ▼
DashboardService
  ├─► شمارش appointments (ماه جاری، کل، pending)
  ├─► جمع payments (ماه جاری، کل)
  └─► average_rating از doctors.average_rating

کوئری درآمد سالانه (بر اساس ماه‌های شمسی)

// RepresentationRepository.php
// توجه: محاسبه بر اساس ماه شمسی است، نه میلادی
// JalaliDateService بازه timestamp هر ماه را می‌دهد
public function getMonthIncome(int $representationId, int $startTs, int $endTs): float
{
    return (float) $this->createQueryBuilder('p')
        ->select('SUM(p.amount)')
        ->where('p.representationId = :repr')
        ->andWhere('p.status = :status')
        ->andWhere('p.createdAt >= :start')
        ->andWhere('p.createdAt < :end')
        ->setParameters([
            'repr'   => $representationId,
            'status' => 'received',   // نه 'paid'!
            'start'  => (new \DateTime())->setTimestamp($startTs),
            'end'    => (new \DateTime())->setTimestamp($endTs),
        ])
        ->getQuery()
        ->getSingleScalarResult() ?? 0.0;
}