Files
clinicpro/docs/api/practice-domain.md
T
hamedandClaude Opus 5 85985b04a0 feat(practice-domain): add practice domains and let a clinic select one
A practice domain is the field a clinic operates in — beauty, dentistry —
and unlike Specialty it is configuration, not a label: treatment workflows
will bind to its code, so the code is immutable once created and only a
platform admin can mint one. A clinic that has not chosen a domain keeps
behaving exactly as it does today.

Assignment reuses PATCH /api/v1/clinic/{uuid} rather than adding a second
endpoint. An unknown domain uuid is rejected instead of silently dropped,
because a lost selection would only surface at the first protocol-driven
booking.

Also corrects ADR-0003: resource occupancy does not in fact guard the panel
booking path, which writes appointments.resource_id and no occupancy row at
all, so the doctor slot key cannot simply be dropped.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 16:06:29 +03:30

4.8 KiB

Practice Domain API

Prefix: /api/v1/practice-domains, /api/v1/practice-domain

A practice domain is the field a clinic operates in — beauty, dentistry, orthopaedics. It is a configuration key, not a marketing label: treatment workflows bind to its code, so the code is immutable once created. It is deliberately not Specialty, which stays a descriptive label for the public booking site.

The table is global (registered in GlobalTables::ENTITIES); a clinic points at zero or one of its rows through clinics.practice_domain_id, which is nullable. NULL means "not configured" and keeps today's behaviour — it is never an error.


GET /api/v1/practice-domains

List domains, ordered by sort_order then name.

Permission: IS_AUTHENTICATED_FULLY. Callers without ROLE_ADMIN see only active rows, so a clinic manager cannot pick a domain the platform has retired. ROLE_ADMIN sees inactive ones too, to be able to switch them back on.

Response 200

{
    "success": true,
    "data": [
        {
            "uuid": "8c7bfd18-9159-11f1-b98b-f28fd8aa5db5",
            "code": "beauty",
            "name": "کلینیک زیبایی",
            "sort_order": 0,
            "active": true
        }
    ]
}

Errors:

Code HTTP توضیح
ERR_AUTH_001 401 بدون توکن

POST /api/v1/practice-domains

Create a domain.

Permission: ROLE_ADMIN (platform admin only). A clinic manager creating its own domain would produce a domain with no workflow behind it, and the misconfiguration would stay invisible until the first protocol-driven booking.

Request Body (application/json)

Field Type Required توضیح
code string ^[a-z0-9_]{1,40}$، یکتا در کل جدول، بعد از ساخت تغییرناپذیر
name string نام نمایشی فارسی
sort_order int پیش‌فرض 0
{ "code": "dental", "name": "دندانپزشکی", "sort_order": 2 }

Response 201

{
    "success": true,
    "data": {
        "uuid": "af5063de-753f-444a-ba95-05ec2ffe13be",
        "code": "dental",
        "name": "دندانپزشکی",
        "sort_order": 2,
        "active": true
    }
}

Errors:

Code HTTP توضیح
ERR_VALIDATION_001 422 بدنهٔ نامعتبر، یا کد خارج از الگو، یا کد تکراری (field: code)
ERR_VALIDATION_002 422 name خالی است (field: name)
ERR_FORBIDDEN_001 403 کاربر ROLE_ADMIN نیست
ERR_AUTH_001 401 بدون توکن

Real 422 for a duplicate code:

{"success":false,"data":null,"errors":[{"code":"ERR_VALIDATION_001","message":"حوزه فعالیتی با این کد از قبل وجود دارد","field":"code"}]}

PATCH /api/v1/practice-domain/{uuid}

Update a domain's display fields.

Permission: ROLE_ADMIN.

code is ignored if sent. Workflow implementations are resolved by code, so renaming it would silently detach a live clinic from its workflow.

Request Body (application/json)

Field Type توضیح
name string فقط اگر ناتهی باشد اعمال می‌شود
sort_order int
active bool

Response 200

{
    "success": true,
    "data": {
        "uuid": "af5063de-753f-444a-ba95-05ec2ffe13be",
        "code": "dental",
        "name": "دندان‌پزشکی",
        "sort_order": 5,
        "active": true
    }
}

Errors:

Code HTTP توضیح
ERR_VALIDATION_001 422 بدنهٔ درخواست نامعتبر است
ERR_VALIDATION_002 404 حوزه فعالیت یافت نشد
ERR_FORBIDDEN_001 403 کاربر ROLE_ADMIN نیست

Assigning a domain to a clinic

There is no dedicated endpoint. The existing PATCH /api/v1/clinic/{uuid} accepts one more key — see clinic.md.

Body اثر
"practice_domain_uuid": "<uuid>" حوزه ست می‌شود
"practice_domain_uuid": "" یا null حوزه پاک می‌شود
کلید اصلاً نباشد حوزهٔ فعلی دست‌نخورده می‌ماند

An unknown uuid is rejected rather than ignored, because a silently dropped selection would only surface at the first protocol-driven booking:

{"success":false,"data":null,"errors":[{"code":"ERR_VALIDATION_002","message":"حوزه فعالیت یافت نشد","field":"practice_domain_uuid"}]}

GET /api/v1/clinic/{uuid} returns the current value under data.data.practice_domain, null when unset:

{"uuid":"8c7bfd18-9159-11f1-b98b-f28fd8aa5db5","code":"beauty","name":"کلینیک زیبایی","sort_order":0,"active":true}