# چک‌لیست — تسک ۰۶ (موتور جستجوی وقت چندمنبعی) **وضعیت کلی:** ⏳ شروع نشده · **آخرین بازبینی:** — قواعد: [_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 .` | ⏳ | | | ۷.۱۲ | موارد به‌تعویق با دلیل و تسک مقصد | ⏳ | |