feat(representation): add representation management for doctors, including attach and update functionality

This commit is contained in:
hamed
2026-07-12 14:20:42 +03:30
parent 1a8b3bfa53
commit c1e4cd7f94
5 changed files with 432 additions and 31 deletions
+97 -2
View File
@@ -129,7 +129,7 @@ List all users with pagination and filters.
| `page` | integer | ❌ | Default: 1 |
| `limit` | integer | ❌ | Default: 20 |
| `search` | string | ❌ | Search by name or mobile |
| `role` | string | ❌ | Filter: `ROLE_USER`, `ROLE_DOCTOR`, `ROLE_ADMIN`, etc. |
| `role` | string | ❌ | فیلتر نقش: `admin` \| `doctor` \| `secretary` \| `clinic` \| `representation` (کاربران دارای `ROLE_REPRESENTATION`) \| `patient` |
| `status` | string | ❌ | `"active"` or `"inactive"` |
| `sort` | string | ❌ | `"created_at"` (default desc) |
@@ -344,6 +344,7 @@ List all doctors with pagination.
| `gender` | string | ❌ | `"male"` or `"female"` |
| `specialty_id` | integer | ❌ | Filter by specialty |
| `owner_status` | string | ❌ | `claimed` \| `unclaimed` \| `pending_transfer` — پروفایل‌های ایمپورت IRIMC (خروجی هم `owner_status` و `source` دارد) |
| `unassigned` | string | ❌ | `1` → فقط پزشکانِ بدون نماینده (`representation_id IS NULL`) — برای انتخاب و اتصال به نماینده |
| `sort` | string | ❌ | Sort field |
### Response `200`
@@ -407,6 +408,38 @@ Toggle doctor active status.
---
### PUT `/api/v1/admin/doctors/{uuid}/representation`
ست کردن یا حذف نماینده‌ی یک پزشک (از صفحه‌ی پروفایل پزشک در پنل ادمین).
**Permission:** `ROLE_ADMIN`
### Request Body
```json
{ "representation_id": 12 }
```
> `representation_id: null` (یا حذف‌شده/خالی) → نماینده‌ی پزشک حذف می‌شود (`representation_id = NULL`). بر خلاف `POST /representations/{uuid}/doctors`، این endpoint اجازه‌ی **تغییر** نماینده‌ی پزشکی که از قبل نماینده دارد را هم می‌دهد.
### Response `200`
```json
{
"success": true,
"data": {
"message": "نماینده ثبت شد",
"representation": { "id": 12, "uuid": "9c1...", "full_name": "علی محمدی" }
}
}
```
> برای حذف، `representation` برابر `null` برمی‌گردد.
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `DOCTOR_NOT_FOUND` | 404 | پزشک یافت نشد |
| `ERR_NOT_FOUND_001` | 404 | نماینده یافت نشد |
---
## Clinic Management
### GET `/api/v1/admin/clinics`
@@ -805,10 +838,72 @@ Paginated. Each item:
"medical_code": "12345",
"is_active": true,
"owner_status": "claimed",
"appointment_count": 17,
"past_count": 12,
"upcoming_count": 5,
"created_at": "2026-06-18T..."
}
```
> `past_count` = نوبت‌های `slot_start < now`؛ `upcoming_count` = `slot_start >= now`.
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_NOT_FOUND_001` | 404 | نماینده یافت نشد |
---
### POST `/api/v1/admin/representations/{uuid}/doctors`
اتصال یک پزشکِ موجودِ **بدون نماینده** به این نماینده (`representation_id` ست می‌شود).
**Permission:** `ROLE_ADMIN`
### Request Body
```json
{ "doctor_uuid": "550e8400-..." }
```
### Response `200`
```json
{ "success": true, "data": { "message": "پزشک به نماینده متصل شد", "doctor_uuid": "550e8400-...", "representation_id": 12 } }
```
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_VALIDATION_001` | 422 | `doctor_uuid` ارسال نشده |
| `ERR_NOT_FOUND_001` | 404 | نماینده یا پزشک یافت نشد |
| `ERR_CONFLICT_001` | 409 | پزشک از قبل به یک نماینده متصل است |
---
### GET `/api/v1/admin/representations/{uuid}/appointments`
نوبت‌های پزشکانِ زیرمجموعه‌ی یک نماینده (paginated).
**Permission:** `ROLE_ADMIN`
### Query Parameters
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `scope` | string | ❌ | `upcoming` (پیش‌فرض، `slot_start >= now`، صعودی) یا `past` (`slot_start < now`، نزولی) |
| `page` | integer | ❌ | Default: 1 |
| `limit` | integer | ❌ | Default: 15 (max 100) |
### Response `200`
Paginated. Each item:
```json
{
"uuid": "...",
"slot_start": 1750000000,
"slot_end": 1750001800,
"status": "confirmed",
"patient_name": "علی رضایی",
"doctor_uuid": "...",
"doctor_name": "دکتر علی احمدی"
}
```
> `slot_start`/`slot_end` Unix timestamp (ثانیه).
### Errors
| Code | HTTP | Description |