# تسک ۰۶ — موتور جستجوی وقت چندمنبعی **فاز:** ۱ (هسته) · **وابستگی:** ۰۳، ۰۵ · **زمان:** ۲۰-۲۴ ساعت --- ## هدف مستند بند ۱۰: برنامهٔ نوبت (تسک ۰۵) را روی تقویم منابع (تسک ۰۳) بلغزان و بگو چه ساعت‌هایی واقعاً ممکن‌اند — با پیشنهاد اینکه کدام منبع استفاده شود. **هدف کارایی: جستجوی یک ماهه زیر نیم ثانیه.** ## وضعیت فعلی ```php // SlotCalculatorService::getServiceStartTimes() — تک‌منبعی، یک بلوک پیوسته $busy = $this->appointmentRepo->findBusyIntervals($doctor, $dayStart, $dayStart + 86400); while ($t + $durSec <= $winEnd) { $conflict = $this->firstOverlap($t, $t + $needSec, $busy); … } ``` فقط تداخل **پزشک** بررسی می‌شود. اتاق، دستگاه و اپراتور اصلاً وجود ندارند. ## دامنه **هست:** - `AvailabilityEngine` — ورودی: برنامهٔ نوبت + بازهٔ تاریخ + شعبه؛ خروجی: وقت‌های معتبر همراه با تخصیص منبع پیشنهادی - تولید نقطه‌های شروع کاندید (پیش‌فرض هر ۱۵ دقیقه، قابل تنظیم per محیط) - هرس زودهنگام کاندیدهای قطعاً ناممکن - تخصیص منبع: تطبیق نیازمندی‌های هر بخش به منابع آزاد - استراتژی انتخاب منبع: `least_gap` (پیش‌فرض) · `balanced` · `preserve_specialists` · `same_as_previous` - کش روزانهٔ پنجرهٔ آزاد هر منبع - endpoint عمومی و پنلی - حالت `booking_mode = resource` روی `WeeklySchedule` و مسیر ارتقای داوطلبانه **نیست:** ثبت اشغال و رزرو موقت (تسک ۰۷)، قوانین فاصلهٔ زمانی (تسک ۰۹ — قلاب اینجا گذاشته می‌شود). ## Endpoint ها | متد | مسیر | توضیح | |---|---|---| | POST | `/api/v1/appointment-availability` | جستجوی وقت با برنامه (بدنه: سرویس، آیتم‌ها، شعبه، بازهٔ تاریخ) | | GET | `/api/v1/appointment-availability/month` | روزهای دارای ظرفیت در یک ماه (سبک — فقط بولین per روز) | ## معیار پذیرش - ✅ موفق: سناریوی مستند — سرویس لیزر با چهار بخش، شعبه با ۳ اتاق / ۲ اپراتور / ۳ دستگاه. جستجوی یک روز → لیست زمان‌های شروع، و برای هر زمان `assignment` شامل اتاق، اپراتور و دستگاه انتخابی. - ✅ موفق (**آزادسازی ظرفیت — قلب کل پروژه**): بیمار الف نوبت ۱۰:۰۰-۱۱:۰۰ دارد (اپراتور فقط ۱۰:۰۰-۱۰:۰۵ و ۱۰:۳۵-۱۱:۰۰ درگیر است). جستجو برای بیمار ب باید زمانی در بازهٔ ۱۰:۰۵-۱۰:۳۵ پیدا کند اگر اتاق دومی آزاد باشد. **تست بدون این سناریو، تسک را تأیید نمی‌کند.** - ✅ موفق: کارایی — جستجوی ۳۰ روزه با ۲۰ منبع و ۵۰۰ نوبت ثبت‌شده، **زیر ۵۰۰ms**. تست کارایی بخشی از تسک است، نه اختیاری. - ✅ موفق: پزشکی که در حالت `slot` یا `service` است → این endpoint `422` با `ERR_WRONG_BOOKING_MODE` می‌دهد و مسیر قدیمی دست‌نخورده کار می‌کند. - ❌ خطا: بازهٔ بزرگ‌تر از ۹۰ روز → `422`. - ❌ خطا: شعبهٔ محیط دیگر → `404`. - ❌ خطا: نیازمندی بدون منبع واجد شرایط → `422` با پیام انسانی (از تسک ۰۵). - ⚠️ مرزی: منبع با `capacity=3` و دو نوبت هم‌زمان → سومی هنوز جا دارد، چهارمی نه. - ⚠️ مرزی: `setup/cleanup` منبع → بازهٔ اشغال گسترده‌تر از بازهٔ بخش است و باید در بررسی تداخل لحاظ شود. - ⚠️ مرزی: بخش با `occupancy=passive` → منبع را می‌گیرد ولی در گزارش بهره‌وری «کار» نیست. - ⚠️ مرزی: نقطهٔ شروع در گذشته → حذف. - ⚠️ مرزی: هیچ روزی ظرفیت ندارد → آرایهٔ خالی + `reason` قابل فهم، نه ۴۰۴. - ⚠️ مرزی: منبع مشترک بین دو بخش غیرمجاور یک نوبت → **همان** منبع باید انتخاب شود (اپراتور بخش ۱ و بخش ۳ یکی است، نه دو نفر). ## خروجی - `src/Appointment/Availability/` - `docs/api/appointment-availability.md` - تست کارایی با داده مصنوعی: `tests/Appointment/AvailabilityPerformanceTest.php` - توسعهٔ `AppointmentSettingsPage.tsx` برای انتخاب حالت `resource` و استراتژی