- Implemented ClinicFormPage for adding new clinics with validation. - Created MyFinancialPage to display financial summaries and charts. - Developed MyPatientsPage for managing patient data with search and pagination. - Added PreRegistrationsPage for handling pre-registration requests with approval and rejection functionalities. - Introduced database migration for pre_registrations table. - Built PreRegistrationController for managing pre-registration logic, including submission, approval, and rejection. - Created PreRegistration entity and repository for handling pre-registration data.
18 KiB
Admin API
Prefix:
/api/v1/admin
Permission: ALL endpoints in this file requireROLE_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
{
"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
{
"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
{
"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
{
"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
{
"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
{
"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)
{
"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)
{
"role": "ROLE_DOCTOR"
}
| Field | Type | Required | Allowed Values |
|---|---|---|---|
role |
string | ✅ | ROLE_USER, ROLE_DOCTOR, ROLE_CLINIC, ROLE_SECRETARY, ROLE_ADMIN |
Response 200
{ "success": true, "data": { "message": "نقش کاربر تغییر کرد", "roles": ["ROLE_DOCTOR"] } }
POST /api/v1/admin/users/{uuid}/status
Toggle user active/inactive status.
Permission: ROLE_ADMIN
Response 200
{ "success": true, "data": { "status": "inactive" } }
DELETE /api/v1/admin/users/{uuid}
Delete a user.
Permission: ROLE_ADMIN
Response 200
{ "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
{
"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
{
"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
{ "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
{
"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
{ "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
{ "success": true, "data": { "message": "کلینیک حذف شد" } }
Appointment Management
GET /api/v1/admin/appointments/today-stats
Get appointment statistics for a specific date (defaults to today).
Permission: ROLE_ADMIN
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
date |
string (YYYY-MM-DD) | ❌ | Default: today |
Response 200
{
"success": true,
"data": {
"total": 47,
"completed": 20,
"waiting": 18,
"cancelled": 9
}
}
GET /api/v1/admin/appointments
List appointments filtered by date and/or doctor. Sorted by slot_start ASC.
Permission: ROLE_ADMIN
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
page |
integer | ❌ | Default: 1 |
limit |
integer | ❌ | Default: 15, max: 500 |
search |
string | ❌ | Search by patient name/mobile or doctor name |
status |
string | ❌ | Filter by status |
date |
string (YYYY-MM-DD) | ❌ | Filter by slot date |
doctor_uuid |
string | ❌ | Filter by doctor UUID |
Response 200
{
"success": true,
"data": [
{
"uuid": "appt-uuid",
"patient_name": "محمد رضایی",
"patient_mobile": "09123456789",
"doctor_uuid": "doctor-uuid",
"doctor_name": "دکتر علی احمدی",
"slot_start": 1718438400,
"slot_end": 1718439600,
"appointment_date": "2025-06-15",
"appointment_time": "09:00",
"end_time": "09:20",
"status": "confirmed",
"version": 1,
"created_at": "2025-06-14T10:30:00+03:30"
}
],
"meta": { "totalRecords": 47, "totalPages": 1, "currentPage": 1 }
}
Status values: pending | confirmed | completed | cancelled_by_doctor | cancelled_by_user | no_show | expired
POST /api/v1/admin/appointment
Create a new appointment for a patient. If no user exists with the given mobile, a new user account is created automatically.
Permission: ROLE_ADMIN
Request Body
{
"doctor_uuid": "doctor-uuid",
"slot_start": 1718438400,
"slot_end": 1718439600,
"patient_mobile": "09123456789",
"patient_name": "علی محمدی",
"note": "optional note"
}
patient_mobileوpatient_nameهر دو اجباری هستند. اگر کاربری با این شماره موبایل نداشته باشیم، یک کاربر جدید با نقشROLE_USERساخته میشود.
Response 201
{
"success": true,
"data": {
"uuid": "appt-uuid",
"slot_start": 1718438400,
"slot_end": 1718439600,
"status": "pending"
}
}
Error Responses
| Code | HTTP | Description |
|---|---|---|
VALIDATION |
422 | Missing required fields (doctor_uuid, slot_start, slot_end, patient_mobile, patient_name) |
DOCTOR_NOT_FOUND |
404 | Doctor UUID not found |
SLOT_TAKEN |
409 | Slot already booked |
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
{
"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
{
"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}/approveor/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}/approveor/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
{
"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
{
"success": true,
"data": [
{
"uuid": "...",
"name": "تأیید نوبت",
"status": "approved",
"provider_code": "verify_appointment",
"created_at": 1717000000
}
]
}
To create/approve/reject templates, see sms.md
Clinic Invitation Management
See 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
{
"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):
{
"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"= inactivecommission_percent— integer string,0–100- Commission applies only to regular users (
booked_by = user); secretaries are exempt
Pre-Registration Management
GET /api/v1/admin/pre-registrations
List pre-registration requests. Permission: ROLE_ADMIN
Query params:
| Param | Default | Notes |
|---|---|---|
page |
1 | |
limit |
20 | max 50 |
status |
pending |
pending | approved | rejected | all |
Response 200 (paginated):
{
"success": true,
"data": [
{
"uuid": "...",
"type": "independent_doctor",
"name": "دکتر احمدی",
"mobile": "09121234567",
"info": "متخصص داخلی",
"status": "pending",
"admin_note": null,
"created_at": 1718000000
}
],
"meta": { "totalRecords": 5, "totalPages": 1, "currentPage": 1 }
}
POST /api/v1/admin/pre-registrations/{uuid}/approve
Approve a pending request. Creates User + Doctor/Clinic entity based on type, resets password, sends SMS. Permission: ROLE_ADMIN
Response 200:
{ "success": true, "data": { "message": "تأیید شد و اطلاعات ورود ارسال گردید" } }
Error Codes:
| Code | HTTP | Meaning |
|---|---|---|
NOT_FOUND |
404 | UUID not found |
ALREADY_PROCESSED |
409 | Status is not pending |
POST /api/v1/admin/pre-registrations/{uuid}/reject
Reject a pending request. Permission: ROLE_ADMIN
Request body (optional):
{ "note": "مدارک ناقص است" }
Response 200:
{ "success": true, "data": { "message": "درخواست رد شد" } }