Files
clinicpro/docs/api/representation.md
T
hamed fe73fa1a05 feat: add ROLE_REPRESENTATION access to admin panel for managing doctors and clinics
- Updated authStore to include 'representation' role.
- Modified DoctorFormPage and DoctorsPage to handle different endpoints based on user role.
- Created new RepresentationActionController for handling doctor and clinic creation by representatives.
- Added new API endpoints for representatives to manage doctors, clinics, and view appointments.
- Updated documentation to reflect new role and API changes.
2026-06-19 13:20:40 +03:30

360 lines
9.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Representation (Agent) API
> **Prefix:** `/api/v1/representation`
Representations are sales agents who earn commission on appointments booked through their referral.
---
## POST `/api/v1/representation`
Create a new representation.
**Permission:** `ROLE_ADMIN`
### Request Body (`application/json`)
```json
{
"full_name": "علی احمدی",
"mobile_number": "09123456789",
"city_id": 42,
"commission_percent": 10,
"bank_account": {
"iban": "IR...",
"account_number": "1234567890",
"bank_name": "بانک ملت",
"owner_name": "علی احمدی"
}
}
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `full_name` | string | ✅ | Agent full name |
| `mobile_number` | string | ✅ | Login mobile (creates a User account) |
| `city_id` | integer | ❌ | City ID (FK to categories where bundle=city) |
| `commission_percent` | float | ❌ | Commission rate (0100) |
| `bank_account` | object | ❌ | Bank details for settlements |
### Response `201`
```json
{
"success": true,
"data": {
"uuid": "rep-uuid-...",
"full_name": "علی احمدی",
"mobile_number": "09123456789",
"city_id": 42,
"commission_percent": 10,
"active": true,
"bank_account": { ... },
"created_at": 1717000000
}
}
```
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_AUTH_006` | 403 | Not admin |
| `ERR_CONFLICT_001` | 409 | Mobile number already in use |
| `ERR_VALIDATION_001` | 422 | Invalid input |
---
## GET `/api/v1/representation/{uuid}`
Get representation detail.
**Permission:** `AUTH` — must be the representation's user or `ROLE_ADMIN`
### Path Parameters
| Param | Type | Description |
|-------|------|-------------|
| `uuid` | string (UUID) | Representation UUID |
### Response `200`
```json
{
"success": true,
"data": {
"uuid": "...",
"full_name": "علی احمدی",
"mobile_number": "09123456789",
"city_id": 42,
"city_name": "تهران",
"commission_percent": 10,
"active": true,
"bank_account": { ... },
"created_at": 1717000000
}
}
```
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_FORBIDDEN_001` | 403 | Not owner or admin |
| `ERR_NOT_FOUND_001` | 404 | Representation not found |
---
## PATCH `/api/v1/representation/{uuid}`
Update representation.
**Permission:** `AUTH` — must be the representation's user or `ROLE_ADMIN`
### Request Body (`application/json`)
```json
{
"full_name": "علی احمدی جدید",
"city_id": 50,
"commission_percent": 12,
"bank_account": { ... },
"active": true
}
```
All fields optional.
### Response `200`
Updated representation object.
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_FORBIDDEN_001` | 403 | Not owner or admin |
| `ERR_NOT_FOUND_001` | 404 | Representation not found |
---
## DELETE `/api/v1/representation/{uuid}`
Delete a representation.
**Permission:** `ROLE_ADMIN`
### Response `200`
```json
{ "success": true, "data": { "message": "نماینده حذف شد" } }
```
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_AUTH_006` | 403 | Not admin |
| `ERR_NOT_FOUND_001` | 404 | Representation not found |
---
## GET `/api/v1/representation/{uuid}/dashboard/monthly`
Get monthly earnings dashboard for a representation.
**Permission:** `AUTH` — must be the representation's user or `ROLE_ADMIN`
### Path Parameters
| Param | Type | Description |
|-------|------|-------------|
| `uuid` | string (UUID) | Representation UUID |
### Query Parameters
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `year` | integer | ✅ | e.g. `2024` |
| `month` | integer | ✅ | 112 |
### Response `200`
```json
{
"success": true,
"data": {
"period": { "year": 2024, "month": 6 },
"stats": {
"total_appointments": 15,
"total_revenue_rials": 7500000,
"commission_rials": 750000,
"daily": [
{ "date": "2024-06-01", "appointments": 2, "revenue": 1000000, "commission": 100000 }
]
}
}
}
```
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_FORBIDDEN_001` | 403 | Not owner or admin |
| `ERR_NOT_FOUND_001` | 404 | Representation not found |
---
## GET `/api/v1/representation/{uuid}/dashboard/yearly`
Get yearly earnings dashboard for a representation.
**Permission:** `AUTH` — must be the representation's user or `ROLE_ADMIN`
### Query Parameters
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `year` | integer | ✅ | e.g. `2024` |
### Response `200`
```json
{
"success": true,
"data": {
"period": { "year": 2024 },
"months": [
{ "month": 1, "appointments": 10, "revenue_rials": 5000000, "commission_rials": 500000 },
{ "month": 2, "appointments": 8, "revenue_rials": 4000000, "commission_rials": 400000 }
],
"totals": {
"appointments": 97,
"revenue_rials": 48500000,
"commission_rials": 4850000
}
}
}
```
---
## پنل نماینده (ROLE_REPRESENTATION)
این endpointها برای کاربرِ دارای نقش `ROLE_REPRESENTATION` در پنل ادمین (`/admin`) هستند. مالکیت همیشه از کاربر جاری (`#[CurrentUser]` + `findByUser`) تعیین می‌شود؛ هیچ uuid/id ورودی برای تعیین مالکیت پذیرفته نمی‌شود.
> **Permission (همه‌ی این بخش):** `ROLE_REPRESENTATION`
### GET `/api/v1/representation/me`
پروفایل نماینده‌ی کاربر جاری.
#### Response `200`
```json
{
"success": true,
"data": {
"data": {
"uuid": "...",
"full_name": "حامد حسینی",
"mobile_number": "09120671756",
"city_id": 132,
"commission_percent": "10.00",
"bank_account": null,
"active": true,
"created_at": 1718000000
}
}
}
```
> double-nested: مقدار با `data.data` استخراج می‌شود.
#### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_NOT_FOUND_001` | 404 | کاربر جاری نماینده نیست |
---
### POST `/api/v1/representation/doctor`
افزودن پزشک توسط نماینده. `representation_id` پزشک به‌صورت خودکار روی نماینده‌ی کاربر جاری ست می‌شود.
#### Request Body
```json
{ "mobile": "0935...", "name": "دکتر ...", "gender": "man", "degree": "...", "medical_system_code": "...", "specialties": [1,2] }
```
| Field | Type | Required |
|-------|------|----------|
| `mobile` | string | ✅ |
| `name` | string | ✅ |
| `gender` / `degree` / `medical_system_code` / `info` | string | ❌ |
| `specialties` | integer[] | ❌ |
#### Response `201`
```json
{ "success": true, "data": { "uuid": "..." } }
```
#### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_VALIDATION_002` | 422 | موبایل یا نام خالی |
| `ERR_CONFLICT_001` | 409 | این کاربر قبلاً پزشک است |
---
### POST `/api/v1/representation/clinic`
افزودن کلینیک توسط نماینده.
#### Request Body
```json
{ "owner_mobile": "0935...", "name": "کلینیک ...", "telephone": "...", "address": "..." }
```
| Field | Type | Required |
|-------|------|----------|
| `owner_mobile` | string | ✅ |
| `name` | string | ✅ |
| `telephone` / `address` / `info` | string | ❌ |
#### Response `200`
```json
{ "success": true, "data": { "uuid": "...", "name": "...", "is_active": true } }
```
#### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_VALIDATION_002` | 422 | موبایل یا نام خالی |
---
### GET `/api/v1/representation/appointments`
نوبت‌های همه‌ی پزشکانی که `representation_id` آن‌ها = نماینده‌ی کاربر جاری است (paginated، با شکل آیتمِ یکسان با `/api/v1/admin/appointments`).
#### Query Parameters
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `page` | integer | ❌ | پیش‌فرض 1 |
| `limit` | integer | ❌ | پیش‌فرض 15، حداکثر 500 |
| `status` | string | ❌ | فیلتر وضعیت |
| `date` | string (YYYY-MM-DD) | ❌ | فیلتر تاریخِ نوبت |
| `search` | string | ❌ | جستجو در موبایل/نام بیمار یا نام پزشک |
#### Response `200`
```json
{
"success": true,
"data": [
{
"uuid": "...",
"patient_name": "...",
"patient_mobile": "0912...",
"doctor_uuid": "...",
"doctor_name": "دکتر ...",
"slot_start": 1718000000,
"slot_end": 1718001800,
"appointment_date": "2025-06-15",
"appointment_time": "10:00",
"end_time": "10:30",
"status": "confirmed",
"created_at": 1717900000
}
],
"meta": { "totalRecords": 12, "totalPages": 1, "currentPage": 1 }
}
```
#### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_NOT_FOUND_001` | 404 | کاربر جاری نماینده نیست |