Files
clinicpro/docs/api/location.md
T

268 lines
6.1 KiB
Markdown

# Location API (Province & City)
> **Prefix:** `/api/v1/provinces`, `/api/v1/cities`, `/api/v1/admin/province`, `/api/v1/admin/city`
---
## GET `/api/v1/provinces`
List all active provinces.
**Permission:** `PUBLIC`
### Response `200`
```json
{
"success": true,
"data": [
{ "id": 1, "name": "تهران", "status": "active", "weight": 1 },
{ "id": 2, "name": "اصفهان", "status": "active", "weight": 2 }
]
}
```
---
## GET `/api/v1/cities`
List cities, optionally filtered by province.
**Permission:** `PUBLIC`
### Query Parameters
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `province_id` | integer | ❌ | Filter cities by province |
### Response `200`
```json
{
"success": true,
"data": [
{ "id": 10, "name": "تهران", "province_id": 1, "status": "active", "weight": 1 },
{ "id": 11, "name": "کرج", "province_id": 1, "status": "active", "weight": 2 }
]
}
```
---
## GET `/api/v1/admin/provinces`
List all provinces with pagination (admin view — includes inactive).
**Permission:** `ROLE_ADMIN`
### Query Parameters
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `page` | integer | ❌ | Default: 1 |
| `limit` | integer | ❌ | Default: 20 |
| `search` | string | ❌ | Search in name |
### Response `200`
```json
{
"success": true,
"data": [ ... ],
"meta": { "totalRecords": 31, "totalPages": 2, "currentPage": 1 }
}
```
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_AUTH_006` | 403 | Not admin |
---
## GET `/api/v1/admin/cities`
List all cities with pagination (admin view).
**Permission:** `ROLE_ADMIN`
### Query Parameters
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `page` | integer | ❌ | Default: 1 |
| `limit` | integer | ❌ | Default: 20 |
| `search` | string | ❌ | Matches `name`, `site_name`, `domain`, **or the parent province's name** (case-insensitive `LIKE`) |
| `province_id` | integer | ❌ | Filter by province |
### Response `200`
Paginated city list. Each row already carries `province_name` alongside `province_id`.
---
## POST `/api/v1/admin/province`
Create a new province.
**Permission:** `ROLE_ADMIN`
### Request Body (`application/json`)
```json
{
"name": "تهران",
"status": "active",
"weight": 1
}
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | ✅ | Province name |
| `status` | string | ❌ | `"active"` (default) or `"inactive"` |
| `weight` | integer | ❌ | Sort weight |
### Response `201`
Province object.
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_AUTH_006` | 403 | Not admin |
| `ERR_VALIDATION_002` | 422 | Missing name |
---
## PATCH `/api/v1/admin/province/{id}`
Update a province.
**Permission:** `ROLE_ADMIN`
### Path Parameters
| Param | Type | Description |
|-------|------|-------------|
| `id` | integer | Province ID |
All fields optional.
### Response `200`
Updated province object.
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_AUTH_006` | 403 | Not admin |
| `ERR_NOT_FOUND_001` | 404 | Province not found |
---
## DELETE `/api/v1/admin/province/{id}`
Delete a province.
**Permission:** `ROLE_ADMIN`
### Response `200`
```json
{ "success": true, "data": { "message": "استان حذف شد" } }
```
---
## POST `/api/v1/admin/city`
Create a new city.
**Permission:** `ROLE_ADMIN`
### Request Body (`application/json`)
```json
{
"name": "تهران",
"site_name": "تهران نوبت",
"province_id": 1,
"status": "active",
"weight": 1
}
```
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | ✅ | City name |
| `site_name` | string | ❌ | Public site name shown on the city's booking website (e.g. `"یزد نوبت"`) |
| `title` | string | ❌ | SEO meta title for the city's booking website (e.g. `"نوبت‌دهی آنلاین پزشکان یزد | یزد نوبت"`) |
| `province_id` | integer | ❌ | Parent province ID |
| `status` | string | ❌ | `"active"` or `"inactive"` |
| `weight` | integer | ❌ | Sort weight |
| `contact_phone`, `email`, `description`, `slogan`, `domain`, `keywords`, `footer_description`, `social_media`, `logo_url` | mixed | ❌ | SEO / branding fields returned in the city object |
### Response `201`
City object.
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_AUTH_001` | 401 | Missing token |
| `ERR_AUTH_006` | 403 | Not admin |
| `ERR_VALIDATION_002` | 422 | Missing name |
---
## PATCH `/api/v1/admin/city/{id}`
Update a city.
**Permission:** `ROLE_ADMIN`
All body fields optional.
### Response `200`
Updated city object.
---
## DELETE `/api/v1/admin/city/{id}`
Delete a city.
**Permission:** `ROLE_ADMIN`
### Response `200`
```json
{ "success": true, "data": { "message": "شهر حذف شد" } }
```
---
## GET `/api/v1/categorys/{bundle}` *(Legacy)*
Legacy endpoint that proxies to the new endpoints.
**Permission:** `PUBLIC`
### Path Parameters
| Bundle | Maps to |
|--------|---------|
| `state` | `/api/v1/provinces` |
| `city` | `/api/v1/cities` |
| `specially_doctor` | `/api/v1/specialties` |
| `doctor_services` | `/api/v1/doctor-services` |
| `insurance_type` | `/api/v1/insurances?type=basic` |
| `supplementary_insurance` | `/api/v1/insurances?type=supplementary` |
| `tag` | `/api/v1/tags` |
> ⚠️ Response is **triple-nested**: `data?.data?.data ?? []`
> Note: `categorys` (not `categories`) is intentional — legacy route name.
---
## Bulk import / export
Full-table JSON export and strict wipe+replace import for this category live under
`/api/v1/admin/categories/{bundle}/{export|import}` — see [category-import.md](category-import.md).
### Sorting by id
The admin list endpoint accepts `sort=id&order=asc|desc` to order by `id`
(used by the admin «دسته‌بندی‌ها» page when clicking the «شناسه» column).
Without `sort`, the default ordering (weight/name) is unchanged.