# Treatment API > **Prefix:** `/api/v1/service-item/{uuid}/treatment-protocol` A **treatment protocol** is the "طول درمان" of a service: it says a course of that service runs over several sessions, when each one falls due, which doctor supervises it, and which staff may perform it. A service without a protocol row is single-session — the row's existence *is* the switch, which is why there is no separate boolean. `ServiceItem.session_count` is **deprecated**. It never had logic behind it; session count now comes from the protocol's step list. The column still appears in service payloads so existing clients do not break, but nothing should read it. Superseded design note: an earlier `src/Course/` module (`CourseProtocol` / `TreatmentCourse`) was deleted in `65d5831c` and its docs removed. It modelled the gap between sessions as one min/ideal/max triple for the whole course, which cannot express a course whose intervals differ per session — a botox course is session 1, then +15 days, then monthly. This design stores an explicit offset per step instead. --- ## The step model Each step carries `offset_days`, and that offset is measured **from the previous session**, not from the start of the course. The spacing of a laser course is a clinical requirement — hair regrows relative to the last treatment, not relative to when the file was opened — so a patient who arrives late shifts the rest of their course rather than getting the next session too early. | Rule | چرا | |---|---| | حداقل ۲ گام | یک گام یعنی سرویس تک‌جلسه‌ای؛ سوییچ اصلاً نباید روشن باشد | | حداکثر ۶۰ گام | سقف عقلانی، جلوی ورودی اشتباه را می‌گیرد | | `step_number` پیوسته از ۱ | «جلسهٔ ۳ از ۸» فقط وقتی معنی دارد که گامی جا نیفتاده باشد | | گام ۱ → `offset_days = 0` | لنگر دوره است و «جلسهٔ قبل» ندارد | | گام‌های بعدی → `offset_days > 0` | فاصلهٔ صفر یعنی دو جلسه در یک روز | | حداقل یک پرسنل مجاز | بدون آن هر پرسنلی پای هر دستگاهی می‌نشیند | --- ## GET `/api/v1/service-item/{uuid}/treatment-protocol` **Permission:** `IS_AUTHENTICATED_FULLY`, محدود به محیط جاری — سرویس محیط دیگر `404` می‌گیرد. `data: null` یعنی سوییچ خاموش است، نه اینکه چیزی پیدا نشد. ### Response `200` ```json { "success": true, "data": { "uuid": "8de51c47-ddd1-44ea-bae1-83cf6457b182", "service_uuid": "cc0b11ec-1c39-45f0-bc1d-5514619bc74a", "active": true, "total_sessions": 4, "supervisor": null, "steps": [ { "step_number": 1, "offset_days": 0 }, { "step_number": 2, "offset_days": 15 }, { "step_number": 3, "offset_days": 30 }, { "step_number": 4, "offset_days": 30 } ], "staff": [ { "uuid": "53acc523-48a7-4f4a-89b1-745e8e7a69bd", "name": "پرسنل۱" } ] } } ``` **Errors:** | Code | HTTP | توضیح | |------|------|-------| | ERR_NOT_FOUND_001 | 404 | سرویس یافت نشد یا مال محیط دیگری است | | ERR_AUTH_001 | 401 | بدون توکن | --- ## PUT `/api/v1/service-item/{uuid}/treatment-protocol` Replace the whole protocol. Creates it on first call, so this doubles as "turn the switch on". Everything is validated **before** anything is written: an invalid step at the end of the list must not wipe the valid steps already stored. Steps and staff are then cleared and rewritten inside one transaction. **Permission:** `IS_AUTHENTICATED_FULLY`, محدود به محیط جاری. ### Request Body (`application/json`) | Field | Type | Required | توضیح | |---|---|---|---| | `steps` | array | ✅ | ۲ تا ۶۰ گام | | `steps[].step_number` | int | ❌ | پیوسته از ۱؛ نبودنش یعنی ترتیب آرایه | | `steps[].offset_days` | int | ✅ | فاصله از جلسهٔ **قبلی** | | `staff_uuids` | string[] | ✅ | حداقل یکی، همه از محیط جاری و فعال؛ تکراری‌ها حذف می‌شوند | | `supervisor_doctor_uuid` | string | ❌ | پزشک ناظر؛ باید عضو همین محیط باشد | ```json { "staff_uuids": ["53acc523-48a7-4f4a-89b1-745e8e7a69bd"], "supervisor_doctor_uuid": null, "steps": [ { "step_number": 1, "offset_days": 0 }, { "step_number": 2, "offset_days": 15 }, { "step_number": 3, "offset_days": 30 }, { "step_number": 4, "offset_days": 30 } ] } ``` ### Response `200` Same shape as GET. **Errors:** | Code | HTTP | Field | توضیح | |------|------|-------|-------| | ERR_VALIDATION_001 | 422 | `steps` | کمتر از ۲ یا بیشتر از ۶۰ گام | | ERR_VALIDATION_002 | 422 | `steps` | فیلد `steps` نیست یا آرایه نیست | | ERR_VALIDATION_002 | 422 | `offset_days` | `offset_days` یک گام نیست یا عدد نیست | | ERR_VALIDATION_001 | 422 | `offset_days` | گام اول صفر نیست، یا گام بعدی صفر/منفی است | | ERR_VALIDATION_001 | 422 | `step_number` | شماره‌ها پیوسته از ۱ نیستند | | ERR_VALIDATION_002 | 422 | `staff_uuids` | فهرست خالی است یا uuid نامعتبر دارد | | ERR_NOT_FOUND_001 | 404 | `staff_uuids` | پرسنل یافت نشد، غیرفعال است، یا مال محیط دیگری است | | ERR_NOT_FOUND_001 | 404 | — | پزشک ناظر عضو این محیط نیست | Real 422 responses: ```json {"success":false,"data":null,"errors":[{"code":"ERR_VALIDATION_001","message":"دورهٔ درمان حداقل 2 جلسه دارد؛ کمتر از آن یعنی سرویس تک‌جلسه‌ای","field":"steps"}]} {"success":false,"data":null,"errors":[{"code":"ERR_VALIDATION_002","message":"حداقل یک پرسنل مجاز الزامی است","field":"staff_uuids"}]} {"success":false,"data":null,"errors":[{"code":"ERR_VALIDATION_001","message":"شمارهٔ گام‌ها باید پیوسته از ۱ باشد؛ گام 2 انتظار می‌رفت","field":"step_number"}]} ``` --- ## DELETE `/api/v1/service-item/{uuid}/treatment-protocol` Turn the switch off — the protocol, its steps and its staff list are removed and the service is single-session again. Idempotent: deleting a service that has no protocol still answers `200`. **Permission:** `IS_AUTHENTICATED_FULLY`, محدود به محیط جاری. ### Response `200` ```json { "success": true, "data": null } ```