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.
This commit is contained in:
hamed
2026-06-09 22:00:34 +03:30
commit de1a78a235
222 changed files with 36388 additions and 0 deletions
+160
View File
@@ -0,0 +1,160 @@
# پایگاه داده — تسک ۰۵: ماژول دکتر
## جدول: doctors
_(entity_type=clinic_pro, bundle=doctor — از DB backup و config تأیید شده)_
| ستون | نوع | نام Drupal | توضیح |
|------|-----|-----------|-------|
| id | INT UNSIGNED AUTO_INCREMENT PK | id | |
| uuid | CHAR(36) UNIQUE NOT NULL | uuid | |
| user_id | INT FK → users.id UNIQUE NOT NULL | uid | کاربر صاحب پروفایل |
| name | VARCHAR(255) NOT NULL | field_name | نام دکتر |
| gender | VARCHAR(10) NULL | field_gender | `woman` یا `man` |
| medical_system_code | VARCHAR(25) NULL | field_doctor_id | شماره نظام پزشکی (max 25) |
| mobile_number | VARCHAR(15) NULL | field_doctor_mobile_number | شماره موبایل دکتر (max 15) |
| activity_time | INT NULL | field_activity_time | timestamp سال شروع فعالیت |
| degree | VARCHAR(30) NULL | field_degree | مدرک (مقادیر زیر) |
| info | LONGTEXT NULL | field_info | بیوگرافی |
| image_path | VARCHAR(255) NULL | field_image | تصویر (media) |
| doctor_rate | FLOAT NULL | field_doctor_rate | امتیاز ستاره‌ای (default: 3.5) |
| doctor_rate_percentage | FLOAT NULL | field_doctor_rate_percentage | درصد رضایت (default: 60) |
| active_doctor_appointment | TINYINT(1) DEFAULT 1 | field_active_doctor_appointmen | نوبت‌دهی فعال (بدون حرف 't') |
| representation_id | INT FK → representations.id NULL | field_representation | entity ref → clinic_pro |
| created_at | INT NOT NULL | created | Unix timestamp |
| updated_at | INT NOT NULL | changed | Unix timestamp |
## مقادیر field_degree (از config)
```
expert → کارشناس
general → پزشک عمومی
specialist → پزشک متخصص
subspecialistplus → پزشک فوق تخصص
```
## مقادیر field_gender (از config)
```
woman → زن
man → مرد
```
## جدول: doctor_specialties (ManyToMany pivot)
| ستون | نوع | توضیح |
|------|-----|-------|
| doctor_id | INT FK → doctors.id | |
| category_id | INT FK → categories.id | |
| PRIMARY KEY (doctor_id, category_id) | | field_specialty → cardinality=2 (حداکثر ۲ تخصص) |
## جدول: doctor_services (ManyToMany pivot)
| ستون | نوع | توضیح |
|------|-----|-------|
| doctor_id | INT FK → doctors.id | |
| category_id | INT FK → categories.id | |
| PRIMARY KEY (doctor_id, category_id) | | field_doctor_services → cardinality=8 (حداکثر ۸ سرویس) |
## جدول: doctor_states (ManyToMany pivot)
| ستون | نوع | توضیح |
|------|-----|-------|
| doctor_id | INT FK → doctors.id | |
| category_id | INT FK → categories.id | |
| PRIMARY KEY (doctor_id, category_id) | | field_state → cardinality=1 |
## جدول: doctor_cities (ManyToMany pivot)
| ستون | نوع | توضیح |
|------|-----|-------|
| doctor_id | INT FK → doctors.id | |
| category_id | INT FK → categories.id | |
| PRIMARY KEY (doctor_id, category_id) | | field_city → cardinality=1 |
## جدول: doctor_addresses
_(entity_type=clinic_pro, bundle=doctors_addresses — از DB backup)_
| ستون | نوع | نام Drupal | توضیح |
|------|-----|-----------|-------|
| id | INT UNSIGNED AUTO_INCREMENT PK | id | |
| uuid | CHAR(36) UNIQUE NOT NULL | uuid | |
| doctor_id | INT FK → doctors.id CASCADE | field_doctor | دکتر |
| name | VARCHAR(255) NULL | field_name | نام مطب/آدرس |
| address | LONGTEXT NULL | field_address | آدرس کامل |
| telephone | VARCHAR(50) NULL | field_telephone | تلفن مطب |
| latitude | FLOAT NULL | field_latitude | عرض جغرافیایی |
| longitude | FLOAT NULL | field_longitude | طول جغرافیایی |
| created_at | INT NOT NULL | created | Unix timestamp |
| updated_at | INT NOT NULL | changed | Unix timestamp |
## جدول: clinics
_(entity_type=clinic_pro, bundle=clinic — از config تأیید شده)_
| ستون | نوع | نام Drupal | توضیح |
|------|-----|-----------|-------|
| id | INT UNSIGNED AUTO_INCREMENT PK | id | |
| uuid | CHAR(36) UNIQUE NOT NULL | uuid | |
| user_id | INT FK → users.id NOT NULL | uid | مالک |
| name | VARCHAR(255) NULL | field_name | نام کلینیک |
| info | LONGTEXT NULL | field_info | توضیحات |
| address | LONGTEXT NULL | field_address | آدرس |
| telephone | VARCHAR(50) NULL | field_telephone | تلفن |
| is_24_7 | TINYINT(1) DEFAULT 0 | field_24_7 | باز ۲۴/۷ |
| working_days | VARCHAR(255) NULL | field_working_days | روزهای کاری (متن آزاد، مثال: 'شنبه تا سه شنبه ساعت ۱۲:۲۰') |
| latitude | FLOAT NULL | field_latitude | |
| longitude | FLOAT NULL | field_longitude | |
| city_id | INT FK → categories.id NULL | field_city | |
| state_id | INT FK → categories.id NULL | field_state | |
| representation_id | INT FK → representations.id NULL | field_agent | نماینده کلینیک |
| created_at | INT NOT NULL | created | |
| updated_at | INT NOT NULL | changed | |
جداول pivot مرتبط با clinic:
- `clinic_doctors` (clinic_id, doctor_id) → field_doctors (cardinality نامحدود)
- `clinic_specialties` (clinic_id, category_id) → field_clinic_specialty
- `clinic_services` (clinic_id, category_id) → field_doctor_services
- `clinic_insurances` (clinic_id, category_id) → field_insurance
## جدول: doctor_secretaries
_(entity_type=clinic_pro, bundle=doctor_secretary — از config تأیید شده)_
| ستون | نوع | نام Drupal | توضیح |
|------|-----|-----------|-------|
| id | INT UNSIGNED AUTO_INCREMENT PK | id | |
| uuid | CHAR(36) UNIQUE NOT NULL | uuid | |
| user_id | INT FK → users.id NOT NULL | uid | |
| doctor_id | INT FK → doctors.id NOT NULL | field_doctor | entity ref → clinic_pro/doctor |
| secretary_id | INT FK → users.id NOT NULL | field_secretary | entity ref → user (منشی) |
| telephone | VARCHAR(50) NULL | field_telephone | تلفن |
| permission | LONGTEXT NULL | field_permission | مجوزها (JSON) |
| active | TINYINT(1) DEFAULT 1 | field_active | فعال/غیرفعال |
| created_at | INT NOT NULL | created | |
| updated_at | INT NOT NULL | changed | |
## ایندکس‌ها
```sql
CREATE UNIQUE INDEX idx_doctors_user ON doctors(user_id);
CREATE INDEX idx_doctors_representation ON doctors(representation_id);
CREATE INDEX idx_doctors_active ON doctors(active_doctor_appointment);
CREATE INDEX idx_doctors_rate ON doctors(doctor_rate DESC);
CREATE INDEX idx_doctor_addresses_doctor ON doctor_addresses(doctor_id);
CREATE INDEX idx_clinics_user ON clinics(user_id);
CREATE UNIQUE INDEX idx_doctor_secretaries_doctor_secretary ON doctor_secretaries(doctor_id, secretary_id);
```
## نمونه داده واقعی از DB (clinic_pro table)
```
id=18, bundle='doctor'
id=22, bundle='doctor'
id=23, bundle='clinic'
id=24, bundle='clinic'
id=27, bundle='doctor_secretary'
id=29, bundle='doctor'
id=38, bundle='doctors_addresses'
id=41, bundle='representation'
```
## روابط کامل clinic_pro entity
- `doctors``users` (ManyToOne, UNIQUE → OneToOne)
- `doctors``representations` (ManyToOne)
- `doctors``categories` (ManyToMany: specialties, services, states, cities)
- `doctor_addresses``doctors` (ManyToOne, CASCADE)
- `clinics``users` (ManyToOne)
- `clinics``doctors` (ManyToMany)
- `clinics``categories` (ManyToMany)
- `doctor_secretaries``doctors` (ManyToOne)
- `doctor_secretaries``users` as secretary (ManyToOne)