Files
hamed df7a784701 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.
2026-06-15 14:18:25 +03:30

28 KiB
Raw Permalink Blame History

PRD — ClinicPro Phase 2

تاریخ: ۲۴ خرداد ۱۴۰۵ نسخه: 1.2 وضعیت: Draft


خلاصه اجرایی

فاز ۲ پلتفرم ClinicPro را از یک سیستم نوبت‌دهی ساده به یک سیستم مدیریت کلینیک کامل تبدیل می‌کند. شامل پنل‌های اشتراکی، مدیریت پرسنل، پرونده بیمار، سرویس‌های درمانی و پنل پیامکی اختصاصی برای هر کلینیک/مطب.


وضعیت فعلی پروژه

ماژول 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 وجود ندارد

اپیک‌ها


اپیک ۱ — پرسنل (Staff)

توضیح

مدیر کلینیک یا دکتر مستقل می‌تواند پرسنل کلینیک را ثبت کند. پرسنل حساب کاربری ندارند و نیازی به لاگین ندارند. در سرویس‌دهی، سشن‌ها و گزارشات به آن‌ها ارجاع می‌شود.

نیازمندی‌های کارکردی

کد نیازمندی
F1.1 ایجاد / ویرایش / غیرفعال‌سازی پرسنل — حذف سخت ممنوع (تاریخچه حفظ شود)
F1.2 فیلدها: نام و نام‌خانوادگی (اجباری)، شماره تماس، عنوان شغل، آدرس، کد ملی، وضعیت فعال
F1.3 پرسنل به entity_type + entity_id وابسته است (کلینیک یا مطب)
F1.4 لیست پرسنل فقط در scope کلینیک/مطب کاربر جاری نمایش داده می‌شود
F1.5 در ایجاد ServiceItem و SessionService از لیست پرسنل انتخاب می‌شود

Entity جدید

clinic_staff:
  id, uuid
  entity_type: 'doctor' | 'clinic'
  entity_id: int
  full_name: string (required)
  phone: string|null
  job_title: string|null
  address: text|null
  national_code: string(10)|null
  active: bool = true
  created_at, updated_at: int (Unix)

API

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
  • docs/api/staff.mdباید ایجاد شود

اپیک ۲ — پنل اشتراکی (Subscription Tiers)

توضیح

سه سطح پنل با قابلیت‌های متفاوت. ادمین برای هر پنل دوره‌های زمانی با قیمت مشخص تعریف می‌کند. کلینیک/دکتر دوره + پنل انتخاب کرده و پرداخت می‌کند.

سطوح پنل

Level Name منشی قابلیت‌های اضافه
0 Free ۱ منشی نوبت‌دهی — رایگان، بدون انقضا
1 Basic ۲ منشی پرونده بیمار + سرویس‌ها
2 Professional ۵ منشی پرونده بیمار + سرویس‌ها

دوره‌های اشتراک (مثال — ادمین تنظیم می‌کند)

نوع مدت قیمت
تریال ۱ ماه ۰ ریال — فقط برای Basic، یک‌بار
۱ ماهه ۱ ماه ادمین تعیین می‌کند
۳ ماهه ۳ ماه ادمین تعیین می‌کند
۶ ماهه ۶ ماه ادمین تعیین می‌کند
۱۲ ماهه ۱۲ ماه ادمین تعیین می‌کند

قوانین تریال

  • فقط برای پنل Basic
  • هر کلینیک/دکتر یک‌بار — بعد از استفاده، دکمه تریال نمایش داده نمی‌شود
  • بدون پرداخت — endpoint مستقل دارد
  • بعد از انقضا → برگشت به Free (داده‌ها حفظ می‌شوند)
  • ادمین می‌تواند تریال را کلاً غیرفعال کند (trial_enabled در SiteConfig)

نیازمندی‌های کارکردی

کد نیازمندی
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 گزارش فروش برای ادمین (تعداد، درآمد، بر اساس سطح و دوره)

Entities جدید

subscription_plans:
  id, uuid
  name: 'free' | 'basic' | 'professional'
  level: int (0/1/2)
  max_secretaries: int (1/2/5)
  features: json { patient_records, services, sms_panel }
  active: bool
  created_at, updated_at

subscription_periods:
  id, uuid
  plan_id → subscription_plans
  label: string ('۶ ماهه', 'تریال ۱ ماهه')
  duration_months: int
  price_rials: int  ← 0 برای تریال
  is_trial: bool = false
  active: bool
  sort_order: int
  created_at, updated_at

clinic_subscriptions:
  id, uuid
  entity_type: 'doctor' | 'clinic'
  entity_id: int
  plan_id → subscription_plans
  period_id → subscription_periods
  payment_id → payments  ← nullable (تریال = null)
  is_trial: bool
  starts_at: int
  expires_at: int  ← null = بی‌نهایت (Free)
  created_at

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 گزارش فروش + تریال‌ها

Frontend

  • SubscriptionPage.tsx:
    • بنر تریال اگر used_trial=false
    • وضعیت پنل فعال + تاریخ انقضا (شمسی) + badge «تریال»
    • جدول مقایسه پنل‌ها با انتخاب دوره
    • دکمه خرید → redirect به gateway
  • AdminSubscriptionPage.tsx:
    • تب «پنل‌ها»: ویرایش دوره‌ها و قیمت‌ها
    • تب «گزارش»: فروش بر اساس بازه زمانی

فایل‌های جدید

  • src/Subscription/Entity/SubscriptionPlan.php
  • src/Subscription/Entity/SubscriptionPeriod.php
  • src/Subscription/Entity/ClinicSubscription.php
  • src/Subscription/Controller/SubscriptionController.php
  • src/Subscription/Service/SubscriptionService.php
  • docs/api/subscription.mdباید ایجاد شود

اپیک ۳ — منشی (Secretary) — تکمیل

توضیح

Entity DoctorSecretary و API کامل موجود است (docs/api/secretary.md). باید:

  • محدودیت تعداد بر اساس پنل اعمال شود
  • UI مدیریت permissions تکمیل شود

نیازمندی‌های کارکردی

کد نیازمندی
F3.1 بررسی سقف پنل قبل از ایجاد: Free→1، Basic→2، Pro→5
F3.2 UI لیست منشی ها + اضافه‌کردن + ویرایش + غیرفعال‌سازی
F3.3 ویرایشگر permissions: checkbox matrix (موجود در DoctorSecretary.DEFAULT_PERMISSIONS)
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}


اپیک ۴ — سرویس‌های کلینیک (Clinic Services)

توضیح

دسترسی فقط در پنل Basic+. سرویس‌ها در دو سطح: بخش (مثلاً «تزریقات») و زیربخش (مثلاً «سرم»).

نیازمندی‌های کارکردی

کد نیازمندی
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
  entity_type: 'doctor' | 'clinic'
  entity_id: int
  name: string
  active: bool
  created_at, updated_at

service_items:
  id, uuid
  section_id → service_sections
  staff_id → clinic_staff  ← nullable
  name: string
  price_rials: int
  active: bool
  created_at, updated_at

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} حذف

Frontend

  • ServicesPage.tsx — accordion دو سطحی: بخش‌ها ← زیربخش‌ها

فایل‌های جدید

  • src/ClinicService/Entity/ServiceSection.php
  • src/ClinicService/Entity/ServiceItem.php
  • src/ClinicService/Controller/ClinicServiceController.php
  • docs/api/clinic-services.mdباید ایجاد شود

اپیک ۵ — پنل پیامکی (SMS Panel)

توضیح

زیرساخت SMS موجود است (SmsLog, SmsTemplate, SmsProvider در src/Sms/). باید:

  • کیف پول پیامک اختصاصی برای هر کلینیک/دکتر
  • تنظیمات ارسال پیامک (یادآوری، بعد از ویزیت)
  • گزارش لاگ برای کلینیک و ادمین

نیازمندی‌های کارکردی

کد نیازمندی
F5.1 کیف پول پیامک جدا از کیف پول مالی
F5.2 شارژ از طریق gateway موجود
F5.3 ادمین تعرفه هر پیامک را تعیین می‌کند (sms_price_rials در SiteConfig)
F5.4 کسر خودکار هزینه بعد از هر ارسال موفق
F5.5 تنظیمات: یادآوری نوبت (فعال/غیرفعال + چند ساعت قبل)
F5.6 تنظیمات: پیام بعد از ویزیت (فعال/غیرفعال + متن)
F5.7 گزارش لاگ پیامک‌های کلینیک/مطب
F5.8 گزارش ادمین: مصرف هر کلینیک + درآمد پیامکی

Entities جدید

sms_wallets:
  id
  entity_type: 'doctor' | 'clinic'
  entity_id: int
  balance_rials: int = 0
  created_at, updated_at

sms_settings:
  id
  entity_type: 'doctor' | 'clinic'
  entity_id: int
  reminder_enabled: bool = false
  reminder_hours_before: int = 2
  post_visit_enabled: bool = false
  post_visit_text: text|null
  updated_at

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 گزارش مصرف و درآمد

Frontend

  • تب «پیامک» در صفحه تنظیمات کلینیک/دکتر
  • نمایش موجودی + دکمه شارژ + لاگ + فرم تنظیمات

تأثیر بر فایل‌های موجود

  • docs/api/sms.mdبخش جدید wallet/settings اضافه شود

اپیک ۶ — پرونده بیمار (Patient Records)

توضیح

دسترسی فقط در پنل Basic+. پرونده به صورت خودکار پس از تأیید نوبت ایجاد می‌شود یا دستی توسط منشی/دکتر. هر مراجعه یک سشن است که شامل ویزیت + سرویس‌ها است.

نیازمندی‌های کارکردی

کد نیازمندی
F6.1 ایجاد خودکار PatientRecord بعد از تأیید appointment (اگر وجود نداشت)
F6.2 ایجاد دستی توسط منشی یا دکتر
F6.3 ثبت سشن: بیمه پایه + مکمل، مبلغ ویزیت (پیش‌فرض یا دستی)، محاسبه خودکار کسورات
F6.4 ثبت سرویس‌های انجام‌شده در سشن با پرسنل انجام‌دهنده
F6.5 gate: hasFeature('patient_records') — بدون Basic+ → 403
F6.6 تاریخچه کامل مراجعات یک بیمار

محاسبه مبلغ نهایی سشن

visit_price_rials           ← ادمین/دکتر تعیین می‌کند
- base_insurance_discount%  ← بیمه پایه
- supplementary_discount%   ← بیمه مکمل
+ service_items total       ← مجموع سرویس‌های انجام‌شده
= final_price_rials

Entities جدید

patient_records:
  id, uuid
  entity_type: 'doctor' | 'clinic'
  entity_id: int
  user_id → users  ← بیمار
  created_by_type: 'doctor' | 'secretary' | 'system'
  created_by_id: int
  created_at

patient_sessions:
  id, uuid
  record_id → patient_records
  appointment_id → appointments  ← nullable
  insurance_base_id → categories (bundle='insurance_type')  ← nullable
  insurance_supplementary_id → categories  ← nullable
  visit_price_rials: int
  base_insurance_discount_percent: float = 0
  supplementary_discount_percent: float = 0
  final_price_rials: int
  payment_method: 'cash' | 'card' | 'insurance' | 'pending'
  notes: text|null
  created_at, updated_at

session_services:
  id, uuid
  session_id → patient_sessions
  service_item_id → service_items
  staff_id → clinic_staff  ← nullable
  price_rials: int  ← قیمت در زمان ارائه (کپی از service_item)
  created_at

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 ویرایش مراجعه

Frontend

  • PatientsPage.tsx — لیست بیماران + جستجو
  • PatientDetailPage.tsx — پرونده + تاریخچه مراجعات
  • Modal ثبت سشن جدید (بیمه + ویزیت + سرویس‌ها)

فایل‌های جدید

  • src/Patient/Entity/PatientRecord.php
  • src/Patient/Entity/PatientSession.php
  • src/Patient/Entity/SessionService.php
  • src/Patient/Controller/PatientController.php
  • docs/api/patient.mdباید ایجاد شود

اپیک ۷ — داشبورد هوشمند (Smart Dashboard)

توضیح

داشبوردهای موجود (clinic/doctor/secretary در docs/api/dashboard.md) باید با چارت و فیلتر بازه زمانی تکمیل شوند.

نیازمندی‌های کارکردی

کد نیازمندی
F7.1 داشبورد ادمین: چارت درآمد + چارت نوبت‌ها + گزارش فروش پنل‌ها
F7.2 داشبورد کلینیک/مطب: درآمد ماه جاری + بیماران منحصربه‌فرد + موجودی پیامک
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)

اولویت‌بندی پیاده‌سازی

اولویت اپیک وابستگی
۱ اپیک ۱ — Staff پیش‌نیاز اپیک ۴ و ۶
۲ اپیک ۲ — Subscription پیش‌نیاز gate در اپیک ۳، ۴، ۶
۳ اپیک ۳ — Secretary تکمیل وابسته به اپیک ۲
۴ اپیک ۴ — Services وابسته به اپیک ۱ و ۲
۵ اپیک ۵ — SMS Panel مستقل
۶ اپیک ۶ — Patient Records وابسته به اپیک ۱، ۲، ۴
۷ اپیک ۷ — Dashboard آخر — نیاز به داده واقعی

نقشه Entity‌های جدید

clinic_staff ←──────────────── service_items ←─── session_services
     ↑                               ↑                     ↑
     │                         service_sections      patient_sessions
     │                               ↑                     ↑
     │                         entity_type/id        patient_records
     │                                                     ↑
subscription_plans ←── subscription_periods        entity_type/id
         └──────────── clinic_subscriptions
                              ↑
                        payment (موجود)

sms_wallets    sms_settings
(entity_type/id)

زیرساخت موجود قابل استفاده

زیرساخت مسیر استفاده در فاز ۲
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

معماری مشترک

  • همه entity‌های جدید: Unix timestamp (int) برای created_at, updated_at
  • همه controller‌های جدید از BaseController ارث می‌برند
  • پاسخ‌ها: $this->success() / $this->paginated() / $this->error()
  • polymorphic pattern: entity_type: 'doctor'|'clinic' + entity_id
  • gate check: SubscriptionService::hasFeature(string $feature): bool

Definition of Done (هر اپیک)

  • Migration ایجاد و اجرا شده
  • Entity + Repository + Service نوشته شده
  • Controller با همه endpoints کامل شده
  • Type check frontend بدون خطا (yarn dev)
  • API قابل تست در Swagger (/api/doc)
  • فایل docs/api/xxx.md ایجاد یا بروزرسانی شده