- Added `clinic_id` and `type` fields to `DoctorAddress` entity to differentiate between personal and clinic addresses. - Updated constructor to support creation of addresses for both doctors and clinics. - Modified repository methods to handle new address types and added methods for counting and finding addresses by clinic. - Implemented migration to update the database schema accordingly. - Removed deprecated endpoint for creating addresses from clinics and updated related controller methods. - Added new endpoints for managing clinic addresses, including CRUD operations. - Updated frontend components to handle new address types and display accordingly.
419 lines
9.3 KiB
Markdown
419 lines
9.3 KiB
Markdown
# Clinic API
|
|
|
|
> **Prefix:** `/api/v1/clinic`, `/api/v1/clinics`
|
|
|
|
---
|
|
|
|
## POST `/api/v1/clinic`
|
|
|
|
Create a new clinic.
|
|
|
|
**Permission:** `AUTH` — any authenticated user becomes the clinic owner
|
|
|
|
### Request Body (`application/json`)
|
|
```json
|
|
{
|
|
"name": "کلینیک الوند",
|
|
"info": "توضیحات کلینیک",
|
|
"address": "تهران، خیابان ولیعصر",
|
|
"telephone": "02112345678",
|
|
"working_days": "شنبه تا چهارشنبه",
|
|
"is_24_7": false,
|
|
"latitude": 35.6892,
|
|
"longitude": 51.3890,
|
|
"state": "تهران",
|
|
"city": "تهران",
|
|
"image_clinic": [
|
|
{ "url": "https://..." }
|
|
],
|
|
"clinic_logo": "https://...",
|
|
"doctors": ["uuid1", "uuid2"],
|
|
"specialties": [1, 2],
|
|
"doctor_services": [3, 4],
|
|
"insurance": [5, 6]
|
|
}
|
|
```
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `name` | string | ✅ | Clinic name |
|
|
| `info` | string | ❌ | Description |
|
|
| `address` | string | ❌ | Full address |
|
|
| `telephone` | string | ❌ | Contact number |
|
|
| `working_days` | string | ❌ | Working days description |
|
|
| `is_24_7` | boolean | ❌ | Open 24/7 flag |
|
|
| `latitude` | float | ❌ | Latitude for map |
|
|
| `longitude` | float | ❌ | Longitude for map |
|
|
| `state` | string | ❌ | Province name |
|
|
| `city` | string | ❌ | City name |
|
|
| `image_clinic` | object[] | ❌ | Gallery images `[{url: "..."}]` |
|
|
| `clinic_logo` | string | ❌ | Logo URL |
|
|
| `doctors` | string[] | ❌ | Doctor UUIDs to associate |
|
|
| `specialties` | integer[] | ❌ | Specialty IDs |
|
|
| `doctor_services` | integer[] | ❌ | Service IDs |
|
|
| `insurance` | integer[] | ❌ | Insurance IDs |
|
|
|
|
### Response `201`
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"data": {
|
|
"uuid": "550e8400-...",
|
|
"name": "کلینیک الوند",
|
|
"info": "...",
|
|
"address": "...",
|
|
"telephone": "02112345678",
|
|
"working_days": "...",
|
|
"is_24_7": false,
|
|
"latitude": 35.6892,
|
|
"longitude": 51.3890,
|
|
"state": "تهران",
|
|
"city": "تهران",
|
|
"images_clinic": [{ "url": "https://..." }],
|
|
"clinic_logo": "https://...",
|
|
"is_active": true,
|
|
"doctors": [],
|
|
"specialties": [],
|
|
"doctor_services": [],
|
|
"insurance": [],
|
|
"tags": [],
|
|
"created_at": 1717000000
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
> ⚠️ **Double-nested:** Frontend extracts with `data?.data?.data`
|
|
|
|
### Errors
|
|
| Code | HTTP | Description |
|
|
|------|------|-------------|
|
|
| `ERR_AUTH_001` | 401 | Missing or invalid token |
|
|
|
|
---
|
|
|
|
## GET `/api/v1/clinic/{uuid}`
|
|
|
|
Get clinic detail.
|
|
|
|
**Permission:** `PUBLIC`
|
|
|
|
### Path Parameters
|
|
| Param | Type | Description |
|
|
|-------|------|-------------|
|
|
| `uuid` | string (UUID) | Clinic UUID |
|
|
|
|
### Response `200`
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"data": {
|
|
"uuid": "550e8400-...",
|
|
"name": "کلینیک الوند",
|
|
"info": "...",
|
|
"address": "تهران، خیابان ولیعصر",
|
|
"telephone": "02112345678",
|
|
"working_days": "شنبه تا چهارشنبه",
|
|
"is_24_7": false,
|
|
"latitude": 35.6892,
|
|
"longitude": 51.3890,
|
|
"state": "تهران",
|
|
"city": "تهران",
|
|
"images_clinic": [{ "url": "https://..." }],
|
|
"clinic_logo": "https://...",
|
|
"is_active": true,
|
|
"doctors": [{ "uuid": "...", "title": "دکتر..." }],
|
|
"specialties": [{ "id": 1, "name": "قلب" }],
|
|
"doctor_services": [],
|
|
"insurance": [],
|
|
"tags": [],
|
|
"owner": { "uuid": "...", "real_name": "..." }
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Errors
|
|
| Code | HTTP | Description |
|
|
|------|------|-------------|
|
|
| `ERR_NOT_FOUND_001` | 404 | Clinic not found |
|
|
|
|
---
|
|
|
|
## PATCH `/api/v1/clinic/{uuid}`
|
|
|
|
Update a clinic.
|
|
|
|
**Permission:** `AUTH` — must be the clinic owner or `ROLE_ADMIN`
|
|
|
|
### Path Parameters
|
|
| Param | Type | Description |
|
|
|-------|------|-------------|
|
|
| `uuid` | string (UUID) | Clinic UUID |
|
|
|
|
### Request Body
|
|
Same fields as POST — all optional.
|
|
|
|
### Response `200`
|
|
Updated clinic object (same structure as GET).
|
|
|
|
### Errors
|
|
| Code | HTTP | Description |
|
|
|------|------|-------------|
|
|
| `ERR_AUTH_001` | 401 | Missing token |
|
|
| `ERR_FORBIDDEN_001` | 403 | Not the owner |
|
|
| `ERR_NOT_FOUND_001` | 404 | Clinic not found |
|
|
|
|
---
|
|
|
|
## GET `/api/v1/clinics`
|
|
|
|
List clinics with pagination.
|
|
|
|
**Permission:** `PUBLIC`
|
|
|
|
### Query Parameters
|
|
| Param | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `page` | integer | ❌ | Default: 1 |
|
|
| `limit` | integer | ❌ | Default: 20 |
|
|
| `name` | string | ❌ | Search by clinic name |
|
|
| `city` | string | ❌ | Filter by city |
|
|
|
|
### Response `200`
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": [
|
|
{
|
|
"uuid": "...",
|
|
"name": "کلینیک الوند",
|
|
"city": "تهران",
|
|
"clinic_logo": "https://...",
|
|
"is_active": true
|
|
}
|
|
],
|
|
"meta": {
|
|
"totalRecords": 30,
|
|
"totalPages": 2,
|
|
"currentPage": 1
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## GET `/api/v1/clinic/doctor-list/{clinicUuid}`
|
|
|
|
Get doctors associated with a clinic.
|
|
|
|
**Permission:** `PUBLIC`
|
|
|
|
### Path Parameters
|
|
| Param | Type | Description |
|
|
|-------|------|-------------|
|
|
| `clinicUuid` | string (UUID) | Clinic UUID |
|
|
|
|
### Response `200`
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": [
|
|
{
|
|
"uuid": "...",
|
|
"title": "دکتر علی احمدی",
|
|
"degree": "متخصص",
|
|
"doctor_rate": 4.5,
|
|
"image": "https://..."
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Errors
|
|
| Code | HTTP | Description |
|
|
|------|------|-------------|
|
|
| `ERR_NOT_FOUND_001` | 404 | Clinic not found |
|
|
|
|
---
|
|
|
|
## POST `/file/upload/clinic_pro/clinic/field_clinic_logo`
|
|
|
|
Upload clinic logo.
|
|
|
|
**Permission:** `AUTH`
|
|
|
|
### Request
|
|
`Content-Type: multipart/form-data`
|
|
|
|
| Field | Type | Required | Max Size |
|
|
|-------|------|----------|----------|
|
|
| `file` | binary | ✅ | 5MB |
|
|
|
|
### Response `200`
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"url": "https://clinic-pro.ddev.site/uploads/clinic/logo_abc.jpg",
|
|
"uuid": "...",
|
|
"filename": "logo_abc.jpg",
|
|
"filemime": "image/jpeg",
|
|
"filesize": 102400
|
|
}
|
|
}
|
|
```
|
|
|
|
### Errors
|
|
| Code | HTTP | Description |
|
|
|------|------|-------------|
|
|
| `ERR_FILE_001` | 422 | Invalid file type |
|
|
| `ERR_AUTH_001` | 401 | Missing token |
|
|
|
|
---
|
|
|
|
## POST `/file/upload/clinic_pro/clinic/field_image_clinic`
|
|
|
|
Upload clinic gallery image.
|
|
|
|
**Permission:** `AUTH`
|
|
|
|
### Request
|
|
`Content-Type: multipart/form-data`
|
|
|
|
| Field | Type | Required | Max Size |
|
|
|-------|------|----------|----------|
|
|
| `file` | binary | ✅ | 5MB |
|
|
|
|
### Response `200`
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"url": "https://clinic-pro.ddev.site/uploads/clinic/gallery_abc.jpg",
|
|
"uuid": "...",
|
|
"filename": "gallery_abc.jpg",
|
|
"filemime": "image/jpeg",
|
|
"filesize": 307200
|
|
}
|
|
}
|
|
```
|
|
|
|
> After uploading, use the returned `url` inside `image_clinic: [{ "url": "..." }]` when calling PATCH clinic.
|
|
|
|
### Errors
|
|
| Code | HTTP | Description |
|
|
|------|------|-------------|
|
|
| `ERR_FILE_001` | 422 | Invalid file type |
|
|
| `ERR_AUTH_001` | 401 | Missing token |
|
|
|
|
---
|
|
|
|
## Clinic Address Management
|
|
|
|
### `GET /api/v1/clinic/{clinicUuid}/addresses`
|
|
|
|
**Permission:** Public
|
|
|
|
Returns all addresses registered for a clinic (type=clinic entries).
|
|
|
|
#### Response `200`
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": [
|
|
{
|
|
"id": "12",
|
|
"uuid": "abc-123",
|
|
"type": "clinic",
|
|
"clinic_id": "5",
|
|
"name": "شعبه مرکزی",
|
|
"address": "تهران، خیابان ولیعصر...",
|
|
"telephone": "02112345678",
|
|
"map": { "latitude": "35.699", "longitude": "51.337" },
|
|
"city": { "id": "1", "name": "تهران" },
|
|
"province": { "id": "8", "name": "تهران" }
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### `POST /api/v1/clinic/{clinicUuid}/address`
|
|
|
|
**Permission:** Clinic owner or `ROLE_ADMIN`
|
|
|
|
Creates a new address for the clinic. The address will appear in `available-locations` for doctors belonging to this clinic.
|
|
|
|
#### Request
|
|
```json
|
|
{
|
|
"name": "شعبه مرکزی",
|
|
"address": "تهران، خیابان ولیعصر...",
|
|
"telephone": "02112345678",
|
|
"latitude": 35.699,
|
|
"longitude": 51.337,
|
|
"city_id": 123,
|
|
"province_id": 7
|
|
}
|
|
```
|
|
|
|
| Field | Type | Required |
|
|
|-------|------|----------|
|
|
| `name` | string | ❌ |
|
|
| `address` | string | ❌ |
|
|
| `telephone` | string | ❌ |
|
|
| `latitude` | float | ❌ |
|
|
| `longitude` | float | ❌ |
|
|
| `city_id` | integer | ❌ |
|
|
| `province_id` | integer | ❌ |
|
|
|
|
#### Response `201`
|
|
```json
|
|
{ "success": true, "data": { "id": "12", "uuid": "...", "type": "clinic", ... } }
|
|
```
|
|
|
|
#### Errors
|
|
| Code | HTTP | Description |
|
|
|------|------|-------------|
|
|
| `ERR_AUTH_006` | 403 | Not the clinic owner |
|
|
| `ERR_VALIDATION_002` | 404 | Clinic not found |
|
|
|
|
---
|
|
|
|
### `PATCH /api/v1/clinic/{clinicUuid}/address/{addressUuid}`
|
|
|
|
**Permission:** Clinic owner or `ROLE_ADMIN`
|
|
|
|
Updates an existing clinic address. Same body fields as POST (all optional).
|
|
|
|
#### Response `200`
|
|
```json
|
|
{ "success": true, "data": { ... } }
|
|
```
|
|
|
|
---
|
|
|
|
### `DELETE /api/v1/clinic/{clinicUuid}/address/{addressUuid}`
|
|
|
|
**Permission:** Clinic owner or `ROLE_ADMIN`
|
|
|
|
Deletes a clinic address.
|
|
|
|
> A clinic must retain at least one address — attempting to delete the last address returns `409`.
|
|
|
|
#### Errors
|
|
| Code | HTTP | Description |
|
|
|------|------|-------------|
|
|
| `ERR_CONFLICT_001` | 409 | Cannot delete the last address |
|
|
| `ERR_VALIDATION_002` | 404 | Address or clinic not found |
|
|
| `ERR_AUTH_006` | 403 | Not the clinic owner |
|
|
|
|
---
|
|
|
|
### Removed endpoint
|
|
`POST /api/v1/clinic-pro/doctor-address/from-clinic/{clinicUuid}` — **removed**. Use clinic address management endpoints instead.
|