Files
clinicpro/docs/new_feture/taskes/task-05-appointment-plan/task.md
T
hamed 021d0eb6b2 feat: implement cancellation policy, no-show tracking, and waitlist management
- Add implementation notes for cancellation and waitlist features.
- Create task documentation outlining goals, current status, and acceptance criteria for cancellation policy and resource utilization reporting.
- Establish architecture for domain events and outbox pattern to ensure reliable event publishing.
- Define database schema for domain events and necessary queries for resource utilization and plan accuracy reports.
- Implement detailed implementation notes covering edge cases, testing strategies, and documentation requirements.
2026-07-30 11:43:58 +03:30

103 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# تسک ۰۵ — بخش‌های نوبت و سازندهٔ برنامه
**فاز:** ۱ (هسته) · **وابستگی:** ۰۲، ۰۴ · **زمان:** ۱۶-۲۰ ساعت
---
## هدف
مهم‌ترین بخش مستند (بند ۷). یک نوبت یک تکه زمان پیوسته نیست:
| بخش | مدت | اتاق | اپراتور | دستگاه |
|---|---|---|---|---|
| مالیدن کرم بی‌حسی | ۵ | اشغال | اشغال | آزاد |
| انتظار اثر کرم | ۳۰ | اشغال | **آزاد** | آزاد |
| خود لیزر | ۲۰ | اشغال | اشغال | اشغال |
| مراقبت بعد | ۵ | اشغال | اشغال | آزاد |
با مدل امروز اپراتور ۶۰ دقیقه قفل می‌شود در حالی که ۳۰ دقیقه کار می‌کند. نصف ظرفیت
هدر می‌رود.
## وضعیت فعلی
```php
// src/Appointment/Entity/Appointment.php
private int $slotStart; // یک بازهٔ پیوسته
private int $slotEnd;
```
هیچ مفهومی از بخش، و هیچ نیازمندی منبعی وجود ندارد. تنها منبعی که تداخلش بررسی می‌شود
پزشک است (`AppointmentRepository::isSlotTaken`).
## دامنه
**هست:**
- `SegmentTemplate` — الگوی بخش‌های یک سرویس (و بخش‌های اضافهٔ هر `ServiceOption`)
- `SegmentRequirement` — نیازمندی منبع هر بخش: نقش، تعداد، شرط مهارت، قید، نوع اشغال
- `AppointmentPlanBuilder` — از (سرویس، آیتم‌ها، بیمار، شعبه) یک **برنامهٔ نوبت** می‌سازد
- ادغام بخش‌های هم‌نوع، محاسبهٔ مدت هر بخش، چیدمان ترتیبی
- `GET /api/v1/appointment-plan/preview` برای دیدن برنامه پیش از جستجوی وقت
**نیست:** پیدا کردن منابع آزاد و زمان (تسک ۰۶)، ثبت اشغال (تسک ۰۷)،
اعمال قوانین روی برنامه (تسک ۰۹ — نقطهٔ اتصالش اینجا آماده می‌شود).
## Endpoint ها
| متد | مسیر | توضیح |
|---|---|---|
| GET/PUT | `/api/v1/service-item/{uuid}/segments` | الگوی بخش‌های سرویس |
| PUT | `/api/v1/segment-template/{uuid}/requirements` | نیازمندی‌های منبع یک بخش |
| POST | `/api/v1/appointment-plan/preview` | ساخت و برگرداندن برنامهٔ نوبت (بدون ثبت) |
## خروجی `POST /appointment-plan/preview`
```json
{
"success": true,
"data": {
"total_minutes": 60,
"segments": [
{ "sequence": 1, "name": "بی‌حسی موضعی", "offset_minutes": 0, "duration_minutes": 5,
"patient_present": true,
"requirements": [
{ "role": "room", "count": 1, "occupancy": "exclusive", "candidates": 3 },
{ "role": "operator", "count": 1, "occupancy": "exclusive", "candidates": 2 }
] },
{ "sequence": 2, "name": "انتظار", "offset_minutes": 5, "duration_minutes": 30,
"patient_present": true, "mergeable": true,
"requirements": [ { "role": "room", "count": 1, "occupancy": "exclusive", "candidates": 3 } ] }
]
}
}
```
`candidates` تعداد منابع واجد شرایط است — اگر صفر باشد، برنامه ساخته نمی‌شود و خطای
انسانی برمی‌گردد: «هیچ اپراتور خانمی با مهارت لیزر در این شعبه نیست» (مستند بند ۱۰).
## معیار پذیرش
- ✅ موفق: سرویس «لیزر» با چهار بخش بالا تعریف می‌شود؛ `preview` برنامه‌ای با
`total_minutes = 60` و چهار بخش با `offset_minutes` صحیح (۰، ۵، ۳۵، ۵۵) برمی‌گرداند.
- ✅ موفق: انتخاب دو ناحیه (صورت + بیکینی) → بخش «آماده‌سازی» **یک بار** می‌آید
(`mergeable=true` هم‌نوع‌ها ادغام می‌شوند) ولی بخش «لیزر» مدتش با `DurationCalculator`
تسک ۰۴ محاسبه شده است.
- ✅ موفق: سرویسی که هیچ `SegmentTemplate` ندارد → برنامه‌ای با **یک بخش** برابر کل مدت
و نیازمندی پیش‌فرض (منبع `type=doctor`). این همان رفتار امروز است.
- ❌ خطا: نیازمندی با مهارتی که هیچ منبعی در آن شعبه ندارد →
`422` با `ERR_NO_ELIGIBLE_RESOURCE` و پیام فارسی شامل نقش و مهارت.
- ❌ خطا: بخش با `duration_minutes <= 0` و بدون منبع مدت پویا → `422`.
- ⚠️ مرزی: بخش با `requirements = []` (مثلاً «انتظار در خانه») → معتبر؛ زمان می‌گیرد،
هیچ منبعی نمی‌گیرد.
- ⚠️ مرزی: قید `same_gender_as_patient` وقتی جنسیت بیمار نامشخص است → نیازمندی نادیده
گرفته **نمی‌شود**؛ `422` با پیام «برای این سرویس ثبت جنسیت بیمار الزامی است».
- ⚠️ مرزی: `setup/cleanup` منبع در `preview` **نمایش داده نمی‌شود** ولی در
`occupancy_offset` هر نیازمندی می‌آید تا تسک ۰۶ همان را استفاده کند.
- ⚠️ مرزی: مجموع مدت بخش‌ها بیشتر از ۸ ساعت → `422` (حفاظت از جستجوی وقت).
## خروجی
- `src/Appointment/Plan/` — entity ها، `AppointmentPlanBuilder`، DTO ها
- `assets/admin/pages/ServiceSegmentsPage.tsx` + پیش‌نمایش برنامه
- `docs/api/appointment-plan.md`
- الگوهای آماده: `app:segment:seed-templates --preset=beauty|dental|physio` (مستند بند ۱۷)