Files
clinicpro/docs/PROJECT.md
T

31 KiB
Raw Blame History

ClinicPro — مستندات کامل پروژه

تاریخ آخرین به‌روزرسانی: ۱۴۰۵/۰۳/۱۹ | نسخه Symfony: 7.4 | PHP: ≥ 8.2


فهرست مطالب

  1. معرفی پروژه
  2. تکنولوژی Stack
  3. ساختار دایرکتوری
  4. راه‌اندازی محیط توسعه
  5. متغیرهای محیطی
  6. پایگاه داده — موجودیت‌ها
  7. API Endpoints
  8. امنیت و احراز هویت
  9. پنل ادمین React
  10. Frontend Build
  11. دستورات Console
  12. Migrations
  13. سرویس‌های خارجی

۱. معرفی پروژه

ClinicPro یک سیستم جامع مدیریت کلینیک و نوبت‌دهی پزشکی است که شامل:

  • API Backend: Symfony 7.4 (REST API + JWT Auth)
  • Admin Panel: React 19 + TypeScript (SPA داخل Symfony)
  • ویژگی‌های اصلی:
    • مدیریت پزشکان، کلینیک‌ها و کاربران
    • سیستم نوبت‌دهی با مدیریت اسلات زمانی
    • درگاه پرداخت (ملت و سپ)
    • سیستم کیف پول و تسویه‌حساب
    • نمایندگان (Representation) با کمیسیون
    • احراز هویت OTP + رمز عبور
    • مدیریت منشی با دسترسی‌های دانه‌ای
    • ارسال پیامک (KaveNegar / Rangineh)
    • امتیاز و نظرات پزشکان
    • بلاگ

۲. تکنولوژی Stack

Backend

لایه تکنولوژی
Framework Symfony 7.4
PHP >= 8.2
ORM Doctrine ORM 3.6
Auth JWT (lexik/jwt-authentication-bundle)
Queue Symfony Messenger
Cache/Session Redis
Database MySQL
API Docs NelmioApiDocBundle (Swagger)
Rate Limiting Symfony Rate Limiter

Frontend (Admin)

لایه تکنولوژی
Framework React 19 + TypeScript
Routing React Router DOM v7
Styling Tailwind CSS v4
State (server) TanStack Query v5
State (client) Zustand v5
Forms React Hook Form + Zod
Icons Heroicons v2
Toast Sonner
Tables TanStack Table v8
Build Webpack Encore (Symfony UX React)

۳. ساختار دایرکتوری

clinic-pro-symfony/
├── assets/
│   ├── admin/                    ← React Admin SPA
│   │   ├── index.tsx             ← Entry point
│   │   ├── App.tsx               ← Router + PrivateRoute
│   │   ├── styles.css            ← Tailwind CSS v4
│   │   ├── components/
│   │   │   └── layout/
│   │   │       ├── AdminLayout.tsx
│   │   │       ├── Sidebar.tsx
│   │   │       └── Topbar.tsx
│   │   ├── pages/
│   │   │   ├── LoginPage.tsx
│   │   │   └── DashboardPage.tsx
│   │   ├── stores/
│   │   │   ├── authStore.ts      ← Zustand JWT store
│   │   │   └── uiStore.ts        ← Sidebar state
│   │   ├── hooks/
│   │   └── lib/
│   ├── app.js                    ← Symfony main entry
│   ├── styles/app.css
│   └── react/controllers/        ← UX React controllers
│
├── config/
│   ├── packages/
│   │   ├── security.yaml         ← Firewalls + ACL
│   │   ├── doctrine.yaml
│   │   ├── lexik_jwt_authentication.yaml
│   │   ├── messenger.yaml
│   │   ├── rate_limiter.yaml
│   │   └── webpack_encore.yaml
│   └── routes/
│       ├── security.yaml
│       └── nelmio_api_doc.yaml
│
├── migrations/                   ← 16 Doctrine migrations
│
├── public/
│   ├── index.php
│   └── build/                    ← Webpack output
│
├── src/
│   ├── Admin/Controller/         ← SPA catch-all
│   ├── Appointment/              ← نوبت‌دهی
│   ├── Auth/                     ← احراز هویت
│   ├── Blog/                     ← بلاگ
│   ├── Category/                 ← دسته‌بندی‌ها
│   ├── Clinic/                   ← کلینیک‌ها
│   ├── Doctor/                   ← پزشکان
│   ├── Insurance/                ← بیمه
│   ├── Payment/                  ← پرداخت
│   ├── Rating/                   ← امتیاز و نظرات
│   ├── Representation/           ← نمایندگان
│   ├── Secretary/                ← منشی‌ها
│   ├── Settlement/               ← تسویه‌حساب
│   ├── Shared/                   ← زیرساخت مشترک
│   ├── Sms/                      ← پیامک
│   ├── UserProfile/              ← پروفایل کاربر
│   └── Kernel.php
│
├── tests/
├── webpack.config.js
├── tsconfig.json
├── postcss.config.js
├── composer.json
├── package.json
└── .env

۴. راه‌اندازی محیط توسعه

پیش‌نیازها

  • ddev نصب شده
  • Docker Desktop

مراحل اجرا

# ۱. کلون پروژه
git clone <repo-url>
cd clinic-pro-symfony

# ۲. راه‌اندازی ddev
ddev start

# ۳. نصب PHP packages
ddev composer install

# ۴. ساخت JWT keys
ddev exec php bin/console lexik:jwt:generate-keypair

# ۵. اجرای migrations
ddev exec php bin/console doctrine:migrations:migrate --no-interaction

# ۶. نصب npm packages
npm install --legacy-peer-deps

# ۷. Build frontend (dev)
npm run dev

# ۸. یا watch mode
npm run watch

دسترسی

سرویس آدرس
Admin Panel https://clinic-pro.ddev.site/admin
API https://clinic-pro.ddev.site/api/v1
Swagger UI https://clinic-pro.ddev.site/api/doc
Health Check https://clinic-pro.ddev.site/health

اطلاعات ادمین پیش‌فرض

فیلد مقدار
موبایل 09120671713
رمز عبور admin1234
نقش ROLE_ADMIN

۵. متغیرهای محیطی

فایل .env — کلیدها (مقادیر در .env.local تنظیم می‌شوند):

APP_ENV=dev|prod
APP_SECRET=                      # کلید امنیتی Symfony
APP_SHARE_DIR=                   # مسیر shared assets
DEFAULT_URI=                     # آدرس پایه سایت (مثلاً https://clinic-pro.ddev.site)

DATABASE_URL=                    # DSN پایگاه داده MySQL

JWT_SECRET_KEY=                  # مسیر کلید خصوصی JWT
JWT_PUBLIC_KEY=                  # مسیر کلید عمومی JWT
JWT_PASSPHRASE=                  # رمز کلید JWT

CORS_ALLOW_ORIGIN=               # آدرس‌های مجاز CORS

MESSENGER_TRANSPORT_DSN=         # DSN صف پیام (Redis)
REDIS_URL=                       # آدرس Redis

REFRESH_TOKEN_TTL=2592000        # عمر refresh token (ثانیه) = ۳۰ روز
OTP_TTL=1200                     # عمر کد OTP (ثانیه) = ۲۰ دقیقه

# SMS - KaveNegar
KAVENEGAR_API_KEY=
KAVENEGAR_SENDER=
# SMS - Rangineh
RANGINEH_API_KEY=
RANGINEH_SENDER=
SMS_PROVIDER=kavenegar|rangineh  # ارائه‌دهنده فعال

# File Upload
MAX_FILE_SIZE_BYTES=5242880      # حداکثر حجم فایل (۵ مگابایت)
UPLOAD_DIR=                      # مسیر ذخیره فایل‌ها

ALLOWED_FRONTEND_HOSTS=          # هاست‌های مجاز برای redirect پرداخت

# Payment - Mellat Bank
MELLAT_TERMINAL_ID=
MELLAT_USERNAME=
MELLAT_PASSWORD=

# Payment - SEP (Saman)
SEP_TERMINAL_ID=

APP_BASE_URL=                    # آدرس پایه برای callback پرداخت

۶. پایگاه داده — موجودیت‌ها

جداول پایگاه داده

جدول Entity توضیح
users Auth\Entity\User کاربران سیستم
doctors Doctor\Entity\Doctor پروفایل پزشکان
doctor_addresses Doctor\Entity\DoctorAddress آدرس مطب
clinics Clinic\Entity\Clinic کلینیک‌ها
categories Category\Entity\Category دسته‌بندی‌ها
appointments Appointment\Entity\Appointment نوبت‌ها
weekly_schedules Appointment\Entity\WeeklySchedule برنامه هفتگی
date_overrides Appointment\Entity\DateOverride تغییر برنامه خاص
holidays Appointment\Entity\Holiday تعطیلات
payments Payment\Entity\Payment پرداخت‌ها
settlements Settlement\Entity\Settlement درخواست تسویه
wallet_transactions Settlement\Entity\WalletTransaction تراکنش کیف پول
representations Representation\Entity\Representation نمایندگان
doctor_secretaries Secretary\Entity\DoctorSecretary منشی‌های پزشک
comments Rating\Entity\Comment نظرات
rates Rating\Entity\Rate امتیازها
likes Rating\Entity\Like لایک نظرات
blogs Blog\Entity\Blog مقالات بلاگ
sms_templates Sms\Entity\SmsTemplate قالب‌های پیامک
sms_logs Sms\Entity\SmsLog لاگ ارسال پیامک
profiles UserProfile\Entity\UserProfile پروفایل پزشکی کاربر
doctor_insurances Insurance\Entity\DoctorInsurance بیمه‌های پزشک

جداول Join (ManyToMany)

جدول رابطه
doctor_specialties Doctor ↔ Category (specialty)
doctor_expertise Doctor ↔ Category (expertise)
doctor_states Doctor ↔ Category (state)
doctor_cities Doctor ↔ Category (city)
clinic_doctors Clinic ↔ Doctor
clinic_specialties Clinic ↔ Category
clinic_services Clinic ↔ Category
clinic_insurances Clinic ↔ Category

User (users)

id              INT PK AUTO_INCREMENT
uuid            VARCHAR(36) UNIQUE
mobile_number   VARCHAR(20) UNIQUE             ← شناسه ورود
password_hash   VARCHAR(255) nullable
email           VARCHAR(100) nullable
real_name       VARCHAR(100) nullable
roles           JSON                           ← ['ROLE_USER', 'ROLE_ADMIN', ...]
status          SMALLINT default:1             ← 1=active, 0=inactive
created_at      INT (unix timestamp)
updated_at      INT (unix timestamp)

نقش‌های موجود: ROLE_USER | ROLE_ADMIN | ROLE_DOCTOR | ROLE_CLINIC | ROLE_REPRESENTATION | ROLE_SECRETARY


Doctor (doctors)

id                          INT PK
uuid                        VARCHAR(36) UNIQUE
user_id                     INT FK → users
name                        VARCHAR(255)
gender                      VARCHAR(10) nullable
medical_system_code         VARCHAR(25) nullable
mobile_number               VARCHAR(15) nullable
activity_time               INT nullable          ← مدت ویزیت (دقیقه)
degree                      VARCHAR(30) nullable  ← general/specialist/subspecialist
info                        TEXT nullable
images                      JSON nullable
doctor_rate                 FLOAT default:3.5
doctor_rate_percentage      FLOAT default:60.0   ← سهم پزشک از پرداخت (%)
active_doctor_appointment   BOOL default:true
representation_id           INT nullable
created_at / updated_at     INT

Clinic (clinics)

id                INT PK
uuid              VARCHAR(36) UNIQUE
user_id           INT FK → users
name              VARCHAR(255) nullable
info              TEXT nullable
address           TEXT nullable
telephone         VARCHAR(50) nullable
is_24_7           BOOL default:false
working_days      VARCHAR(255) nullable
latitude/longitude FLOAT nullable
city_id           INT nullable → categories
state_id          INT nullable → categories
representation_id INT nullable
images_clinic     JSON nullable
clinic_logo       JSON nullable

Appointment (appointments)

id          INT PK
uuid        VARCHAR(36) UNIQUE
doctor_id   INT FK → doctors
user_id     INT FK → users
slot_start  INT (unix timestamp)
slot_end    INT (unix timestamp)
status      VARCHAR(30)
note        VARCHAR(255) nullable
version     INT (optimistic locking)

وضعیت‌های نوبت:

waiting_for_payment  → در انتظار پرداخت
reserved             → رزرو شده
checked_in           → ورود به مطب
waiting              → در صف انتظار
in_progress          → در حال ویزیت
visited              → ویزیت شده
completed            → تکمیل شده
cancelled_by_doctor  → لغو توسط پزشک
cancelled_by_user    → لغو توسط کاربر
auto_cancel_unpaid   → لغو خودکار (پرداخت‌نشده)
no_show              → غیبت

Payment (payments)

id              INT PK
uuid            VARCHAR(36) UNIQUE
order_id        VARCHAR(64) UNIQUE
user_id         INT FK
appointment_id  INT FK nullable
amount_rials    INT
status          VARCHAR(30)   ← pending|success|failed|refunded
gateway         VARCHAR(20)   ← mellat|sep
type            VARCHAR(30)   ← appointment|subscription
gateway_token   VARCHAR(255) nullable
reference_id    VARCHAR(255) nullable
frontend_address VARCHAR(500) nullable
callback_ip     VARCHAR(45) nullable

Category (categories)

id                INT PK
uuid              VARCHAR(36) UNIQUE
bundle            VARCHAR(32)    ← نوع دسته‌بندی
label             VARCHAR(255) nullable
status            SMALLINT default:1
parent_id         INT nullable   ← برای city → state
weight            INT default:0
representation_id INT nullable

نوع‌های bundle:

state                  ← استان‌ها
city                   ← شهرها (parent_id = state)
specially_doctor       ← تخصص پزشک
doctor_services        ← خدمات پزشک
insurance_type         ← نوع بیمه پایه
supplementary_insurance ← بیمه تکمیلی
tag                    ← تگ بلاگ

Settlement + Wallet

-- settlements
uuid, user_id, amount_rials, status(pending|approved|rejected|paid),
bank_account(JSON), admin_note, reviewed_by, reviewed_at

-- wallet_transactions
user_id, amount, type(credit|debit), balance_after, description

DoctorSecretary

uuid
doctor_id    FK → doctors
secretary_id FK → users
permission   JSON:
  {
    "appointments": { "view": true, "create": true, "cancel": false, "update_status": false },
    "addresses":    { "view": true, "create": false, "update": false, "delete": false },
    "clinic_info":  { "view": true, "update": false },
    "insurances":   { "view": true, "create": false, "update": false, "delete": false }
  }
active       BOOL

۷. API Endpoints

Base URL: https://clinic-pro.ddev.site


🔐 Auth (/api/v1/user/ & /oauth/)

Method Path Auth توضیح
POST /api/v1/user/login Public ورود با موبایل و رمز → JWT + refresh
POST /api/v1/user/send-code Public ارسال کد OTP به موبایل
POST /api/v1/user/verify-code Public تأیید کد OTP
POST /api/v1/user/register Public ثبت‌نام کاربر جدید
POST /oauth/token Public دریافت JWT با موبایل (mobile grant)
POST /oauth/token/refresh Public تمدید JWT با refresh token
GET /oauth/userinfo اطلاعات کاربر جاری
POST /oauth/logout خروج و ابطال refresh token
GET /session/token Public دریافت CSRF session token

درخواست Login:

POST /api/v1/user/login
{ "mobile_number": "09120671713", "password": "admin1234" }

پاسخ موفق:

{
  "access_token": "eyJ...",
  "refresh_token": "8e75...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token_expires_in": 2592000
}

👥 Users

Method Path Auth توضیح
GET /oauth/userinfo پروفایل کاربر جاری
DELETE /api/v1/user/{id} ADMIN حذف کاربر

🩺 Doctors

Method Path Auth توضیح
GET /api/v1/doctors Public لیست پزشکان (فیلتر + pagination)
GET /api/v1/doctor/{uuid} Public جزئیات پزشک
POST /api/v1/doctor ایجاد پروفایل پزشک
PATCH /api/v1/doctor/{uuid} به‌روزرسانی پروفایل
DELETE /api/v1/doctor/{uuid} ADMIN حذف پزشک
POST /file/upload/clinic_pro/doctor/field_image آپلود تصویر
GET /api/v1/clinic-pro/doctor-addresses/{doctorId} Public لیست آدرس‌ها
POST /api/v1/clinic-pro/doctor-address افزودن آدرس
PATCH /api/v1/clinic-pro/doctor-address/{id} ویرایش آدرس
DELETE /api/v1/clinic-pro/doctor-address/{id} حذف آدرس

🏥 Clinics

Method Path Auth توضیح
GET /api/v1/clinics Public لیست کلینیک‌ها
GET /api/v1/clinic/{uuid} Public جزئیات کلینیک
POST /api/v1/clinic ایجاد کلینیک
PATCH /api/v1/clinic/{uuid} ویرایش کلینیک
GET /api/v1/clinic/doctor-list/{clinicUuid} Public پزشکان کلینیک
POST /file/upload/clinic_pro/clinic/field_image_clinic آپلود تصویر
POST /file/upload/clinic_pro/clinic/field_clinic_logo آپلود لوگو

📅 Appointments

Method Path Auth توضیح
GET /api/v1/appointment-slots Public اسلات‌های خالی پزشک
POST /api/v1/appointment رزرو نوبت
GET /api/v1/appointment/{uuid} جزئیات نوبت
PATCH /api/v1/appointment/{uuid}/status تغییر وضعیت نوبت
GET /api/v1/appointments/doctor/{doctorUuid} نوبت‌های پزشک
GET /api/v1/appointments/user نوبت‌های کاربر

تنظیمات نوبت‌دهی:

Method Path توضیح
POST /api/v1/appointment-settings/weekly-schedule برنامه هفتگی
POST /api/v1/appointment-settings/date-override تغییر برنامه خاص
POST /api/v1/appointment-settings/holidays ثبت تعطیلات

💳 Payments

Method Path Auth توضیح
POST /api/v1/payment/appointment شروع پرداخت نوبت
GET/POST /api/v1/payment/callback/{gateway} Public (IP) callback درگاه
GET /api/v1/payment/{uuid} وضعیت پرداخت
POST /api/v1/subscription-payment پرداخت اشتراک

پارامتر {gateway}: mellat یا sep


🏦 Settlement & Wallet

Method Path Auth توضیح
GET /api/v1/wallet/balance موجودی کیف پول
GET /api/v1/wallet/transactions تاریخچه تراکنش‌ها
POST /api/v1/settlement درخواست تسویه
GET /api/v1/settlement لیست درخواست‌ها
GET /api/v1/settlement/{uuid} جزئیات درخواست
POST /api/v1/settlement/{uuid}/approve ADMIN تأیید تسویه
POST /api/v1/settlement/{uuid}/reject ADMIN رد تسویه

Ratings & Comments

Method Path Auth توضیح
POST /api/v1/rate امتیاز به پزشک (۱-۵)
GET /api/v1/rate/{doctorUuid} Public میانگین امتیاز پزشک
POST /api/v1/comment ثبت نظر
GET /api/v1/comments/{doctorUuid} Public نظرات تأییدشده
DELETE /api/v1/comment/{uuid} حذف نظر
POST /api/v1/like/{commentUuid} لایک/آنلایک نظر
GET /api/v1/admin/comments/pending ADMIN نظرات در انتظار
POST /api/v1/admin/comment/{uuid}/approve ADMIN تأیید نظر
POST /api/v1/admin/comment/{uuid}/reject ADMIN رد نظر

🤝 Representations (نمایندگان)

Method Path Auth توضیح
POST /api/v1/representation ADMIN ایجاد نماینده
GET /api/v1/representation/{uuid} جزئیات نماینده
PATCH /api/v1/representation/{uuid} ویرایش
DELETE /api/v1/representation/{uuid} ADMIN حذف
GET /api/v1/representation/{uuid}/dashboard/monthly آمار ماهانه (شمسی)
GET /api/v1/representation/{uuid}/dashboard/yearly آمار سالانه

🔐 Secretaries (منشی‌ها)

Method Path Auth توضیح
POST /api/v1/secretary ایجاد منشی
GET /api/v1/secretary/{uuid} جزئیات
PATCH /api/v1/secretary/{uuid} ویرایش دسترسی‌ها
DELETE /api/v1/secretary/{uuid} حذف
GET /api/v1/secretaries/{doctorUuid} لیست منشی‌های پزشک

📱 SMS

Method Path Auth توضیح
GET /api/v1/admin/sms/templates ADMIN لیست قالب‌ها
POST /api/v1/sms/template ADMIN ایجاد قالب
PATCH /api/v1/sms/template/{uuid} ADMIN ویرایش قالب
POST /api/v1/sms/template/{uuid}/submit ADMIN ارسال برای تأیید
POST /api/v1/admin/sms/template/{uuid}/approve ADMIN تأیید قالب
POST /api/v1/admin/sms/template/{uuid}/reject ADMIN رد قالب
POST /api/v1/sms/send ADMIN ارسال پیامک مستقیم
POST /api/v1/sms/send-template ADMIN ارسال با قالب

🗂 Categories

Method Path Auth توضیح
GET /api/v1/categorys/state Public لیست استان‌ها
GET /api/v1/categorys/city Public لیست شهرها (?state_id=X)
GET /api/v1/categorys/specially_doctor Public تخصص‌های پزشکی
GET /api/v1/categorys/doctor_services Public خدمات پزشکی
GET /api/v1/categorys/insurance_type Public انواع بیمه پایه
GET /api/v1/categorys/supplementary_insurance Public بیمه تکمیلی
GET /api/v1/categorys/tag Public تگ‌های بلاگ
POST /api/v1/category ADMIN ایجاد دسته‌بندی
PATCH /api/v1/category/{id} ADMIN ویرایش
DELETE /api/v1/category/{id} ADMIN حذف

📝 Blog

Method Path Auth توضیح
GET /api/v1/blogs Public لیست مقالات منتشرشده
GET /api/v1/blog/{slug} Public مقاله با slug یا uuid
POST /api/v1/blog ADMIN ایجاد مقاله
PATCH /api/v1/blog/{uuid} ADMIN ویرایش
DELETE /api/v1/blog/{uuid} ADMIN حذف
POST /file/upload/clinic_pro/blog/field_image ADMIN آپلود تصویر مقاله

❤️ Health

Method Path توضیح
GET /health بررسی وضعیت DB و Redis

۸. امنیت و احراز هویت

جریان احراز هویت

[Client] → POST /api/v1/user/login
           { mobile_number, password }

           ↓ PasswordAuthenticator

[Symfony] → Rate Limit check (IP)
          → findByMobile()
          → verify password_hash
          → check isStaff() (ROLE_ADMIN or ROLE_DOCTOR or ROLE_CLINIC)

           ↓ موفق

[Response] → {
               access_token: "eyJ...",   // ← JWT، عمر: 1 ساعت
               refresh_token: "8e75...", // ← در DB کش، عمر: 30 روز
               expires_in: 3600
             }

JWT Token Payload

{
  "iat": 1781031215,
  "exp": 1781034815,
  "roles": ["ROLE_ADMIN", "ROLE_USER"],
  "username": "09120671713"
}

استفاده از Token

Authorization: Bearer eyJ...

Refresh Token

POST /oauth/token/refresh
{ "refresh_token": "8e75..." }

Firewalls

dev              → مسیرهای profiler/assets (no security)
health           → /health (no security)
public_endpoints → مسیرهای عمومی API (no security)
payment_callback → callback درگاه (no security)
api              → ^/(api|oauth)/ — JWT authenticator

نقش‌ها و دسترسی‌ها

نقش دسترسی
ROLE_USER کاربر عادی — رزرو نوبت، پرداخت
ROLE_DOCTOR پزشک — مدیریت پروفایل و نوبت‌ها
ROLE_CLINIC مدیر کلینیک
ROLE_REPRESENTATION نماینده — آمار و کیف پول
ROLE_SECRETARY منشی — بر اساس permissions JSON
ROLE_ADMIN ادمین کامل — تمام endpoint‌ها

Rate Limiting

# config/packages/rate_limiter.yaml
login:      5 تلاش در دقیقه (per IP)
send_code:  3 درخواست در 5 دقیقه (per IP)

۹. پنل ادمین React

آدرس: https://clinic-pro.ddev.site/admin

نحوه کار

[Browser] GET /admin/**
    ↓
[Symfony] AdminController::index()
    ↓
[Twig] templates/admin/index.html.twig
    ↓ (HTML shell + Webpack assets)
[React] mounts در #admin-root
    ↓
[React Router] مسیریابی client-side

مسیرهای React

مسیر صفحه Auth
/admin/login LoginPage عمومی
/admin/dashboard DashboardPage
/admin/users (در حال توسعه)
/admin/doctors (در حال توسعه)
/admin/clinics (در حال توسعه)
/admin/appointments (در حال توسعه)
/admin/payments (در حال توسعه)
/admin/settlements (در حال توسعه)
/admin/comments (در حال توسعه)
/admin/ratings (در حال توسعه)
/admin/sms (در حال توسعه)
/admin/categories (در حال توسعه)
/admin/blogs (در حال توسعه)
/admin/representations (در حال توسعه)
/admin/secretaries (در حال توسعه)

Auth Guard

// اگر کاربر لاگین نباشد → redirect به /admin/login
// اگر کاربر لاگین باشد و /admin/login باز کند → redirect به /admin/dashboard

JWT ذخیره‌سازی

// Zustand + localStorage (با persist middleware)
// کلید: 'clinicpro-auth'
{
  token: string | null,         // access_token
  refreshToken: string | null,
  isAuthenticated: boolean
}

طراحی (Design System)

/* رنگ اصلی */
--color-primary-500: #8b5cf6;  /* بنفش */
--color-bg-sidebar: #0f172a;   /* dark navy */
--color-bg-body: #f1f5f9;      /* خاکستری روشن */

/* فونت */
font-family: "Vazirmatn", "Inter", sans-serif;
direction: rtl;

۱۰. Frontend Build

دستورات npm

npm run dev        # build یک‌بار (dev)
npm run watch      # build + watch
npm run build      # build production (minified + hashed)
npm run dev-server # webpack dev server (HMR)

فایل‌های خروجی

public/build/
├── runtime.js          ← webpack runtime
├── admin.js            ← React Admin bundle
├── admin.css           ← Tailwind CSS
├── app.js              ← Symfony main bundle
├── vendors-*.js        ← کتابخانه‌های مشترک
└── manifest.json       ← نقشه فایل‌ها

تنظیمات TypeScript (tsconfig.json)

{
  "compilerOptions": {
    "target": "ES2020",
    "jsx": "react-jsx",
    "strict": true,
    "baseUrl": ".",
    "paths": { "@/*": ["assets/admin/*"] }
  }
}

تنظیمات PostCSS (postcss.config.js)

module.exports = {
  plugins: { '@tailwindcss/postcss': {} }
};

۱۱. دستورات Console

دستور موجود

# لغو خودکار نوبت‌های منقضی‌شده
ddev exec php bin/console app:cancel-expired-appointments

# توضیح: نوبت‌هایی که slot_start آنها گذشته و هنوز pending هستند
# را به وضعیت auto_cancel_unpaid تغییر می‌دهد
# اجرا: از طریق cron job (مثلاً هر ۱۵ دقیقه)

دستورات Symfony مفید

# مشاهده همه route‌ها
ddev exec php bin/console debug:router

# پاک کردن کش
ddev exec php bin/console cache:clear

# اجرای migrations
ddev exec php bin/console doctrine:migrations:migrate

# هش کردن پسورد
ddev exec php bin/console security:hash-password "your_password"

# تولید JWT key
ddev exec php bin/console lexik:jwt:generate-keypair

۱۲. Migrations

تعداد: ۱۶ migration
آخرین نسخه: Version20260609140423

# مشاهده وضعیت
ddev exec php bin/console doctrine:migrations:status

# اجرای migrations جدید
ddev exec php bin/console doctrine:migrations:migrate --no-interaction

# ساخت migration جدید
ddev exec php bin/console doctrine:migrations:diff

۱۳. سرویس‌های خارجی

درگاه‌های پرداخت

درگاه Provider متغیرها
بانک ملت MellatGateway MELLAT_TERMINAL_ID, MELLAT_USERNAME, MELLAT_PASSWORD
سامان (SEP) SepGateway SEP_TERMINAL_ID

IP‌های مجاز callback: در ALLOWED_FRONTEND_HOSTS تنظیم می‌شود.


SMS Providers

ارائه‌دهنده Provider Class انتخاب
کاوه‌نگار KavehNegarProvider SMS_PROVIDER=kavenegar
رنگینه RanginehProvider SMS_PROVIDER=rangineh

Redis

  • صف پیام (Symfony Messenger)
  • کش OTP codes
  • کش Refresh Tokens
  • Rate limiter storage

JWT Keys

config/jwt/private.pem   ← کلید خصوصی (در .gitignore)
config/jwt/public.pem    ← کلید عمومی (در .gitignore)

خلاصه آماری

معیار تعداد
Domain modules ۱۵
PHP Controllers ۱۷
API Endpoints ۱۳۰+
Doctrine Entities ۲۲
Database Tables ۳۰
Migrations ۱۶
React Pages ۲ (پیاده‌سازی‌شده) + ۱۳ (در حال توسعه)
npm packages ۳۴
composer packages ۲۸