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
+146 -107
View File
@@ -6,10 +6,10 @@
هر رابطه منشی-پزشک دارای یک **scope** است که از تداخل بین محیط‌های مختلف جلوگیری می‌کند:
| Scope | `owner_type` | تعریف‌کننده | دسترسی |
|-------|-------------|-------------|---------|
| مطب شخصی | `doctor` | خود پزشک | فقط نوبت‌ها و داده‌های مطب شخصی |
| کلینیک | `clinic` | مدیر کلینیک | فقط نوبت‌ها و داده‌های کلینیک |
| Scope | `owner_type` | تعریف‌کننده | دسترسی |
| -------- | ------------ | ----------- | ------------------------------- |
| مطب شخصی | `doctor` | خود پزشک | فقط نوبت‌ها و داده‌های مطب شخصی |
| کلینیک | `clinic` | مدیر کلینیک | فقط نوبت‌ها و داده‌های کلینیک |
- یک منشی می‌تواند هم در مطب شخصی یک دکتر و هم در کلینیک همان دکتر فعال باشد (دو ردیف مجزا)
- منشی کلینیک می‌تواند به چند دکتر در همان کلینیک متصل باشد
@@ -26,62 +26,80 @@ Create a secretary for a doctor.
**Permission:** `ROLE_DOCTOR` (must own the doctor — creates `owner_type='doctor'`) | `ROLE_CLINIC` (must have the doctor in its clinic — creates `owner_type='clinic'`) | `ROLE_ADMIN`
### Request Body (`application/json`)
```json
{
"doctor_uuid": "550e8400-...",
"mobile_number": "09123456789",
"password": "secretaryPass123",
"permissions": {
"version": 1,
"resources": {
"appointments": { "view": true, "create": true, "cancel": false, "update_status": true },
"addresses": { "view": true, "create": false, "update": false, "delete": false },
"clinic_info": { "view": true, "update": false },
"insurances": { "view": true, "create": false, "update": false, "delete": false }
"doctor_uuid": "550e8400-...",
"mobile_number": "09123456789",
"password": "secretaryPass123",
"permissions": {
"version": 1,
"resources": {
"appointments": {
"view": true,
"create": true,
"cancel": false,
"update_status": true
},
"addresses": {
"view": true,
"create": false,
"update": false,
"delete": false
},
"clinic_info": { "view": true, "update": false },
"insurances": {
"view": true,
"create": false,
"update": false,
"delete": false
}
}
}
}
}
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `doctor_uuid` | string (UUID) | ✅ | Doctor to assign secretary to |
| `mobile_number` | string | ✅ | Secretary's login mobile |
| `password` | string | ❌ | Initial password (auto-generated if omitted) |
| `permissions` | object | ❌ | Permission set (see structure below) |
| Field | Type | Required | Description |
| --------------- | ------------- | -------- | -------------------------------------------- |
| `doctor_uuid` | string (UUID) | ✅ | Doctor to assign secretary to |
| `mobile_number` | string | ✅ | Secretary's login mobile |
| `password` | string | ❌ | Initial password (auto-generated if omitted) |
| `permissions` | object | ❌ | Permission set (see structure below) |
**Permissions Structure:**
```json
{
"version": 1,
"resources": {
"appointments": {
"view": true, // Can view appointments list
"create": true, // Can book appointments
"cancel": false, // Can cancel appointments
"update_status": true // Can mark as completed/no_show
},
"addresses": {
"view": true,
"create": false,
"update": false,
"delete": false
},
"clinic_info": {
"view": true,
"update": false
},
"insurances": {
"view": true,
"create": false,
"update": false,
"delete": false
"version": 1,
"resources": {
"appointments": {
"view": true, // Can view appointments list
"create": true, // Can book appointments
"cancel": false, // Can cancel appointments
"update_status": true // Can mark as completed/no_show
},
"addresses": {
"view": true,
"create": false,
"update": false,
"delete": false
},
"clinic_info": {
"view": true,
"update": false
},
"insurances": {
"view": true,
"create": false,
"update": false,
"delete": false
}
}
}
}
```
### Response `201`
```json
{
"success": true,
@@ -107,13 +125,14 @@ Create a secretary for a doctor.
| `clinic` | منشی توسط مدیر کلینیک تعریف شده — فقط کلینیک |
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_AUTH_006` | 403 | Not the doctor owner / clinic owner / admin |
| `ERR_NOT_FOUND_001` | 404 | Doctor not found |
| `ERR_CONFLICT_001` | 409 | Secretary already added for this doctor |
| `ERR_SECRETARY_001` | 422 | Plan limit for secretaries reached |
| Code | HTTP | Description |
| ------------------- | ---- | ------------------------------------------- |
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_AUTH_006` | 403 | Not the doctor owner / clinic owner / admin |
| `ERR_NOT_FOUND_001` | 404 | Doctor not found |
| `ERR_CONFLICT_001` | 409 | Secretary already added for this doctor |
| `ERR_SECRETARY_001` | 422 | Plan limit for secretaries reached |
---
@@ -124,11 +143,13 @@ Get secretary detail.
**Permission:** `AUTH` — must be the linked doctor or `ROLE_ADMIN`
### Path Parameters
| Param | Type | Description |
|-------|------|-------------|
| Param | Type | Description |
| ------ | ------------- | -------------- |
| `uuid` | string (UUID) | Secretary UUID |
### Response `200`
```json
{
"success": true,
@@ -144,11 +165,12 @@ Get secretary detail.
```
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_FORBIDDEN_001` | 403 | Not authorized |
| `ERR_NOT_FOUND_001` | 404 | Secretary not found |
| Code | HTTP | Description |
| ------------------- | ---- | ------------------- |
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_FORBIDDEN_001` | 403 | Not authorized |
| `ERR_NOT_FOUND_001` | 404 | Secretary not found |
---
@@ -159,32 +181,40 @@ Update secretary active status or permissions.
**Permission:** `ROLE_DOCTOR` — must be the linked doctor
### Request Body (`application/json`)
```json
{
"active": false,
"permissions": {
"version": 1,
"resources": {
"appointments": { "view": true, "create": false, "cancel": false, "update_status": false }
"active": false,
"permissions": {
"version": 1,
"resources": {
"appointments": {
"view": true,
"create": false,
"cancel": false,
"update_status": false
}
}
}
}
}
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `active` | boolean | ❌ | Enable/disable secretary |
| `permissions` | object | ❌ | New permissions object |
| Field | Type | Required | Description |
| ------------- | ------- | -------- | ------------------------ |
| `active` | boolean | ❌ | Enable/disable secretary |
| `permissions` | object | ❌ | New permissions object |
### Response `200`
Updated secretary object.
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_FORBIDDEN_001` | 403 | Not the linked doctor |
| `ERR_NOT_FOUND_001` | 404 | Secretary not found |
| Code | HTTP | Description |
| ------------------- | ---- | --------------------- |
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_FORBIDDEN_001` | 403 | Not the linked doctor |
| `ERR_NOT_FOUND_001` | 404 | Secretary not found |
---
@@ -195,16 +225,18 @@ Delete a secretary.
**Permission:** `ROLE_DOCTOR` — must be the linked doctor
### Response `200`
```json
{ "success": true, "data": { "message": "منشی حذف شد" } }
```
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_FORBIDDEN_001` | 403 | Not the linked doctor |
| `ERR_NOT_FOUND_001` | 404 | Secretary not found |
| Code | HTTP | Description |
| ------------------- | ---- | --------------------- |
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_FORBIDDEN_001` | 403 | Not the linked doctor |
| `ERR_NOT_FOUND_001` | 404 | Secretary not found |
---
@@ -215,11 +247,13 @@ Get all secretaries for a specific doctor.
**Permission:** `ROLE_DOCTOR` (must own doctor) | `ROLE_CLINIC` (must have doctor in clinic) | `ROLE_ADMIN`
### Path Parameters
| Param | Type | Description |
|-------|------|-------------|
| Param | Type | Description |
| ------------ | ------------- | ----------- |
| `doctorUuid` | string (UUID) | Doctor UUID |
### Response `200`
```json
{
"success": true,
@@ -239,11 +273,12 @@ Get all secretaries for a specific doctor.
```
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_FORBIDDEN_001` | 403 | Not authorized |
| `ERR_NOT_FOUND_001` | 404 | Doctor not found |
| Code | HTTP | Description |
| ------------------- | ---- | ---------------- |
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_FORBIDDEN_001` | 403 | Not authorized |
| `ERR_NOT_FOUND_001` | 404 | Doctor not found |
---
@@ -254,11 +289,13 @@ Get all secretaries across **all doctors** of a clinic.
**Permission:** `ROLE_CLINIC` (must own clinic) | `ROLE_ADMIN`
### Path Parameters
| Param | Type | Description |
|-------|------|-------------|
| Param | Type | Description |
| ------------ | ------------- | ----------- |
| `clinicUuid` | string (UUID) | Clinic UUID |
### Response `200`
```json
{
"success": true,
@@ -278,16 +315,18 @@ Get all secretaries across **all doctors** of a clinic.
```
### Notes
- این endpoint فقط منشیانی را برمی‌گرداند که با `owner_type='clinic'` تعریف شده‌اند
- منشیانی که خود دکتر (با `owner_type='doctor'`) تعریف کرده از این لیست مخفی هستند
- این endpoint فقط منشی های را برمی‌گرداند که با `owner_type='clinic'` تعریف شده‌اند
- منشی های که خود دکتر (با `owner_type='doctor'`) تعریف کرده از این لیست مخفی هستند
- یک منشی می‌تواند به چند دکتر در همان کلینیک متصل باشد — در لیست چندبار ظاهر می‌شود (یک ردیف به ازای هر دکتر)
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_FORBIDDEN_001` | 403 | Not clinic owner |
| `ERR_NOT_FOUND_001` | 404 | Clinic not found |
| Code | HTTP | Description |
| ------------------- | ---- | ---------------- |
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_FORBIDDEN_001` | 403 | Not clinic owner |
| `ERR_NOT_FOUND_001` | 404 | Clinic not found |
---
@@ -295,23 +334,23 @@ Get all secretaries across **all doctors** of a clinic.
تعداد منشی‌های مجاز بر اساس پنل فعال doctor تعیین می‌شود:
| پنل | حداکثر منشی |
|-----|-------------|
| Free (بدون اشتراک) | ۱ |
| Basic | ۳ |
| Professional | ۱۰ |
| پنل | حداکثر منشی |
| ------------------ | ----------- |
| Free (بدون اشتراک) | ۱ |
| Basic | ۳ |
| Professional | ۱۰ |
اگر تعداد منشی‌های فعال به حد مجاز رسیده باشد، ایجاد منشی جدید خطای زیر را برمی‌گرداند:
```json
{
"success": false,
"errors": [
{
"code": "ERR_SECRETARY_001",
"message": "پلن فعلی اجازه منشی بیشتر را نمی‌دهد"
}
]
"success": false,
"errors": [
{
"code": "ERR_SECRETARY_001",
"message": "پلن فعلی اجازه منشی بیشتر را نمی‌دهد"
}
]
}
```