feat: implement realistic data seeding for doctors, clinics, and secretaries

- Added seed_realistic_data.php to clean existing data and populate the database with realistic entries for doctors, clinics, and secretaries.
- Created a structured approach to generate 100 doctors per city with diverse specialties and services.
- Implemented database cleanup routines to ensure a fresh start for data seeding.
- Enhanced the DoctorSecretaryRepository with improved comments for clarity.
This commit is contained in:
hamed
2026-06-15 14:18:25 +03:30
parent 68dfe613a2
commit df7a784701
15 changed files with 3024 additions and 1417 deletions
+180 -145
View File
@@ -1,4 +1,5 @@
# PRD — ClinicPro Phase 2
**تاریخ:** ۲۴ خرداد ۱۴۰۵
**نسخه:** 1.2
**وضعیت:** Draft
@@ -13,24 +14,24 @@
## وضعیت فعلی پروژه
| ماژول | Backend | API Doc |
|--------|---------|---------|
| Auth (OTP + JWT + switch-context) | ✅ کامل | `docs/api/auth.md` |
| Doctor profile | ✅ کامل | `docs/api/doctor.md` |
| Clinic management | ✅ کامل | `docs/api/clinic.md` |
| Appointment booking + settings | ✅ کامل | `docs/api/appointment.md`, `appointment-settings.md` |
| Secretary (`DoctorSecretary` entity) | ✅ entity + API موجود | `docs/api/secretary.md` |
| Payment gateway (Mellat, SEP) | ✅ کامل — `Payment.type='subscription'` هم موجود | `docs/api/payment.md` |
| SMS log + template | ✅ زیرساخت موجود | `docs/api/sms.md` |
| Wallet / Settlement | ✅ کامل | `docs/api/settlement.md` |
| SiteConfig (key-value store) | ✅ موجود | `docs/api/admin.md` §Settings |
| Dashboard (clinic/doctor/secretary) | ✅ کامل | `docs/api/dashboard.md` |
| Rating, Blog, Representation, Location | ✅ کامل | فایل‌های مربوطه در `docs/api/` |
| **Staff (پرسنل)** | ❌ entity وجود ندارد | ❌ فایل doc وجود ندارد |
| **Subscription tiers** | ❌ entity وجود ندارد | ❌ فایل doc وجود ندارد |
| **Clinic services** | ❌ entity وجود ندارد | ❌ فایل doc وجود ندارد |
| **Patient records** | ❌ entity وجود ندارد | ❌ فایل doc وجود ندارد |
| **SMS wallet/settings per clinic** | ❌ entity وجود ندارد | ❌ بخش در sms.md وجود ندارد |
| ماژول | Backend | API Doc |
| -------------------------------------- | ------------------------------------------------ | ---------------------------------------------------- |
| Auth (OTP + JWT + switch-context) | ✅ کامل | `docs/api/auth.md` |
| Doctor profile | ✅ کامل | `docs/api/doctor.md` |
| Clinic management | ✅ کامل | `docs/api/clinic.md` |
| Appointment booking + settings | ✅ کامل | `docs/api/appointment.md`, `appointment-settings.md` |
| Secretary (`DoctorSecretary` entity) | ✅ entity + API موجود | `docs/api/secretary.md` |
| Payment gateway (Mellat, SEP) | ✅ کامل — `Payment.type='subscription'` هم موجود | `docs/api/payment.md` |
| SMS log + template | ✅ زیرساخت موجود | `docs/api/sms.md` |
| Wallet / Settlement | ✅ کامل | `docs/api/settlement.md` |
| SiteConfig (key-value store) | ✅ موجود | `docs/api/admin.md` §Settings |
| Dashboard (clinic/doctor/secretary) | ✅ کامل | `docs/api/dashboard.md` |
| Rating, Blog, Representation, Location | ✅ کامل | فایل‌های مربوطه در `docs/api/` |
| **Staff (پرسنل)** | ❌ entity وجود ندارد | ❌ فایل doc وجود ندارد |
| **Subscription tiers** | ❌ entity وجود ندارد | ❌ فایل doc وجود ندارد |
| **Clinic services** | ❌ entity وجود ندارد | ❌ فایل doc وجود ندارد |
| **Patient records** | ❌ entity وجود ندارد | ❌ فایل doc وجود ندارد |
| **SMS wallet/settings per clinic** | ❌ entity وجود ندارد | ❌ بخش در sms.md وجود ندارد |
---
@@ -41,19 +42,21 @@
### اپیک ۱ — پرسنل (Staff)
#### توضیح
مدیر کلینیک یا دکتر مستقل می‌تواند پرسنل کلینیک را ثبت کند. پرسنل حساب کاربری ندارند و نیازی به لاگین ندارند. در سرویس‌دهی، سشن‌ها و گزارشات به آن‌ها ارجاع می‌شود.
#### نیازمندی‌های کارکردی
| کد | نیازمندی |
|----|---------|
| F1.1 | ایجاد / ویرایش / غیرفعال‌سازی پرسنل — **حذف سخت ممنوع** (تاریخچه حفظ شود) |
| کد | نیازمندی |
| ---- | ------------------------------------------------------------------------------------ |
| F1.1 | ایجاد / ویرایش / غیرفعال‌سازی پرسنل — **حذف سخت ممنوع** (تاریخچه حفظ شود) |
| F1.2 | فیلدها: نام و نام‌خانوادگی (اجباری)، شماره تماس، عنوان شغل، آدرس، کد ملی، وضعیت فعال |
| F1.3 | پرسنل به `entity_type + entity_id` وابسته است (کلینیک یا مطب) |
| F1.4 | لیست پرسنل فقط در scope کلینیک/مطب کاربر جاری نمایش داده می‌شود |
| F1.5 | در ایجاد ServiceItem و SessionService از لیست پرسنل انتخاب می‌شود |
| F1.3 | پرسنل به `entity_type + entity_id` وابسته است (کلینیک یا مطب) |
| F1.4 | لیست پرسنل فقط در scope کلینیک/مطب کاربر جاری نمایش داده می‌شود |
| F1.5 | در ایجاد ServiceItem و SessionService از لیست پرسنل انتخاب می‌شود |
#### Entity جدید
```
clinic_staff:
id, uuid
@@ -69,18 +72,21 @@ clinic_staff:
```
#### API
| Method | Path | توضیح |
|--------|------|-------|
| `GET` | `/api/v1/staff` | لیست پرسنل کاربر جاری |
| `POST` | `/api/v1/staff` | ایجاد پرسنل جدید |
| `PATCH` | `/api/v1/staff/{uuid}` | ویرایش اطلاعات |
| Method | Path | توضیح |
| ------- | ----------------------------- | -------------------------- |
| `GET` | `/api/v1/staff` | لیست پرسنل کاربر جاری |
| `POST` | `/api/v1/staff` | ایجاد پرسنل جدید |
| `PATCH` | `/api/v1/staff/{uuid}` | ویرایش اطلاعات |
| `PATCH` | `/api/v1/staff/{uuid}/toggle` | فعال/غیرفعال (soft delete) |
#### Frontend
- `StaffPage.tsx` — DataTable + Modal ایجاد/ویرایش
- Sidebar: زیر «تنظیمات»
#### فایل‌های جدید
- `src/Staff/Entity/ClinicStaff.php`
- `src/Staff/Controller/StaffController.php`
- `src/Staff/Repository/ClinicStaffRepository.php`
@@ -91,25 +97,26 @@ clinic_staff:
### اپیک ۲ — پنل اشتراکی (Subscription Tiers)
#### توضیح
سه سطح پنل با قابلیت‌های متفاوت. ادمین برای هر پنل دوره‌های زمانی با قیمت مشخص تعریف می‌کند. کلینیک/دکتر دوره + پنل انتخاب کرده و پرداخت می‌کند.
#### سطوح پنل
| Level | Name | منشی | قابلیت‌های اضافه |
|-------|------|------|----------------|
| 0 | Free | ۱ منشی | نوبت‌دهی — رایگان، بدون انقضا |
| 1 | Basic | ۲ منشی | پرونده بیمار + سرویس‌ها |
| 2 | Professional | ۵ منشی | پرونده بیمار + سرویس‌ها |
| Level | Name | منشی | قابلیت‌های اضافه |
| ----- | ------------ | ------ | ----------------------------- |
| 0 | Free | ۱ منشی | نوبت‌دهی — رایگان، بدون انقضا |
| 1 | Basic | ۲ منشی | پرونده بیمار + سرویس‌ها |
| 2 | Professional | ۵ منشی | پرونده بیمار + سرویس‌ها |
#### دوره‌های اشتراک (مثال — ادمین تنظیم می‌کند)
| نوع | مدت | قیمت |
|-----|-----|------|
| تریال | ۱ ماه | ۰ ریال — فقط برای Basic، یک‌بار |
| ۱ ماهه | ۱ ماه | ادمین تعیین می‌کند |
| ۳ ماهه | ۳ ماه | ادمین تعیین می‌کند |
| ۶ ماهه | ۶ ماه | ادمین تعیین می‌کند |
| ۱۲ ماهه | ۱۲ ماه | ادمین تعیین می‌کند |
| نوع | مدت | قیمت |
| ------- | ------ | ------------------------------- |
| تریال | ۱ ماه | ۰ ریال — فقط برای Basic، یک‌بار |
| ۱ ماهه | ۱ ماه | ادمین تعیین می‌کند |
| ۳ ماهه | ۳ ماه | ادمین تعیین می‌کند |
| ۶ ماهه | ۶ ماه | ادمین تعیین می‌کند |
| ۱۲ ماهه | ۱۲ ماه | ادمین تعیین می‌کند |
#### قوانین تریال
@@ -121,18 +128,19 @@ clinic_staff:
#### نیازمندی‌های کارکردی
| کد | نیازمندی |
|----|---------|
| F2.1 | ادمین قیمت هر ترکیب (پنل × دوره) را تعریف می‌کند |
| F2.2 | ادمین می‌تواند دوره‌های جدید اضافه یا غیرفعال کند |
| کد | نیازمندی |
| ---- | ---------------------------------------------------------------------------- |
| F2.1 | ادمین قیمت هر ترکیب (پنل × دوره) را تعریف می‌کند |
| F2.2 | ادمین می‌تواند دوره‌های جدید اضافه یا غیرفعال کند |
| F2.3 | پرداخت از طریق gateway موجود (Mellat/SEP) — `Payment.type='subscription'` ✅ |
| F2.4 | پس از پرداخت موفق: `starts_at=now`, `expires_at=now + months*30*86400` |
| F2.5 | تمدید از تاریخ انقضای قبلی محاسبه می‌شود (نه از now) |
| F2.6 | gate check: `hasFeature('patient_records')` — اشتراک فعال و منقضی نشده |
| F2.7 | هشدار ۷ روز قبل از انقضا به کلینیک/دکتر |
| F2.8 | گزارش فروش برای ادمین (تعداد، درآمد، بر اساس سطح و دوره) |
| F2.4 | پس از پرداخت موفق: `starts_at=now`, `expires_at=now + months*30*86400` |
| F2.5 | تمدید از تاریخ انقضای قبلی محاسبه می‌شود (نه از now) |
| F2.6 | gate check: `hasFeature('patient_records')` — اشتراک فعال و منقضی نشده |
| F2.7 | هشدار ۷ روز قبل از انقضا به کلینیک/دکتر |
| F2.8 | گزارش فروش برای ادمین (تعداد، درآمد، بر اساس سطح و دوره) |
#### Entities جدید
```
subscription_plans:
id, uuid
@@ -168,31 +176,34 @@ clinic_subscriptions:
```
#### API
| Method | Path | Permission | توضیح |
|--------|------|-----------|-------|
| `GET` | `/api/v1/subscription/plans` | public | لیست پنل‌ها با دوره‌ها و قیمت‌ها |
| `GET` | `/api/v1/subscription/my` | clinic/doctor | اشتراک فعال + `used_trial` + تاریخ انقضا |
| `POST` | `/api/v1/subscription/trial` | clinic/doctor | فعال‌سازی تریال (رایگان، یک‌بار) |
| `POST` | `/api/v1/subscription-payment` | clinic/doctor | شروع پرداخت — body: `{ period_uuid }` |
| `GET` | `/api/v1/admin/subscription/plans` | admin | لیست پنل‌ها |
| `POST` | `/api/v1/admin/subscription/plan` | admin | ایجاد پنل |
| `PATCH` | `/api/v1/admin/subscription/plan/{uuid}` | admin | ویرایش پنل |
| `POST` | `/api/v1/admin/subscription/period` | admin | افزودن دوره جدید |
| `PATCH` | `/api/v1/admin/subscription/period/{uuid}` | admin | ویرایش قیمت/مدت |
| `DELETE` | `/api/v1/admin/subscription/period/{uuid}` | admin | غیرفعال‌سازی دوره |
| `GET` | `/api/v1/admin/subscription/report` | admin | گزارش فروش + تریال‌ها |
| Method | Path | Permission | توضیح |
| -------- | ------------------------------------------ | ------------- | ---------------------------------------- |
| `GET` | `/api/v1/subscription/plans` | public | لیست پنل‌ها با دوره‌ها و قیمت‌ها |
| `GET` | `/api/v1/subscription/my` | clinic/doctor | اشتراک فعال + `used_trial` + تاریخ انقضا |
| `POST` | `/api/v1/subscription/trial` | clinic/doctor | فعال‌سازی تریال (رایگان، یک‌بار) |
| `POST` | `/api/v1/subscription-payment` | clinic/doctor | شروع پرداخت — body: `{ period_uuid }` |
| `GET` | `/api/v1/admin/subscription/plans` | admin | لیست پنل‌ها |
| `POST` | `/api/v1/admin/subscription/plan` | admin | ایجاد پنل |
| `PATCH` | `/api/v1/admin/subscription/plan/{uuid}` | admin | ویرایش پنل |
| `POST` | `/api/v1/admin/subscription/period` | admin | افزودن دوره جدید |
| `PATCH` | `/api/v1/admin/subscription/period/{uuid}` | admin | ویرایش قیمت/مدت |
| `DELETE` | `/api/v1/admin/subscription/period/{uuid}` | admin | غیرفعال‌سازی دوره |
| `GET` | `/api/v1/admin/subscription/report` | admin | گزارش فروش + تریال‌ها |
#### Frontend
- `SubscriptionPage.tsx`:
- بنر تریال اگر `used_trial=false`
- وضعیت پنل فعال + تاریخ انقضا (شمسی) + badge «تریال»
- جدول مقایسه پنل‌ها با انتخاب دوره
- دکمه خرید → redirect به gateway
- بنر تریال اگر `used_trial=false`
- وضعیت پنل فعال + تاریخ انقضا (شمسی) + badge «تریال»
- جدول مقایسه پنل‌ها با انتخاب دوره
- دکمه خرید → redirect به gateway
- `AdminSubscriptionPage.tsx`:
- تب «پنل‌ها»: ویرایش دوره‌ها و قیمت‌ها
- تب «گزارش»: فروش بر اساس بازه زمانی
- تب «پنل‌ها»: ویرایش دوره‌ها و قیمت‌ها
- تب «گزارش»: فروش بر اساس بازه زمانی
#### فایل‌های جدید
- `src/Subscription/Entity/SubscriptionPlan.php`
- `src/Subscription/Entity/SubscriptionPeriod.php`
- `src/Subscription/Entity/ClinicSubscription.php`
@@ -205,24 +216,28 @@ clinic_subscriptions:
### اپیک ۳ — منشی (Secretary) — تکمیل
#### توضیح
Entity `DoctorSecretary` و API کامل موجود است (`docs/api/secretary.md`). باید:
- محدودیت تعداد بر اساس پنل اعمال شود
- UI مدیریت permissions تکمیل شود
#### نیازمندی‌های کارکردی
| کد | نیازمندی |
|----|---------|
| F3.1 | بررسی سقف پنل قبل از ایجاد: Free→1، Basic→2، Pro→5 |
| F3.2 | UI لیست منشیان + اضافه‌کردن + ویرایش + غیرفعال‌سازی |
| کد | نیازمندی |
| ---- | -------------------------------------------------------------------------------------- |
| F3.1 | بررسی سقف پنل قبل از ایجاد: Free→1، Basic→2، Pro→5 |
| F3.2 | UI لیست منشی ها + اضافه‌کردن + ویرایش + غیرفعال‌سازی |
| F3.3 | ویرایشگر permissions: checkbox matrix (موجود در `DoctorSecretary.DEFAULT_PERMISSIONS`) |
| F3.4 | منشی هرگز حذف نمی‌شود — `active: false` |
| F3.4 | منشی هرگز حذف نمی‌شود — `active: false` |
#### تغییرات مورد نیاز
- **Backend:** `SecretaryController::create()` — بررسی سقف پنل با `SubscriptionService`
- **Frontend:** Modal با checkbox matrix برای permissions در `SecretariesPage.tsx`
#### API موجود (نیاز به تغییر ندارند)
`GET /api/v1/secretaries/{doctorUuid}` | `POST /api/v1/secretary` | `PATCH /api/v1/secretary/{uuid}` | `DELETE /api/v1/secretary/{uuid}`
---
@@ -230,19 +245,21 @@ Entity `DoctorSecretary` و API کامل موجود است (`docs/api/secretary.
### اپیک ۴ — سرویس‌های کلینیک (Clinic Services)
#### توضیح
دسترسی فقط در پنل Basic+. سرویس‌ها در دو سطح: بخش (مثلاً «تزریقات») و زیربخش (مثلاً «سرم»).
#### نیازمندی‌های کارکردی
| کد | نیازمندی |
|----|---------|
| F4.1 | CRUD بخش‌ها (ServiceSection) |
| F4.2 | CRUD زیربخش‌ها (ServiceItem) با انتخاب بخش + پرسنل انجام‌دهنده |
| F4.3 | قیمت هر زیربخش قابل ویرایش |
| F4.4 | gate: `hasFeature('services')` — بدون Basic+ → 403 |
| کد | نیازمندی |
| ---- | ------------------------------------------------------------------ |
| F4.1 | CRUD بخش‌ها (ServiceSection) |
| F4.2 | CRUD زیربخش‌ها (ServiceItem) با انتخاب بخش + پرسنل انجام‌دهنده |
| F4.3 | قیمت هر زیربخش قابل ویرایش |
| F4.4 | gate: `hasFeature('services')` — بدون Basic+ → 403 |
| F4.5 | لیست ServiceItems در ثبت سشن بیمار استفاده می‌شود (وابستگی اپیک ۶) |
#### Entities جدید
```
service_sections:
id, uuid
@@ -263,21 +280,24 @@ service_items:
```
#### API
| Method | Path | توضیح |
|--------|------|-------|
| `GET` | `/api/v1/service-sections` | لیست بخش‌ها |
| `POST` | `/api/v1/service-section` | ایجاد بخش (Basic+) |
| `PATCH` | `/api/v1/service-section/{uuid}` | ویرایش |
| `DELETE` | `/api/v1/service-section/{uuid}` | حذف |
| `GET` | `/api/v1/service-items/{sectionUuid}` | لیست زیربخش‌های یک بخش |
| `POST` | `/api/v1/service-item` | ایجاد زیربخش (Basic+) |
| `PATCH` | `/api/v1/service-item/{uuid}` | ویرایش |
| `DELETE` | `/api/v1/service-item/{uuid}` | حذف |
| Method | Path | توضیح |
| -------- | ------------------------------------- | ---------------------- |
| `GET` | `/api/v1/service-sections` | لیست بخش‌ها |
| `POST` | `/api/v1/service-section` | ایجاد بخش (Basic+) |
| `PATCH` | `/api/v1/service-section/{uuid}` | ویرایش |
| `DELETE` | `/api/v1/service-section/{uuid}` | حذف |
| `GET` | `/api/v1/service-items/{sectionUuid}` | لیست زیربخش‌های یک بخش |
| `POST` | `/api/v1/service-item` | ایجاد زیربخش (Basic+) |
| `PATCH` | `/api/v1/service-item/{uuid}` | ویرایش |
| `DELETE` | `/api/v1/service-item/{uuid}` | حذف |
#### Frontend
- `ServicesPage.tsx` — accordion دو سطحی: بخش‌ها ← زیربخش‌ها
#### فایل‌های جدید
- `src/ClinicService/Entity/ServiceSection.php`
- `src/ClinicService/Entity/ServiceItem.php`
- `src/ClinicService/Controller/ClinicServiceController.php`
@@ -288,25 +308,28 @@ service_items:
### اپیک ۵ — پنل پیامکی (SMS Panel)
#### توضیح
زیرساخت SMS موجود است (`SmsLog`, `SmsTemplate`, `SmsProvider` در `src/Sms/`). باید:
- کیف پول پیامک اختصاصی برای هر کلینیک/دکتر
- تنظیمات ارسال پیامک (یادآوری، بعد از ویزیت)
- گزارش لاگ برای کلینیک و ادمین
#### نیازمندی‌های کارکردی
| کد | نیازمندی |
|----|---------|
| F5.1 | کیف پول پیامک جدا از کیف پول مالی |
| F5.2 | شارژ از طریق gateway موجود |
| کد | نیازمندی |
| ---- | ---------------------------------------------------------------------- |
| F5.1 | کیف پول پیامک جدا از کیف پول مالی |
| F5.2 | شارژ از طریق gateway موجود |
| F5.3 | ادمین تعرفه هر پیامک را تعیین می‌کند (`sms_price_rials` در SiteConfig) |
| F5.4 | کسر خودکار هزینه بعد از هر ارسال موفق |
| F5.5 | تنظیمات: یادآوری نوبت (فعال/غیرفعال + چند ساعت قبل) |
| F5.6 | تنظیمات: پیام بعد از ویزیت (فعال/غیرفعال + متن) |
| F5.7 | گزارش لاگ پیامک‌های کلینیک/مطب |
| F5.8 | گزارش ادمین: مصرف هر کلینیک + درآمد پیامکی |
| F5.4 | کسر خودکار هزینه بعد از هر ارسال موفق |
| F5.5 | تنظیمات: یادآوری نوبت (فعال/غیرفعال + چند ساعت قبل) |
| F5.6 | تنظیمات: پیام بعد از ویزیت (فعال/غیرفعال + متن) |
| F5.7 | گزارش لاگ پیامک‌های کلینیک/مطب |
| F5.8 | گزارش ادمین: مصرف هر کلینیک + درآمد پیامکی |
#### Entities جدید
```
sms_wallets:
id
@@ -327,20 +350,23 @@ sms_settings:
```
#### API
| Method | Path | Permission | توضیح |
|--------|------|-----------|-------|
| `GET` | `/api/v1/sms/wallet/balance` | clinic/doctor | موجودی کیف پول پیامک |
| `POST` | `/api/v1/sms/wallet/charge` | clinic/doctor | شارژ — body: `{ gateway, amount_rials }` |
| `GET` | `/api/v1/sms/wallet/logs` | clinic/doctor | تاریخچه کسر/شارژ |
| `GET` | `/api/v1/sms/settings` | clinic/doctor | تنظیمات پیامک |
| `PATCH` | `/api/v1/sms/settings` | clinic/doctor | ذخیره تنظیمات |
| `GET` | `/api/v1/admin/sms/wallet-report` | admin | گزارش مصرف و درآمد |
| Method | Path | Permission | توضیح |
| ------- | --------------------------------- | ------------- | ---------------------------------------- |
| `GET` | `/api/v1/sms/wallet/balance` | clinic/doctor | موجودی کیف پول پیامک |
| `POST` | `/api/v1/sms/wallet/charge` | clinic/doctor | شارژ — body: `{ gateway, amount_rials }` |
| `GET` | `/api/v1/sms/wallet/logs` | clinic/doctor | تاریخچه کسر/شارژ |
| `GET` | `/api/v1/sms/settings` | clinic/doctor | تنظیمات پیامک |
| `PATCH` | `/api/v1/sms/settings` | clinic/doctor | ذخیره تنظیمات |
| `GET` | `/api/v1/admin/sms/wallet-report` | admin | گزارش مصرف و درآمد |
#### Frontend
- تب «پیامک» در صفحه تنظیمات کلینیک/دکتر
- نمایش موجودی + دکمه شارژ + لاگ + فرم تنظیمات
#### تأثیر بر فایل‌های موجود
- `docs/api/sms.md`**بخش جدید wallet/settings اضافه شود**
---
@@ -348,20 +374,22 @@ sms_settings:
### اپیک ۶ — پرونده بیمار (Patient Records)
#### توضیح
دسترسی فقط در پنل Basic+. پرونده به صورت خودکار پس از تأیید نوبت ایجاد می‌شود یا دستی توسط منشی/دکتر. هر مراجعه یک سشن است که شامل ویزیت + سرویس‌ها است.
#### نیازمندی‌های کارکردی
| کد | نیازمندی |
|----|---------|
| F6.1 | ایجاد خودکار `PatientRecord` بعد از تأیید appointment (اگر وجود نداشت) |
| F6.2 | ایجاد دستی توسط منشی یا دکتر |
| کد | نیازمندی |
| ---- | ----------------------------------------------------------------------------- |
| F6.1 | ایجاد خودکار `PatientRecord` بعد از تأیید appointment (اگر وجود نداشت) |
| F6.2 | ایجاد دستی توسط منشی یا دکتر |
| F6.3 | ثبت سشن: بیمه پایه + مکمل، مبلغ ویزیت (پیش‌فرض یا دستی)، محاسبه خودکار کسورات |
| F6.4 | ثبت سرویس‌های انجام‌شده در سشن با پرسنل انجام‌دهنده |
| F6.5 | gate: `hasFeature('patient_records')` — بدون Basic+ → 403 |
| F6.6 | تاریخچه کامل مراجعات یک بیمار |
| F6.4 | ثبت سرویس‌های انجام‌شده در سشن با پرسنل انجام‌دهنده |
| F6.5 | gate: `hasFeature('patient_records')` — بدون Basic+ → 403 |
| F6.6 | تاریخچه کامل مراجعات یک بیمار |
#### محاسبه مبلغ نهایی سشن
```
visit_price_rials ← ادمین/دکتر تعیین می‌کند
- base_insurance_discount% ← بیمه پایه
@@ -371,6 +399,7 @@ visit_price_rials ← ادمین/دکتر تعیین می‌کند
```
#### Entities جدید
```
patient_records:
id, uuid
@@ -405,21 +434,24 @@ session_services:
```
#### API
| Method | Path | Permission | توضیح |
|--------|------|-----------|-------|
| `GET` | `/api/v1/patients` | clinic/doctor (basic+) | لیست بیماران با جستجو |
| `POST` | `/api/v1/patient` | clinic/doctor (basic+) | ایجاد پرونده دستی |
| `GET` | `/api/v1/patient/{uuid}` | clinic/doctor | جزئیات پرونده |
| `GET` | `/api/v1/patient/{uuid}/sessions` | clinic/doctor | لیست مراجعات |
| `POST` | `/api/v1/patient/{uuid}/session` | clinic/doctor | ثبت مراجعه جدید |
| `PATCH` | `/api/v1/session/{uuid}` | clinic/doctor | ویرایش مراجعه |
| Method | Path | Permission | توضیح |
| ------- | --------------------------------- | ---------------------- | --------------------- |
| `GET` | `/api/v1/patients` | clinic/doctor (basic+) | لیست بیماران با جستجو |
| `POST` | `/api/v1/patient` | clinic/doctor (basic+) | ایجاد پرونده دستی |
| `GET` | `/api/v1/patient/{uuid}` | clinic/doctor | جزئیات پرونده |
| `GET` | `/api/v1/patient/{uuid}/sessions` | clinic/doctor | لیست مراجعات |
| `POST` | `/api/v1/patient/{uuid}/session` | clinic/doctor | ثبت مراجعه جدید |
| `PATCH` | `/api/v1/session/{uuid}` | clinic/doctor | ویرایش مراجعه |
#### Frontend
- `PatientsPage.tsx` — لیست بیماران + جستجو
- `PatientDetailPage.tsx` — پرونده + تاریخچه مراجعات
- Modal ثبت سشن جدید (بیمه + ویزیت + سرویس‌ها)
#### فایل‌های جدید
- `src/Patient/Entity/PatientRecord.php`
- `src/Patient/Entity/PatientSession.php`
- `src/Patient/Entity/SessionService.php`
@@ -431,22 +463,25 @@ session_services:
### اپیک ۷ — داشبورد هوشمند (Smart Dashboard)
#### توضیح
داشبوردهای موجود (clinic/doctor/secretary در `docs/api/dashboard.md`) باید با چارت و فیلتر بازه زمانی تکمیل شوند.
#### نیازمندی‌های کارکردی
| کد | نیازمندی |
|----|---------|
| F7.1 | داشبورد ادمین: چارت درآمد + چارت نوبت‌ها + گزارش فروش پنل‌ها |
| کد | نیازمندی |
| ---- | ----------------------------------------------------------------------- |
| F7.1 | داشبورد ادمین: چارت درآمد + چارت نوبت‌ها + گزارش فروش پنل‌ها |
| F7.2 | داشبورد کلینیک/مطب: درآمد ماه جاری + بیماران منحصربه‌فرد + موجودی پیامک |
| F7.3 | فیلتر بازه زمانی: این هفته / این ماه / ۳ ماه / سفارشی |
| F7.4 | فیلتر نقش: منشی فقط نوبت‌ها را می‌بیند |
| F7.3 | فیلتر بازه زمانی: این هفته / این ماه / ۳ ماه / سفارشی |
| F7.4 | فیلتر نقش: منشی فقط نوبت‌ها را می‌بیند |
#### API موجود (نیاز به endpoint جدید ندارد)
`GET /api/v1/admin/dashboard/stats` | `/charts` | `/recent`
`GET /api/v1/dashboard/clinic` | `/doctor` | `/secretary`
#### تغییر مورد نیاز
- backend: اضافه کردن پارامترهای `from` و `to` به endpoint های charts
- frontend: `DashboardPage.tsx` — افزودن date range selector + نمودارها (Recharts/Chart.js)
@@ -454,15 +489,15 @@ session_services:
## اولویت‌بندی پیاده‌سازی
| اولویت | اپیک | وابستگی |
|--------|------|---------|
| ۱ | اپیک ۱ — Staff | پیش‌نیاز اپیک ۴ و ۶ |
| ۲ | اپیک ۲ — Subscription | پیش‌نیاز gate در اپیک ۳، ۴، ۶ |
| ۳ | اپیک ۳ — Secretary تکمیل | وابسته به اپیک ۲ |
| ۴ | اپیک ۴ — Services | وابسته به اپیک ۱ و ۲ |
| ۵ | اپیک ۵ — SMS Panel | مستقل |
| ۶ | اپیک ۶ — Patient Records | وابسته به اپیک ۱، ۲، ۴ |
| ۷ | اپیک ۷ — Dashboard | آخر — نیاز به داده واقعی |
| اولویت | اپیک | وابستگی |
| ------ | ------------------------ | ----------------------------- |
| ۱ | اپیک ۱ — Staff | پیش‌نیاز اپیک ۴ و ۶ |
| ۲ | اپیک ۲ — Subscription | پیش‌نیاز gate در اپیک ۳، ۴، ۶ |
| ۳ | اپیک ۳ — Secretary تکمیل | وابسته به اپیک ۲ |
| ۴ | اپیک ۴ — Services | وابسته به اپیک ۱ و ۲ |
| ۵ | اپیک ۵ — SMS Panel | مستقل |
| ۶ | اپیک ۶ — Patient Records | وابسته به اپیک ۱، ۲، ۴ |
| ۷ | اپیک ۷ — Dashboard | آخر — نیاز به داده واقعی |
---
@@ -488,15 +523,15 @@ sms_wallets sms_settings
## زیرساخت موجود قابل استفاده
| زیرساخت | مسیر | استفاده در فاز ۲ |
|---------|------|-----------------|
| Payment gateway | `src/Payment/` | پرداخت subscription + شارژ SMS wallet |
| `Payment.type='subscription'` | `Payment::TYPE_SUBSCRIPTION` | پرداخت پنل اشتراکی — موجود ✅ |
| SiteConfig (key-value) | `src/Config/Entity/SiteConfig.php` | `sms_price_rials`, `trial_enabled` |
| Categories (insurance) | `bundle='insurance_type'` | انتخاب بیمه در PatientSession |
| DoctorSecretary | `src/Secretary/Entity/` | اضافه کردن gate check |
| SmsLog/SmsTemplate | `src/Sms/Entity/` | ارسال پیامک‌های خودکار |
| WalletTransaction | `src/Settlement/Entity/` | الگوی مشابه برای SmsWallet |
| زیرساخت | مسیر | استفاده در فاز ۲ |
| ----------------------------- | ---------------------------------- | ------------------------------------- |
| Payment gateway | `src/Payment/` | پرداخت subscription + شارژ SMS wallet |
| `Payment.type='subscription'` | `Payment::TYPE_SUBSCRIPTION` | پرداخت پنل اشتراکی — موجود ✅ |
| SiteConfig (key-value) | `src/Config/Entity/SiteConfig.php` | `sms_price_rials`, `trial_enabled` |
| Categories (insurance) | `bundle='insurance_type'` | انتخاب بیمه در PatientSession |
| DoctorSecretary | `src/Secretary/Entity/` | اضافه کردن gate check |
| SmsLog/SmsTemplate | `src/Sms/Entity/` | ارسال پیامک‌های خودکار |
| WalletTransaction | `src/Settlement/Entity/` | الگوی مشابه برای SmsWallet |
---