# چک‌لیست — تسک ۰۶ (موتور جستجوی وقت چندمنبعی)

**وضعیت کلی:** ⏳ شروع نشده · **آخرین بازبینی:** —

قواعد: [_shared/definition-of-done.md](../_shared/definition-of-done.md) ·
[red-lines.md](../_shared/red-lines.md) · [ui-conventions.md](../_shared/ui-conventions.md)

---

## ۰. خط سرخ — حساس‌ترین تسک این فاز

| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۰.۱ | `--group=slot-mode-frozen` سبز | ⏳ | |
| ۰.۲ | `SlotCalculatorService` **هیچ** متدی عوض نشد | ⏳ | `AvailabilityEngine` کلاس موازی |
| ۰.۳ | `GET /appointment-slots` بیت‌به‌بیت دست‌نخورده | ⏳ | |
| ۰.۴ | `GET /appointment-service-slots` دست‌نخورده | ⏳ | حالت `service` موجود |
| ۰.۵ | `GET /month-availability/{doctorUuid}` دست‌نخورده | ⏳ | |
| ۰.۶ | `LegacyBookingUnchangedTest`: همهٔ تست‌های اسلاتی و سرویسی موجود سبز | ⏳ | ⭐ |
| ۰.۷ | انتخاب موتور فقط با `match($mode)` در کنترلر — **هیچ fallback خاموشی** | ⏳ | حالت اشتباه → `ERR_WRONG_BOOKING_MODE` |
| ۰.۸ | `DEFAULT_META['booking_mode']` همچنان `slot` | ⏳ | |

## ۱. بک‌اند

| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۱.۱ | `AvailabilityEngine` · `CandidateGenerator` · `ResourceAllocator` · `OccupancyIndex` | ⏳ | |
| ۱.۲ | چهار استراتژی + `ResourcePickerInterface` با tagged_iterator | ⏳ | OCP |
| ۱.۳ | `DailyWindowCache` — **فقط پنجرهٔ تقویمی**، هرگز اشغال | ⏳ | ⭐ |
| ۱.۴ | `MODE_RESOURCE` + `slot_granularity` + `picker_strategy` در `meta` | ⏳ | با اعتبارسنجی |
| ۱.۵ | `POST /appointment-settings/upgrade-booking-mode` — یک‌طرفه، با شرط | ⏳ | |
| ۱.۶ | دو endpoint جستجو | ⏳ | |
| ۱.۷ | `groupKey` = `(role, skills, constraints, indexInSegment)`؛ تطبیق بین‌بخشی روی سه جزء اول | ⏳ | ⭐ تلهٔ دو نیازمندی هم‌شکل در یک بخش |
| ۱.۸ | تخصیص حریصانه (بدون backtracking) + دلیل مکتوب | ⏳ | |
| ۱.۹ | دو گذر `setup/cleanup`: بیشینهٔ کاندیدها، بعد دقیق منبع انتخابی | ⏳ | |
| ۱.۱۰ | `hasRoom` شرط `expires_at > now` روی hold | ⏳ | |
| ۱.۱۱ | `reason` در پاسخ خالی: `no_resource`/`no_calendar`/`fully_booked`/`outside_window` | ⏳ | نه ۴۰۴، نه پیام واحد |
| ۱.۱۲ | قلاب `policies->filterSlots` از روز اول در امضا | ⏳ | تسک ۰۹ |
| ۱.۱۳ | سقف‌ها: بازه ۹۰ روز · `limit` ۲۰۰ · گام ≥۵ · کاندید ≤۵۰ per نیازمندی | ⏳ | |
| ۱.۱۴ | `TenantOwnershipChecker` روی هر uuid از request | ⏳ | |

## ۲. کارایی — بخشی از تسک، نه اختیاری

| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۲.۱ | **سه** کوئری برای کل بازه؛ هیچ I/O داخل حلقه | ⏳ | ⭐ |
| ۲.۲ | هرس با «تنگ‌ترین منبع» پیاده شد | ⏳ | ~۸۰٪ کاندیدها حذف |
| ۲.۳ | `busy` مرتب + جستجوی دودویی در `OccupancyIndex` | ⏳ | |
| ۲.۴ | `app:dev:seed-availability-benchmark` | ⏳ | ۳ اتاق، ۲ اپراتور، ۳ دستگاه، ۵۰۰ نوبت |
| ۲.۵ | `AvailabilityPerformanceTest`: **< ۵۰۰ms** | ⏳ | |
| ۲.۶ | `AvailabilityPerformanceTest`: **≤ ۵ کوئری** | ⏳ | مهم‌تر از زمان — ماشین‌مستقل |
| ۲.۷ | ابطال کش: تقویم/استثنا/ساعت شعبه/تعطیلی → `win`؛ ثبت نوبت → فقط `month` | ⏳ | |

## ۳. دیتابیس

| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۳.۱ | `resource_occupancy` **در این تسک** migrate شد (تعریف در تسک ۰۷) | ⏳ | وابستگی معکوس |
| ۳.۲ | `idx_occupancy_resource_range (resource_id, start_at, end_at, status)` | ⏳ | `resource_id` اول — نه tenant |
| ۳.۳ | ترتیب ستون‌های ایندکس در migration **دستی** نوشته شد | ⏳ | `diff` گاهی جابه‌جا می‌کند |
| ۳.۴ | `setMeta` کلیدهای جدید را با اعتبارسنجی می‌پذیرد | ⏳ | مقدار نامعتبر → مقدار فعلی |

## ۴. UI

| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۴.۱ | `AppointmentSettingsPage` انتخاب حالت `resource` + گام + استراتژی | ⏳ | |
| ۴.۲ | چک‌لیست پیش از ارتقا با علامت ✓/✗ هر شرط | ⏳ | ⭐ بدون آن ارتقای اشتباه |
| ۴.۳ | تیک «می‌دانم برگشت‌ناپذیر است» اجباری | ⏳ | |
| ۴.۴ | جدول وقت‌ها با ستون «منابع پیشنهادی» و `SearchableSelect` per منبع | ⏳ | پنل |
| ۴.۵ | عوض کردن یک منبع → اعتبارسنجی **همان زمان**، نه کل لیست | ⏳ | |
| ۴.۶ | `reason` خالی‌بودن با پیام فارسی + دکمهٔ پیشنهادی | ⏳ | چهار حالت |
| ۴.۷ | `assignment` به بیمار نمایش داده **نمی‌شود** | ⏳ | فقط پنل |
| ۴.۸ | هیچ رنگ/شعاع hard-code | ⏳ | |
| ۴.۹ | دارک‌مود و حالت فشرده | ⏳ | |
| ۴.۱۰ | RTL و موبایل | ⏳ | |
| ۴.۱۱ | همهٔ رشته‌ها فارسی | ⏳ | |
| ۴.۱۲ | `ScheduleSection.tsx` موجود توسعه یافت، کامپوننت موازی ساخته نشد | ⏳ | |

## ۵. تست

| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۵.۱ | `OccupancyIndexTest` — capacity، بازهٔ مماس، shared/exclusive | ⏳ | واحد |
| ۵.۲ | `CandidateGeneratorTest` — هرس، گذشته، برنامهٔ جا‌نشو | ⏳ | |
| ۵.۳ | `ResourceAllocatorTest` — منبع مشترک یکی؛ دو هم‌شکل در یک بخش دو منبع | ⏳ | |
| ۵.۴ | `CapacityReleaseTest` — **آزادسازی ظرفیت** | ⏳ | ⭐⭐ بدون این تسک تأیید نمی‌شود |
| ۵.۵ | `StrategyTest` — سه استراتژی | ⏳ | |
| ۵.۶ | `BookingModeGuardTest` — حالت اشتباه دو طرفه ۴۲۲ + ارتقا با نوبت فعال | ⏳ | |
| ۵.۷ | `AvailabilityPerformanceTest` | ⏳ | |
| ۵.۸ | `LegacyBookingUnchangedTest` | ⏳ | ⭐ |

## ۶. مستندات

| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۶.۱ | `docs/api/appointment-availability.md` | ⏳ | |
| ۶.۲ | جدول استراتژی‌ها | ⏳ | |
| ۶.۳ | محدودیت تخصیص حریصانه مکتوب | ⏳ | |
| ۶.۴ | ماتریس «کدام endpoint در کدام حالت» | ⏳ | |
| ۶.۵ | `docs/architecture/booking-modes.md` (تسک ۰۰) حالت سوم را گرفت | ⏳ | |
| ۶.۶ | در `docs/api/appointment.md` برجسته: کلاینت‌ها پس از ارتقا باید مسیر جدید بزنند | ⏳ | ⭐ |

## ۷. بازبینی پایانی

| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۷.۱ | هیچ 🔄 و ⏳ بی‌دلیل نمانده | ⏳ | |
| ۷.۲ | `bin/phpunit` کامل سبز | ⏳ | |
| ۷.۳ | `--group=slot-mode-frozen` سبز | ⏳ | |
| ۷.۴ | `phpstan` بدون خطای جدید | ⏳ | |
| ۷.۵ | `npx tsc --noEmit` و `yarn test` سبز | ⏳ | |
| ۷.۶ | تست‌های tenant سبز | ⏳ | |
| ۷.۷ | `docs/api/*` به‌روز | ⏳ | |
| ۷.۸ | چک‌لیست UI کامل | ⏳ | |
| ۷.۹ | ⚠️ `nobat724_front` و `clinic-pro-tauri`: تا کلینیک ارتقا نداده، تغییری لازم نیست — تأیید شد | ⏳ | ⭐ |
| ۷.۱۰ | تسک frontend حالت `resource` برای سایت ثبت شد (خارج از این فاز) | ⏳ | |
| ۷.۱۱ | commit، سپس `graphify update .` | ⏳ | |
| ۷.۱۲ | موارد به‌تعویق با دلیل و تسک مقصد | ⏳ | |
