# تسک ۱۲ — دوره درمان **فاز:** ۳ (کسب‌وکار) · **وابستگی:** ۰۷، ۱۱ · **زمان:** ۱۶-۲۰ ساعت --- ## هدف مستند بند ۱۳: «لیزر معمولاً شش تا هشت جلسه است. طراحی قبلی فقط نوبت تکی می‌شناخت، در حالی که این حالت اصلی کسب‌وکار است.» ## وضعیت فعلی هیچ مفهومی از دوره وجود ندارد. `PatientSession` وجود دارد ولی «مراجعهٔ انجام‌شده» است، نه جلسهٔ برنامه‌ریزی‌شدهٔ یک دوره. تسک ۰۴ ستون `session_count` را به `ServiceItem` اضافه کرده ولی هیچ رفتاری به آن وصل نیست. ## دامنه **هست:** - `CourseProtocol` — پروتکل دوره: تعداد جلسه، فاصلهٔ حداقل/ایده‌آل/حداکثر، پارامتر هر جلسه - `TreatmentCourse` — دورهٔ یک بیمار - `CourseSession` — جلسات دوره (برنامه‌ریزی‌شده یا انجام‌شده) - رزرو کل دوره یکجا، یا جلسه‌به‌جلسه - پیشنهاد تاریخ جلسهٔ بعدی - هشدار عبور از حداکثر فاصله - ردیابی پیشرفت («جلسهٔ ۳ از ۸») - ترجیح **همان منبع قبلی** (استراتژی `same_as_previous` تسک ۰۶) **نیست:** موتور قانون فاصله (تسک ۰۹ — `spacing` از آن استفاده می‌شود)، پکیج (تسک ۱۱ — اتصال دارد ولی مستقل است). ## Endpoint ها | متد | مسیر | توضیح | |---|---|---| | GET/POST | `/api/v1/course-protocols` | پروتکل دوره per سرویس | | GET/PATCH/DELETE | `/api/v1/course-protocol/{uuid}` | | | POST | `/api/v1/treatment-course` | شروع دوره برای بیمار | | GET | `/api/v1/treatment-course/{uuid}` | جزئیات + جلسات + پیشرفت | | GET | `/api/v1/patient/{uuid}/courses` | دوره‌های بیمار | | POST | `/api/v1/treatment-course/{uuid}/book-all` | رزرو همهٔ جلسات باقی‌مانده | | GET | `/api/v1/treatment-course/{uuid}/next-slot-suggestion` | پیشنهاد تاریخ جلسهٔ بعدی | | POST | `/api/v1/treatment-course/{uuid}/abandon` | رهاکردن دوره با دلیل | ## معیار پذیرش - ✅ موفق: پروتکل «لیزر فول‌بادی: ۸ جلسه، حداقل ۲۱ / ایده‌آل ۲۸ / حداکثر ۴۵ روز، سطح انرژی ۱۲،۱۴،۱۶،۱۸،۲۰،۲۰،۲۲،۲۲» تعریف می‌شود → `POST /treatment-course` هشت `CourseSession` با وضعیت `planned` می‌سازد و پارامتر هر جلسه را از پروتکل کپی می‌کند. - ✅ موفق: `POST /book-all` → هشت نوبت با فاصلهٔ ایده‌آل ۲۸ روز رزرو می‌شود؛ هر جلسه به `CourseSession` متناظر لینک می‌شود. اگر روز ایده‌آل ظرفیت نداشت، **نزدیک‌ترین روز داخل بازهٔ حداقل..حداکثر** انتخاب می‌شود. - ✅ موفق: بعد از انجام جلسهٔ ۳، `GET /next-slot-suggestion` تاریخ ۲۸ روز بعد از **جلسهٔ ۳** را پیشنهاد می‌دهد (نه از شروع دوره). - ✅ موفق: بیمار ۵۰ روز از جلسهٔ قبل گذشته → پاسخ شامل `warning: 'از حداکثر فاصلهٔ مجاز (۴۵ روز) عبور شده است'`. - ✅ موفق: جلسهٔ ۲ به بعد، `same_as_previous` اپراتور جلسهٔ ۱ را انتخاب می‌کند اگر آزاد باشد. - ✅ موفق: پیشرفت — `GET /treatment-course/{uuid}` می‌دهد `{ completed: 3, total: 8, next_session_number: 4, next_params: { energy: 18 } }`. - ❌ خطا: `book-all` وقتی برای یکی از جلسات هیچ وقتی نیست → **هیچ‌کدام رزرو نمی‌شود**، `422` با شمارهٔ جلسهٔ مشکل‌دار. رزرو نیمه‌کاره ممنوع. - ❌ خطا: شروع دوره برای سرویسی که پروتکل ندارد → `422`. - ⚠️ مرزی: بیمار دورهٔ فعال دیگری برای همان سرویس دارد → `422` با لینک به دورهٔ موجود. - ⚠️ مرزی: لغو یک جلسهٔ وسط دوره → آن `CourseSession` به `planned` برمی‌گردد، بقیه دست‌نخورده؛ پیشنهاد بعدی مبنایش آخرین جلسهٔ **انجام‌شده** است. - ⚠️ مرزی: دورهٔ متصل به پکیج (تسک ۱۱) → هر جلسه یک واحد اعتبار مصرف می‌کند. - ⚠️ مرزی: تعداد جلسات پروتکل تغییر کرد → دوره‌های فعال دست‌نخورده (snapshot). - ⚠️ مرزی: `book-all` بیشتر از بازهٔ ۹۰ روزهٔ مجاز (۸ جلسه × ۲۸ روز = ۲۲۴ روز) → فقط جلساتی که در ۹۰ روز جا می‌شوند رزرو شوند، بقیه `planned` بمانند + پیام روشن. ## خروجی - `src/Course/` - `assets/admin/pages/CourseProtocolsPage.tsx` + `TreatmentCoursePage.tsx` - کارت «دوره‌های درمان» در `PatientDetailPage.tsx` - `docs/api/course.md`