Files
clinicpro/docs/api/patient.md
T
hamedandClaude Opus 4.8 af881231d0 fix: store appointment address from schedule and auto-add patient to clinic
Appointments now persist address_id resolved from the weekly-schedule
session (location_id) across all booking paths (online, secretary, admin).
On confirm, the patient is added to the clinic owning that address, or to
the doctor's single clinic as fallback. Weekly-schedule create/update now
requires location_id on every active session. PatientSession exposes
doctor_uuid/doctor_name so clinic records show which doctor each visit is for.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 16:10:36 +03:30

7.9 KiB
Raw Blame History

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 (1050)
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).

سه حالت پشتیبانی می‌شود:

  1. کاربر ثبت‌نام‌کرده با uuid: user_uuid ارسال شود.
  2. کاربر ثبت‌نام‌کرده با موبایل: mobile ارسال شود (کاربر موجود پیدا می‌شود).
  3. بیمار جدید بدون ثبت‌نام: mobile + name ارسال شود؛ اگر کاربری با آن موبایل نباشد، User جدید (نقش ROLE_USER، بدون رمز عبور) ساخته می‌شود سپس پرونده.

Request body:

{
  "user_uuid": "string (اختیاری)",
  "mobile": "09xxxxxxxxx (اختیاری — برای جستجو یا ساخت بیمار جدید)",
  "name": "string (الزامی فقط هنگام ساخت بیمار جدید)",
  "national_code": "string (اختیاری، ۱۰ رقم)"
}
  • اگر user_uuid و mobile هر دو خالی باشند → خطا.
  • national_code فقط وقتی روی کاربر ست می‌شود که کاربر کد ملی نداشته باشد.
  • موبایل تکراری duplicate نمی‌سازد؛ همان کاربر استفاده می‌شود.

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/mobile خالی، یا موبایل/کد ملی نامعتبر، یا نام برای بیمار جدید خالی
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 | pending
  • services: array of service items to attach; price_rials is snapshot-copied from ServiceItem
  • final_price_rials is 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:

  1. Creates a PatientRecord for the appointment's user (if not already existing) under the doctor entity
  2. Creates a blank PatientSession linked to the appointment
  3. اگر نوبت با آدرس کلینیک ثبت شده باشد (appointment.address_idDoctorAddress.clinic_id)، همان دو مرحله برای آن کلینیک (entity_type='clinic') هم تکرار می‌شود. اگر آدرس نوبت کلینیک نداشت ولی دکتر فقط عضو یک کلینیک بود، به همان کلینیک اضافه می‌شود.

هر شاخه (doctor / clinic) مستقل و فقط در صورت فعال‌بودن ویژگی patient_records برای همان entity اجرا می‌شود. duplicate با findByEntityAndUser جلوگیری می‌شود.

انتساب پزشک: هر PatientSession در پاسخ، doctor_uuid و doctor_name را از روی نوبتِ متناظر برمی‌گرداند؛ پس در پرونده‌ی کلینیک مشخص است هر مراجعه برای کدام پزشک بوده است.

آدرس نوبت: هنگام رزرو، address_id خودکار از location_id همان session برنامه‌ی هفتگی ست می‌شود (در همه‌ی مسیرهای رزرو). ثبت location_id برای هر شیفت فعال در برنامه‌ی هفتگی الزامی است (POST/PATCH /api/v1/appointment-settings/weekly-schedule)؛ در غیر این صورت 422.