Files
clinicpro/docs/api/admin.md
T
hamed e7b90a6399 feat(api): add dashboard endpoints for clinic, doctor, and secretary roles
- Implemented GET /api/v1/dashboard/clinic to return clinic stats and today's schedule for clinic owners.
- Implemented GET /api/v1/dashboard/doctor to return doctor's stats and today's schedule for doctors.
- Implemented GET /api/v1/dashboard/secretary to return stats and conditional appointments for secretaries.

feat(migrations): create user_active_context and mobile_verification_otp tables

- Added migration to create user_active_context table for tracking active user sessions.
- Added migration to create mobile_verification_otp table for handling mobile number verification.

feat(migrations): create site_config table for application settings

- Added migration to create site_config table to store various site configuration settings.

feat(appointments): create MyAppointmentsController for user-specific appointments

- Added MyAppointmentsController to handle fetching user-specific appointments with pagination and filtering.

feat(auth): implement NotificationMobileController for mobile number verification

- Added NotificationMobileController to handle OTP requests and verification for mobile number changes.

feat(auth): create MobileVerificationOtp entity for OTP management

- Created MobileVerificationOtp entity to manage OTP records for mobile verification.

feat(auth): create UserActiveContext entity for user session management

- Created UserActiveContext entity to manage user active sessions.

feat(config): implement SiteConfigController for managing site settings

- Added SiteConfigController to handle fetching and updating site configuration settings.

feat(config): create SiteConfig entity and repository for configuration management

- Created SiteConfig entity and repository to manage site configuration data.
2026-06-11 12:20:12 +03:30

725 lines
14 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.
# Admin API
> **Prefix:** `/api/v1/admin`
> **Permission:** ALL endpoints in this file require `ROLE_ADMIN`
> **Headers:** `Authorization: Bearer <admin_jwt_token>`
---
## Dashboard
### GET `/api/v1/admin/dashboard/stats`
Get key performance indicators (KPIs) for the dashboard.
**Permission:** `ROLE_ADMIN`
### Response `200`
```json
{
"success": true,
"data": {
"total_users": 1200,
"active_doctors": 85,
"total_doctors": 92,
"total_clinics": 34,
"today_appointments": 47,
"total_appointments": 8540,
"today_payments_count": 30,
"today_payments_amount": 15000000,
"total_payments_amount": 425000000,
"pending_comments": 12,
"pending_settlements": 5,
"this_month_revenue": 52000000,
"this_month_appointments": 620
}
}
```
---
### GET `/api/v1/admin/dashboard/charts`
Get chart data for the last 30 days.
**Permission:** `ROLE_ADMIN`
### Response `200`
```json
{
"success": true,
"data": {
"appointments_30d": [
{ "date": "2024-06-01", "count": 42 }
],
"revenue_30d": [
{ "date": "2024-06-01", "amount_rials": 21000000 }
],
"appointment_status": {
"confirmed": 350,
"completed": 180,
"cancelled": 45,
"pending": 20,
"no_show": 25
},
"top_specialties": [
{ "name": "قلب و عروق", "count": 120 }
]
}
}
```
---
### GET `/api/v1/admin/dashboard/recent`
Get recent activity (last 10 of each type).
**Permission:** `ROLE_ADMIN`
### Response `200`
```json
{
"success": true,
"data": {
"appointments": [
{
"uuid": "...",
"doctor_title": "دکتر علی احمدی",
"patient_name": "محمد رضایی",
"slot_start": 1718438400,
"status": "confirmed"
}
],
"payments": [
{
"uuid": "...",
"amount_rials": 500000,
"gateway": "mellat",
"status": "paid",
"created_at": 1717000000
}
],
"users": [
{
"uuid": "...",
"real_name": "محمد رضایی",
"mobile_number": "09...",
"roles": ["ROLE_USER"],
"created_at": 1717000000
}
]
}
}
```
---
## User Management
### GET `/api/v1/admin/users`
List all users with pagination and filters.
**Permission:** `ROLE_ADMIN`
### Query Parameters
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `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. |
| `status` | string | ❌ | `"active"` or `"inactive"` |
| `sort` | string | ❌ | `"created_at"` (default desc) |
### Response `200`
```json
{
"success": true,
"data": [
{
"uuid": "...",
"real_name": "علی احمدی",
"mobile_number": "09123456789",
"roles": ["ROLE_USER"],
"status": "active",
"created_at": 1717000000
}
],
"meta": { "totalRecords": 1200, "totalPages": 60, "currentPage": 1 }
}
```
---
### GET `/api/v1/admin/users/{uuid}`
Get detailed user info.
**Permission:** `ROLE_ADMIN`
### Response `200`
```json
{
"success": true,
"data": {
"uuid": "...",
"real_name": "علی احمدی",
"mobile_number": "09123456789",
"roles": ["ROLE_USER"],
"status": "active",
"wallet_balance_rials": 500000,
"appointments_count": 5,
"created_at": 1717000000
}
}
```
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_NOT_FOUND_001` | 404 | User not found |
---
### GET `/api/v1/admin/users/stats`
Get user statistics.
**Permission:** `ROLE_ADMIN`
### Response `200`
```json
{
"success": true,
"data": {
"total": 1200,
"active": 1150,
"inactive": 50,
"admins": 3,
"doctors": 92,
"patients": 1100
}
}
```
---
### PUT `/api/v1/admin/users/{uuid}`
Update user info (name, email, password).
**Permission:** `ROLE_ADMIN`
### Request Body (`application/json`)
```json
{
"real_name": "علی احمدی جدید",
"password": "newPassword123"
}
```
### Response `200`
Updated user object.
---
### PUT `/api/v1/admin/users/{uuid}/role`
Change a user's role.
**Permission:** `ROLE_ADMIN`
### Request Body (`application/json`)
```json
{
"role": "ROLE_DOCTOR"
}
```
| Field | Type | Required | Allowed Values |
|-------|------|----------|----------------|
| `role` | string | ✅ | `ROLE_USER`, `ROLE_DOCTOR`, `ROLE_CLINIC`, `ROLE_SECRETARY`, `ROLE_ADMIN` |
### Response `200`
```json
{ "success": true, "data": { "message": "نقش کاربر تغییر کرد", "roles": ["ROLE_DOCTOR"] } }
```
---
### POST `/api/v1/admin/users/{uuid}/status`
Toggle user active/inactive status.
**Permission:** `ROLE_ADMIN`
### Response `200`
```json
{ "success": true, "data": { "status": "inactive" } }
```
---
### DELETE `/api/v1/admin/users/{uuid}`
Delete a user.
**Permission:** `ROLE_ADMIN`
### Response `200`
```json
{ "success": true, "data": { "message": "کاربر حذف شد" } }
```
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_NOT_FOUND_001` | 404 | User not found |
---
## Doctor Management
### GET `/api/v1/admin/doctors`
List all doctors with pagination.
**Permission:** `ROLE_ADMIN`
### Query Parameters
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `page` | integer | ❌ | Default: 1 |
| `limit` | integer | ❌ | Default: 20 |
| `search` | string | ❌ | Search in title |
| `status` | string | ❌ | `"active"` or `"inactive"` |
| `gender` | string | ❌ | `"male"` or `"female"` |
| `specialty_id` | integer | ❌ | Filter by specialty |
| `sort` | string | ❌ | Sort field |
### Response `200`
```json
{
"success": true,
"data": [
{
"uuid": "...",
"title": "دکتر علی احمدی",
"degree": "متخصص",
"gender": "male",
"doctor_rate": 4.5,
"active_doctor_appointment": true
}
],
"meta": { "totalRecords": 92, "totalPages": 5, "currentPage": 1 }
}
```
---
### GET `/api/v1/admin/doctors/stats`
Get doctor statistics.
**Permission:** `ROLE_ADMIN`
### Response `200`
```json
{
"success": true,
"data": {
"total": 92,
"active": 85,
"inactive": 7,
"male": 60,
"female": 32,
"top_specialty": "قلب و عروق"
}
}
```
---
### POST `/api/v1/admin/doctors/{uuid}/status`
Toggle doctor active status.
**Permission:** `ROLE_ADMIN`
### Response `200`
```json
{ "success": true, "data": { "active": false } }
```
---
## Clinic Management
### GET `/api/v1/admin/clinics`
List all clinics with pagination.
**Permission:** `ROLE_ADMIN`
### Query Parameters
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `page` | integer | ❌ | Default: 1 |
| `limit` | integer | ❌ | Default: 20 |
| `search` | string | ❌ | Search by clinic name |
| `status` | string | ❌ | `"active"` or `"inactive"` |
### Response `200`
```json
{
"success": true,
"data": [
{
"uuid": "...",
"name": "کلینیک الوند",
"city": "تهران",
"telephone": "02112345678",
"is_active": true,
"created_at": 1717000000
}
],
"meta": { "totalRecords": 34, "totalPages": 2, "currentPage": 1 }
}
```
---
### PATCH `/api/v1/admin/clinic/{uuid}/status`
Toggle clinic active/inactive.
**Permission:** `ROLE_ADMIN`
### Response `200`
```json
{ "success": true, "data": { "is_active": false } }
```
### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_NOT_FOUND_001` | 404 | Clinic not found |
---
### DELETE `/api/v1/admin/clinic/{uuid}`
Delete a clinic.
**Permission:** `ROLE_ADMIN`
### Response `200`
```json
{ "success": true, "data": { "message": "کلینیک حذف شد" } }
```
---
## Appointment Management
### GET `/api/v1/admin/appointments`
List all appointments.
**Permission:** `ROLE_ADMIN`
### Query Parameters
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `page` | integer | ❌ | Default: 1 |
| `limit` | integer | ❌ | Default: 20 |
| `search` | string | ❌ | Search by doctor/patient name |
| `status` | string | ❌ | Filter by status |
### Response `200`
```json
{
"success": true,
"data": [
{
"uuid": "...",
"doctor_title": "دکتر علی احمدی",
"patient_name": "محمد رضایی",
"slot_start": 1718438400,
"status": "confirmed",
"price": 500000
}
],
"meta": { "totalRecords": 8540, "totalPages": 427, "currentPage": 1 }
}
```
---
## Payment Management
### GET `/api/v1/admin/payments`
List all payments.
**Permission:** `ROLE_ADMIN`
### Query Parameters
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `page` | integer | ❌ | Default: 1 |
| `limit` | integer | ❌ | Default: 20 |
| `status` | string | ❌ | `"pending"`, `"paid"`, `"failed"`, `"cancelled"` |
### Response `200`
```json
{
"success": true,
"data": [
{
"uuid": "...",
"order_id": "CLINICPRO-...",
"amount_rials": 500000,
"status": "paid",
"gateway": "mellat",
"created_at": 1717000000
}
],
"meta": { "totalRecords": 7800, "totalPages": 390, "currentPage": 1 }
}
```
---
## Settlement Management
### GET `/api/v1/admin/settlements`
List all settlement requests.
**Permission:** `ROLE_ADMIN`
### Query Parameters
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `page` | integer | ❌ | Default: 1 |
| `limit` | integer | ❌ | Default: 20 |
| `status` | string | ❌ | `"pending"`, `"approved"`, `"rejected"` |
### Response `200`
```json
{
"success": true,
"data": [
{
"uuid": "...",
"user": { "uuid": "...", "real_name": "دکتر علی احمدی" },
"amount_rials": 1000000,
"status": "pending",
"bank_account": { "bank_name": "بانک ملت", "owner_name": "..." },
"created_at": 1717000000
}
],
"meta": { "totalRecords": 45, "totalPages": 3, "currentPage": 1 }
}
```
> To approve or reject, use the Settlement API: `POST /api/v1/settlement/{uuid}/approve` or `/reject`
---
## Representation Management
### GET `/api/v1/admin/representations`
List all representations.
**Permission:** `ROLE_ADMIN`
### Query Parameters
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `page` | integer | ❌ | Default: 1 |
| `limit` | integer | ❌ | Default: 20 |
| `search` | string | ❌ | Search by name |
| `city_id` | integer | ❌ | Filter by city |
### Response `200`
Paginated representation list.
---
## Secretary Management
### GET `/api/v1/admin/secretaries`
List all secretaries.
**Permission:** `ROLE_ADMIN`
### Query Parameters
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `page` | integer | ❌ | Default: 1 |
| `limit` | integer | ❌ | Default: 20 |
| `search` | string | ❌ | Search by mobile |
### Response `200`
Paginated secretary list with linked doctor info.
---
## Rating & Comment Management
### GET `/api/v1/admin/rates`
List all ratings.
**Permission:** `ROLE_ADMIN`
### Query Parameters
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `page` | integer | ❌ | Default: 1 |
| `limit` | integer | ❌ | Default: 20 |
| `search` | string | ❌ | Search by doctor/patient |
---
### GET `/api/v1/admin/comments`
List all comments (all statuses).
**Permission:** `ROLE_ADMIN`
### Query Parameters
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `page` | integer | ❌ | Default: 1 |
| `limit` | integer | ❌ | Default: 20 |
| `search` | string | ❌ | Search in body |
| `status` | string | ❌ | `"pending"`, `"approved"`, `"rejected"` |
> To approve/reject comments, use the Rating API: `POST /api/v1/admin/comment/{uuid}/approve` or `/reject`
---
## SMS Management (Admin)
### GET `/api/v1/admin/sms/logs`
List SMS send logs.
**Permission:** `ROLE_ADMIN`
### Query Parameters
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `page` | integer | ❌ | Default: 1 |
| `limit` | integer | ❌ | Default: 20 |
### Response `200`
```json
{
"success": true,
"data": [
{
"id": 1,
"mobile": "09123456789",
"message": "کد تأیید: 123456",
"provider": "kavenegar",
"success": true,
"created_at": 1717000000
}
],
"meta": { "totalRecords": 5000, "totalPages": 250, "currentPage": 1 }
}
```
---
### GET `/api/v1/admin/sms/templates`
List all SMS templates.
**Permission:** `ROLE_ADMIN`
### Response `200`
```json
{
"success": true,
"data": [
{
"uuid": "...",
"name": "تأیید نوبت",
"status": "approved",
"provider_code": "verify_appointment",
"created_at": 1717000000
}
]
}
```
> To create/approve/reject templates, see [sms.md](sms.md)
---
## Clinic Invitation Management
> See [clinic-invitation.md](clinic-invitation.md) for full endpoint details.
| Endpoint | Description |
|----------|-------------|
| `POST /api/v1/admin/clinic/{uuid}/invite-doctor` | Send invitation |
| `GET /api/v1/admin/clinic/{uuid}/invitations` | List invitations |
| `POST /api/v1/admin/clinic/invitation/{invUuid}/resend` | Resend SMS |
| `PATCH /api/v1/admin/clinic/invitation/{invUuid}/status` | Change status |
| `DELETE /api/v1/admin/clinic/invitation/{invUuid}` | Delete |
---
## Settings
### GET /api/v1/admin/settings
Returns all site configuration values.
**Response `200`**
```json
{
"success": true,
"data": {
"commission_enabled": "0",
"commission_percent": "0",
"site_name": "ClinicPro",
"support_phone": "",
"max_cancel_hours_before": "24",
"appointment_reminder_hours": "2"
}
}
```
All values are strings. Missing keys return their default values.
### PATCH /api/v1/admin/settings
Update one or more settings. Unknown keys are silently ignored.
**Request body** (partial update — send only keys to change):
```json
{
"commission_enabled": "1",
"commission_percent": "5",
"site_name": "کلینیک‌پرو"
}
```
**Response `200`** — same shape as GET, returns all settings after save.
**Commission rules:**
- `commission_enabled``"1"` = active, `"0"` = inactive
- `commission_percent` — integer string, `0``100`
- Commission applies only to regular users (`booked_by = user`); secretaries are exempt