Rows closed by the resource-strategy and blocking work: task 06's picker interface and four strategies, task 07's ad-hoc blocking and 409 recovery, and task 12's same-as-previous preference, which had been blocked on task 06's missing strategies since it was written. Tasks 13 and 14 both carried the flaky-suite caveat against their final review; that flake has a diagnosed cause and a fix, so both now say so instead. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
9.8 KiB
9.8 KiB
چکلیست — تسک ۰۶ (موتور جستجوی وقت چندمنبعی)
وضعیت کلی: ✅ تمامشده — موتور، کارایی، مستندات، انتخاب حالت و جریان رزرو · آخرین بازبینی: —
قواعد: _shared/definition-of-done.md · red-lines.md · 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 |
✅ | |
| ۱.۲ | چهار استراتژی + ResourcePicker با tagged_iterator |
✅ | ⭐ first_available · least_gap · least_loaded · same_as_previous؛ استراتژی مرتب میکند، انتخاب نمیکند |
| ۱.۳ | 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
| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۴.۱ | انتخاب حالت resource + گام + استراتژی |
✅ | هر سه در ScheduleSection؛ فهرست استراتژیها از GET /appointment-settings/resource-strategies میآید، نه از فهرستی که در فرانت تکرار شود |
| ۴.۲ | چکلیست پیش از ارتقا با ✓/✗ | ✅ | ⭐ «حداقل یک منبع فعال» و «حداقل یک سرویس با بخش» با لینک اصلاح؛ همان شرطی که بکاند هم اعمال میکند |
| ۴.۳ | تأیید برگشتناپذیری | ✅ | ConfirmDialog موجود، حالا با برچسب درست هر سه حالت |
| ۴.۴ | جدول وقتها با ستون «منابع پیشنهادی» | ✅ | ResourceBookingPage — تاریخ، ساعت، منابع، انتخاب |
| ۴.۵ | عوض کردن یک منبع → گزینههای همان زمان | ✅ | ⭐ فهرست هر نقش فقط منابعی است که موتور برای همان زمان داده؛ فهرست کامل شعبه یعنی انتخابی که ۴۰۹ میگیرد |
| ۴.۶ | reason خالیبودن با پیام فارسی |
✅ | REASON_LABELS — «بازه را بزرگتر کنید یا شعبهٔ دیگری را امتحان کنید» |
| ۴.۷ | assignment به بیمار نمایش داده نمیشود |
✅ | صفحه پنلمحور است و همانجا هم نوشته شده |
| ۴.۸ | هیچ رنگ/شعاع hard-code | ✅ | فقط var(--…) |
| ۴.۹ | دارکمود و حالت فشرده | ⚠️ | فقط توکنها؛ بازبینی چشمی انجام نشد |
| ۴.۱۰ | RTL و موبایل | ✅ | کارتهای حالت روی موبایل تکستونه میشوند |
| ۴.۱۱ | همهٔ رشتهها فارسی | ✅ | |
| ۴.۱۲ | ScheduleSection.tsx توسعه یافت، کامپوننت موازی نه |
✅ | ⭐ همان فایل، سه کارت بهجای دو |
| ۴.۱۳ | نگهبان بکاند برای آمادگی حالت | ✅ | ⭐ تازه اضافه شد: بدون منبع فعال، 422 — وگرنه انتخابِ برگشتناپذیر محیط را قفل میکرد |
| ۴.۱۴ | تست نگهبان | ✅ | ResourceModeReadinessTest — سه تست |
۵. تست
| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۵.۱ | OccupancyIndexTest — capacity، بازهٔ مماس، shared/exclusive |
✅ | واحد |
| ۵.۲ | CandidateGeneratorTest — هرس، گذشته، برنامهٔ جانشو |
✅ | |
| ۵.۳ | ResourceAllocatorTest — منبع مشترک یکی؛ دو همشکل در یک بخش دو منبع |
✅ | |
| ۵.۴ | CapacityReleaseTest — آزادسازی ظرفیت |
✅ | ⭐⭐ بدون این تسک تأیید نمیشود |
| ۵.۵ | تست استراتژیها | ✅ | ResourcePickerTest — ۹ تست: ترتیب هر چهار استراتژی، رجیستری، بازگشت به پیشفرض روی کلید ناشناخته، رد شدن هنگام ذخیره |
| ۵.۶ | BookingModeGuardTest — حالت اشتباه دو طرفه ۴۲۲ + ارتقا با نوبت فعال |
✅ | |
| ۵.۷ | AvailabilityPerformanceTest |
✅ | |
| ۵.۸ | LegacyBookingUnchangedTest |
✅ | ⭐ |
۶. مستندات
| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۶.۱ | docs/api/appointment-availability.md |
✅ | |
| ۶.۲ | جدول استراتژیها | ✅ | در 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 . |
✅ | |
| ۷.۱۲ | موارد بهتعویق با دلیل و تسک مقصد | ✅ |