- Fix national code handling in staff creation and updates to support Persian digits. - Update ClinicStaff entity to allow longer national codes (up to 15 characters). - Implement support for clinic secretaries in SecretaryController, allowing creation without a doctor UUID. - Add a new endpoint to retrieve doctors associated with a clinic for secretary management. - Improve appointment management by ensuring doctors are selectable even when no appointments exist. - Extend PatientController to allow secretaries to create patient records if they have the appropriate permissions. - Introduce a PriceInput component for better price formatting in forms, supporting Persian digits. - Add a MockGateway for testing payment processes without real transactions. - Enhance SMS settings management with an approval flow for post-visit text messages, including new fields for pending text and status. - Update migrations to reflect changes in database schema for national codes and SMS settings.
5.6 KiB
Patient Records & Sessions API
Overview
Patient records track patients per entity (doctor or clinic). Each record holds multiple sessions (visits). Access requires an active subscription with the patient_records feature.
Base path: /api/v1
Auth: Bearer JWT (doctor, clinic, or secretary with appointments.view permission required)
Endpoints
List Patients
GET /api/v1/patients
Returns a paginated list of patient records belonging to the authenticated entity.
Query params:
| Param | Type | Default | Description |
|---|---|---|---|
page |
int | 1 | Page number |
limit |
int | 20 | Items per page (10–50) |
search |
string | — | Search by patient name or phone |
Response 200:
{
"success": true,
"data": [
{
"uuid": "...",
"entity_type": "doctor",
"entity_id": 5,
"user": { "uuid": "...", "fullName": "علی رضایی", "phone": "09123456789" },
"created_by_type": "doctor",
"created_by_id": 5,
"created_at": 1718375000
}
],
"meta": {
"totalRecords": 42,
"totalPages": 3,
"currentPage": 1
}
}
Errors:
| Code | HTTP | Description |
|---|---|---|
ERR_SUBSCRIPTION_REQUIRED |
403 | No active plan with patient_records feature |
Create Patient Record
POST /api/v1/patient
Creates a patient record for a user under the current entity. If the record already exists, returns the existing record (idempotent).
Request body:
{
"user_uuid": "string (required)"
}
Response 201:
{
"success": true,
"data": {
"uuid": "...",
"entity_type": "doctor",
"entity_id": 5,
"user": { "uuid": "...", "fullName": "...", "phone": "..." },
"created_by_type": "doctor",
"created_by_id": 5,
"created_at": 1718375000
}
}
Errors:
| Code | HTTP | Description |
|---|---|---|
ERR_VALIDATION_001 |
422 | user_uuid missing |
ERR_NOT_FOUND_001 |
404 | User not found |
ERR_SUBSCRIPTION_REQUIRED |
403 | No patient_records feature |
Get Patient Record
GET /api/v1/patient/{uuid}
Returns a single patient record.
Response 200:
{
"success": true,
"data": {
"uuid": "...",
"entity_type": "doctor",
"entity_id": 5,
"user": { "uuid": "...", "fullName": "...", "phone": "..." },
"created_by_type": "doctor",
"created_by_id": 5,
"created_at": 1718375000
}
}
Errors:
| Code | HTTP | Description |
|---|---|---|
ERR_PATIENT_NOT_FOUND |
404 | Record not found or not owned by caller |
ERR_SUBSCRIPTION_REQUIRED |
403 | No patient_records feature |
List Patient Sessions
GET /api/v1/patient/{uuid}/sessions
Returns paginated sessions for a patient record.
Query params: page, limit (same as list)
Response 200:
{
"success": true,
"data": [
{
"uuid": "...",
"record_uuid": "...",
"appointment_uuid": null,
"insurance_base_id": null,
"insurance_supplementary_id": null,
"visit_price_rials": 200000,
"base_insurance_discount_percent": "10.00",
"supplementary_discount_percent": "5.00",
"services_total_rials": 50000,
"final_price_rials": 230000,
"payment_method": "cash",
"notes": "...",
"created_at": 1718375000,
"updated_at": 1718375000
}
],
"meta": { "totalRecords": 8, "totalPages": 1, "currentPage": 1 }
}
Errors:
| Code | HTTP | Description |
|---|---|---|
ERR_PATIENT_NOT_FOUND |
404 | Record not found or not owned by caller |
ERR_SUBSCRIPTION_REQUIRED |
403 | No patient_records feature |
Create Session
POST /api/v1/patient/{uuid}/session
Creates a new visit session for a patient record.
Request body:
{
"visit_price_rials": 200000,
"base_insurance_discount_percent": 10,
"supplementary_discount_percent": 5,
"insurance_base_id": null,
"insurance_supplementary_id": null,
"payment_method": "cash",
"notes": "...",
"services": [
{
"service_item_uuid": "...",
"staff_uuid": null
}
]
}
Field notes:
payment_method:cash|card|insurance|online|pendingservices: array of service items to attach;price_rialsis snapshot-copied from ServiceItemfinal_price_rialsis computed:(visit_price × (1 - base%) × (1 - supp%)) + services_total
Response 201:
{
"success": true,
"data": { ...session object... }
}
Errors:
| Code | HTTP | Description |
|---|---|---|
ERR_PATIENT_NOT_FOUND |
404 | Record not found or not owned |
ERR_SUBSCRIPTION_REQUIRED |
403 | No patient_records feature |
Update Session
PATCH /api/v1/session/{uuid}
Updates mutable fields on a session.
Request body (all optional):
{
"notes": "...",
"payment_method": "card"
}
Response 200:
{
"success": true,
"data": { ...session object... }
}
Errors:
| Code | HTTP | Description |
|---|---|---|
ERR_SESSION_NOT_FOUND |
404 | Session not found or not owned |
Auto-Creation on Appointment Confirm
When an appointment's status changes to confirmed via PATCH /api/v1/appointment/{uuid}/status, the system automatically:
- Creates a
PatientRecordfor the appointment's user (if not already existing) under the doctor entity - Creates a blank
PatientSessionlinked to the appointment
This only runs if the doctor has the patient_records subscription feature active.