21 KiB
PRD — ClinicPro Phase 2
تاریخ: ۲۴ خرداد ۱۴۰۵
نسخه: 1.0
وضعیت: Draft
خلاصه اجرایی
این سند نیازمندیهای فاز ۲ پلتفرم ClinicPro را پوشش میدهد. هدف: تبدیل پلتفرم از یک سیستم نوبتدهی ساده به یک سیستم مدیریت کلینیک کامل با پنلهای اشتراکی، پرونده بیمار، مدیریت پرسنل و پنل پیامکی.
وضعیت فعلی پروژه
| ماژول | وضعیت |
|---|---|
| Auth (OTP + JWT) | ✅ کامل |
| Doctor profile | ✅ کامل |
| Clinic management | ✅ کامل |
| Appointment booking | ✅ کامل |
| Secretary entity (DoctorSecretary) | ✅ موجود — نیاز به UI و permissions بیشتر |
| Payment gateway (Mellat, SEP) | ✅ کامل — برای نوبت + subscription |
| SMS (SmsLog, SmsTemplate) | ✅ زیرساخت موجود — نیاز به پنل کلینیک |
| Wallet / Settlement | ✅ کامل |
| Site config (SiteConfig key-value) | ✅ موجود |
| Staff (پرسنل) | ❌ موجود نیست |
| Panel subscription tiers | ❌ موجود نیست |
| Patient records (پرونده بیمار) | ❌ موجود نیست |
| Clinic services (خدمات) | ❌ موجود نیست |
| SMS panel per clinic | ❌ UI نیاز دارد |
اپیکها و قابلیتها
اپیک ۱ — پرسنل (Staff)
توضیح
مدیر کلینیک یا دکتر مستقل میتواند پرسنلی که نیازی به لاگین ندارند را ثبت کند. این پرسنل در سرویسدهی، سشنها و گزارشات استفاده میشوند.
نیازمندیهای کارکردی
- F1.1 — ایجاد / ویرایش / غیرفعالسازی پرسنل (حذف نرم — soft delete)
- F1.2 — فیلدهای پرسنل:
- نام و نام خانوادگی (اجباری)
- شماره تماس
- عنوان شغل (مثال: پرستار، منشی، تکنسین)
- آدرس
- کد ملی
- فعال / غیرفعال
- F1.3 — پرسنل به کلینیک یا مطب دکتر وابسته است (FK به clinic_id یا doctor_id)
- F1.4 — لیست پرسنل فقط در scope کلینیک/مطب فعال نمایش داده میشود
- F1.5 — در ایجاد سرویس، از لیست پرسنل انتخاب میشود
موجودیتهای جدید مورد نیاز
ClinicStaff:
- id, uuid
- clinic_id (FK → clinics) OR doctor_id (FK → doctors) [یکی از دو]
- full_name, phone, job_title, address, national_code
- active (bool, default: true)
- created_at, updated_at (Unix timestamp)
API endpoints
| Method | Path | Permission |
|---|---|---|
GET |
/api/v1/staff |
clinic/doctor |
POST |
/api/v1/staff |
clinic/doctor |
PATCH |
/api/v1/staff/{uuid} |
clinic/doctor |
PATCH |
/api/v1/staff/{uuid}/toggle |
clinic/doctor |
Frontend
- صفحه:
StaffPage.tsx— لیست با DataTable + Modal ایجاد/ویرایش - در Sidebar زیر بخش «تنظیمات»
اپیک ۲ — پنل اشتراکی (Subscription Tiers)
توضیح
سه سطح پنل وجود دارد. برای هر پنل، ادمین میتواند چند دوره زمانی با قیمتهای مختلف تعریف کند (مثلاً ۱ ماهه، ۶ ماهه، ۱۲ ماهه). کلینیک/دکتر دوره و پنل مورد نظر را انتخاب و پرداخت میکند.
پنلها
| سطح | نام | قابلیتها |
|---|---|---|
| 0 | Free | نوبتدهی + ۱ منشی — رایگان، بدون زمان انقضا |
| 1 | Basic | ۲ منشی + پرونده بیمار + مدیریت سرویسها |
| 2 | Professional | ۵ منشی + پرونده بیمار + مدیریت سرویسها |
دورههای اشتراک (مثال)
| دوره | مدت (ماه) | نوع | قیمت |
|---|---|---|---|
| تریال | 1 | trial — رایگان | ۰ ریال |
| ۱ ماهه | 1 | paid | ادمین تعیین میکند |
| ۳ ماهه | 3 | paid | ادمین تعیین میکند |
| ۶ ماهه | 6 | paid | ادمین تعیین میکند |
| ۱۲ ماهه | 12 | paid | ادمین تعیین میکند |
ادمین میتواند دورههای دلخواه اضافه، ویرایش یا غیرفعال کند.
دوره تریال
- تریال فقط برای پنل Basic فعال است
- هر کلینیک/دکتر فقط یک بار میتواند از تریال استفاده کند (بررسی در
ClinicSubscription) - تریال نیازی به پرداخت ندارد — مستقیم فعال میشود
- ادمین میتواند تریال را بهطور کلی فعال/غیرفعال کند (
trial_enabledدر SiteConfig) - بعد از انقضای تریال، سیستم به پنل Free بازمیگردد (نه حذف داده)
نیازمندیهای کارکردی
- F2.1 — ادمین برای هر ترکیب (پنل × دوره) یک قیمت تعریف میکند
- F2.2 — ادمین میتواند دورههای جدید اضافه کند (مثلاً ۲ ماهه) یا دورهای را غیرفعال کند
- F2.3 — کلینیک/دکتر پنل + دوره را انتخاب و از طریق gateway موجود (Mellat/SEP) پرداخت میکند
- F2.4 — پس از پرداخت موفق، اشتراک فعال میشود:
starts_at = now,expires_at = now + duration_months * 30 * 86400 - F2.5 — تمدید: اگر اشتراک فعال باشد،
starts_atاز تاریخ انقضای قبلی محاسبه میشود (نه از now) - F2.6 — gate:
hasFeature('patient_records')— بررسی اشتراک فعال و expired نبودن - F2.7 — گزارش فروش پنلها در داشبورد ادمین (تعداد، درآمد، بر اساس دوره و سطح)
- F2.8 — نمایش تاریخ انقضا و هشدار ۷ روز قبل به کلینیک/دکتر
- F2.9 — تریال Basic: فعالسازی رایگان یکبار — endpoint جداگانه
POST /api/v1/subscription/trial - F2.10 — بررسی استفاده قبلی از تریال قبل از فعالسازی (
used_trial: boolروی entity)
موجودیتهای جدید مورد نیاز
SubscriptionPlan:
- id, uuid
- name: 'free' | 'basic' | 'professional'
- level: int (0/1/2)
- max_secretaries: int (1/2/5)
- features: json { patient_records: bool, services: bool, sms_panel: bool }
- active: bool
- created_at, updated_at
SubscriptionPeriod:
- id, uuid
- plan_id (FK → subscription_plans)
- label: string (مثال: "۶ ماهه", "تریال ۱ ماهه")
- duration_months: int (1, 3, 6, 12, ...)
- price_rials: int (0 برای تریال)
- is_trial: bool (default: false — فقط یک دوره trial در Basic)
- active: bool
- sort_order: int (ترتیب نمایش)
- created_at, updated_at
ClinicSubscription:
- id, uuid
- entity_type: 'doctor' | 'clinic'
- entity_id: int
- plan_id (FK → subscription_plans)
- period_id (FK → subscription_periods)
- payment_id (FK → payments, nullable — برای تریال null است)
- is_trial: bool (کپی از period — برای گزارش راحتتر)
- starts_at: int (Unix timestamp)
- expires_at: int (Unix timestamp — null = بینهایت برای Free)
- created_at
وابستگی به Payment موجود
Payment.type = 'subscription'✅ (از قبل موجود)- Callback در
PaymentController::subscriptionCallback(): ایجادClinicSubscriptionپس از تأیید
API endpoints
| 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 — فعالسازی تریال Basic (رایگان، یکبار) |
POST |
/api/v1/subscription-payment |
clinic/doctor — { 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 «تریال» اگر is_trial باشد
- جدول مقایسه پنلها با انتخاب دوره (toggle)
- دکمه خرید → redirect به gateway
- اگر
- صفحه ادمین:
AdminSubscriptionPage.tsx- تب «پنلها»: ویرایش قیمت دورهها + مشخص کردن کدام دوره تریال است
- تب «گزارش»: فروش + تریالها بر اساس بازه زمانی
اپیک ۳ — منشی (Secretary) — تکمیل
توضیح
جدول doctor_secretaries و entity DoctorSecretary موجود است. نیاز به:
- محدودیت تعداد منشی بر اساس پنل
- صفحه فرانتاند کامل برای مدیریت منشیان و تنظیم دسترسیها
نیازمندیهای کارکردی
- F3.1 — بررسی سقف تعداد منشی قبل از ایجاد (free→1, basic→2, pro→5)
- F3.2 — UI کامل: لیست منشیان + اضافه کردن + ویرایش دسترسی + غیرفعالسازی
- F3.3 — پنل دسترسی: checkbox matrix برای هر منشی (permissions JSON موجود)
- نوبتها: view, create, cancel, update_status
- آدرسها: view, create, update, delete
- اطلاعات کلینیک: view, update
- بیمهها: view, create, update, delete
- F3.4 — منشی هرگز حذف نمیشود (soft delete با
active: false)
وضعیت فعلی
// DoctorSecretary.DEFAULT_PERMISSIONS — موجود
// API موجود: GET /api/v1/secretaries/{doctorUuid}, POST /api/v1/secretary, PATCH, DELETE
// صفحه SecretariesPage.tsx موجود — نیاز به بررسی کامل بودن
تغییرات مورد نیاز
- Backend: اضافه کردن بررسی سقف پنل در
SecretaryController::create() - Frontend: ویرایشگر گرافیکی permissions (checkbox matrix در Modal)
اپیک ۴ — سرویسهای کلینیک (Clinic Services)
توضیح
دسترسی فقط در پنل Basic و بالاتر. سرویسها در دو سطح تعریف میشوند: بخش و زیر بخش.
ساختار سرویس
ServiceSection (بخش — مثال: تزریقات، پانسمان)
└── ServiceItem (زیر بخش — مثال: سرم)
- section_id (FK)
- staff_id (FK → clinic_staff) — پرسنل انجامدهنده
- price (ریال)
- active
نیازمندیهای کارکردی
- F4.1 — CRUD بخشها (ServiceSection)
- F4.2 — CRUD زیر بخشها (ServiceItem) با انتخاب بخش و پرسنل
- F4.3 — قیمت هر زیر بخش قابل ویرایش
- F4.4 — gate:
hasFeature('services')— بدون Basic+ → 403
موجودیتهای جدید مورد نیاز
ServiceSection:
- id, uuid
- entity_type: 'doctor' | 'clinic', entity_id
- name
- active, created_at, updated_at
ServiceItem:
- id, uuid
- section_id (FK → service_sections)
- staff_id (FK → clinic_staff, nullable)
- name, price_rials
- active, created_at, updated_at
API endpoints
| Method | Path | Permission |
|---|---|---|
GET |
/api/v1/service-sections |
clinic/doctor |
POST |
/api/v1/service-section |
clinic/doctor (basic+) |
PATCH |
/api/v1/service-section/{uuid} |
clinic/doctor |
DELETE |
/api/v1/service-section/{uuid} |
clinic/doctor |
GET |
/api/v1/service-items/{sectionUuid} |
clinic/doctor |
POST |
/api/v1/service-item |
clinic/doctor (basic+) |
PATCH |
/api/v1/service-item/{uuid} |
clinic/doctor |
DELETE |
/api/v1/service-item/{uuid} |
clinic/doctor |
Frontend
- صفحه:
ServicesPage.tsxبا دو سطح accordion: بخشها و زیر بخشها
اپیک ۵ — پنل پیامکی (SMS Panel)
توضیح
زیرساخت SMS (SmsLog, SmsTemplate, SmsProvider) موجود است. باید پنل شارژی برای هر کلینیک/دکتر اضافه شود.
نیازمندیهای کارکردی
- F5.1 — کیف پول پیامک جداگانه از کیف پول مالی (یا همان wallet با type مجزا)
- F5.2 — شارژ کردن پنل پیامک از طریق gateway موجود
- F5.3 — ادمین تعرفه هر پیامک را در SiteConfig تعیین میکند (
sms_price_rials) - F5.4 — کسر خودکار هزینه از پنل پس از هر ارسال موفق
- F5.5 — تنظیمات ارسال پیامک (در صفحه تنظیمات کلینیک):
- یادآوری نوبت: فعال/غیرفعال + چند ساعت قبل
- پیام بعد از ویزیت: فعال/غیرفعال + متن قابل تنظیم
- F5.6 — گزارش لاگ پیامکهای هر کلینیک/دکتر
- F5.7 — گزارش ادمین: درآمد پیامکی، مصرف هر کلینیک
موجودیتهای جدید/تغییر یافته
SmsWallet (یا افزودن فیلد به Doctor/Clinic):
- entity_type, entity_id
- balance_rials (موجودی)
- created_at, updated_at
SmsSettings:
- entity_type, entity_id
- reminder_enabled (bool)
- reminder_hours_before (int)
- post_visit_enabled (bool)
- post_visit_text (text)
- updated_at
API endpoints
| Method | Path | Permission |
|---|---|---|
GET |
/api/v1/sms/wallet/balance |
clinic/doctor |
POST |
/api/v1/sms/wallet/charge |
clinic/doctor |
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
- تب «پیامک» در صفحه تنظیمات کلینیک/دکتر
- نمایش موجودی + دکمه شارژ + لاگ
اپیک ۶ — پرونده بیمار (Patient Records)
توضیح
دسترسی در پنل Basic+. پرونده بیمار به صورت خودکار پس از تأیید نوبت ایجاد میشود یا دستی توسط منشی/دکتر.
ساختار پرونده
PatientRecord (پرونده بیمار):
- entity_type, entity_id (کلینیک/مطب که پرونده به آن تعلق دارد)
- user_id (FK → users — بیمار)
- created_by (منشی/دکتر که ایجاد کرده)
- created_at
PatientSession (مراجعه/ویزیت):
- record_id (FK → patient_records)
- appointment_id (FK → appointments, nullable — اگر از نوبت)
- insurance_base_id (FK → categories, bundle='insurance_type')
- insurance_supplementary_id (FK → categories)
- visit_price_rials (مبلغ کل ویزیت)
- base_insurance_discount_percent (کسر بیمه پایه)
- supplementary_discount_percent (کسر بیمه مکمل)
- final_price_rials (مبلغ نهایی پس از کسورات)
- payment_method: 'cash' | 'card' | 'insurance' | 'pending'
- notes (text)
- created_at, updated_at
SessionService (سرویس انجامشده در یک مراجعه):
- session_id (FK → patient_sessions)
- service_item_id (FK → service_items)
- staff_id (FK → clinic_staff — پرسنل انجامدهنده)
- price_rials (قیمت در زمان ارائه)
- created_at
نیازمندیهای کارکردی
- F6.1 — ایجاد خودکار PatientRecord پس از تأیید appointment (اگر وجود ندارد)
- F6.2 — ایجاد دستی توسط منشی یا دکتر
- F6.3 — ثبت سشن جدید با:
- انتخاب بیمه پایه و تکمیلی (از categories)
- تعیین مبلغ ویزیت (از پیش تعیینشده یا قابل ویرایش)
- محاسبه خودکار مبلغ نهایی
- ثبت سرویسهای انجام شده (از ServiceItems)
- تعیین پرسنل انجامدهنده
- F6.4 — gate:
hasFeature('patient_records')— بدون Basic+ → 403 - F6.5 — تاریخچه مراجعات یک بیمار قابل نمایش
API endpoints
| 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 ثبت سشن جدید
اپیک ۷ — داشبورد هوشمند (Smart Dashboard)
توضیح
هر داشبورد (ادمین، کلینیک، مطب، منشی) باید چارتهای مناسب با فیلترهای role-based داشته باشد.
نیازمندیهای کارکردی
- F7.1 — داشبورد ادمین:
- چارت: درآمد پلتفرم (ماهانه، هفتگی)
- چارت: نوبتهای ثبتشده در بازه زمانی
- آمار: تعداد کلینیکها، دکترها، کاربران فعال
- گزارش پنلهای فروختهشده
- F7.2 — داشبورد کلینیک/مطب:
- نوبتهای امروز (موجود)
- درآمد ماه جاری
- تعداد بیماران منحصربهفرد
- موجودی پیامک
- F7.3 — فیلتر بازه زمانی در همه چارتها (این هفته / این ماه / ۳ ماه / سفارشی)
- F7.4 — فیلتر بر اساس نقش (منشی فقط نوبتها را میبیند)
اولویتبندی پیادهسازی
| اولویت | اپیک | دلیل |
|---|---|---|
| 1 | اپیک ۱ (Staff) | پیشنیاز اپیک ۴ و ۶ |
| 2 | اپیک ۲ (Subscription) | پیشنیاز gate checks |
| 3 | اپیک ۳ (Secretary - تکمیل) | وابسته به پنل |
| 4 | اپیک ۴ (Services) | پیشنیاز اپیک ۶ |
| 5 | اپیک ۵ (SMS Panel) | مستقل از بقیه |
| 6 | اپیک ۶ (Patient Records) | بیشترین وابستگی |
| 7 | اپیک ۷ (Dashboard) | آخر — نیاز به داده واقعی |
وابستگیهای فنی
وضعیت زیرساخت موجود و قابل استفاده
| زیرساخت | فایل | نحوه استفاده در فاز ۲ |
|---|---|---|
| Payment gateway | src/Payment/ |
پرداخت پنل اشتراکی و شارژ SMS |
| Wallet | src/Settlement/Entity/WalletTransaction.php |
بررسی مدل برای SMS wallet |
| SiteConfig | src/Config/Entity/SiteConfig.php |
ذخیره قیمت پنلها + تعرفه SMS |
| Categories (insurance) | bundle='insurance_type' |
انتخاب بیمه در سشن |
| DoctorSecretary | src/Secretary/Entity/DoctorSecretary.php |
افزودن بررسی سقف پنل |
| SmsLog/SmsTemplate | src/Sms/Entity/ |
زیرساخت ارسال موجود |
نکات معماری
- همه entityهای جدید از الگوی Unix timestamp استفاده میکنند
- همه controllerهای جدید از
BaseControllerارث میبرند - gate check برای features با یک helper در
BaseControllerیاSubscriptionServiceپیادهسازی شود entity_type+entity_idpattern (polymorphic) برای Staff، Services، SmsSettings، Patient Records
معیارهای پذیرش (Definition of Done)
برای هر اپیک:
- Entity + Migration ایجاد شده
- Controller + Repository + Service نوشته شده
- API endpoints تستپذیر در Swagger (
/api/doc) - Frontend page کامل با CRUD
- مستندات
docs/api/بهروزرسانی شده - بررسی gate/permission برای plan-gated features