# چک‌لیست — تسک ۰۰ (تکمیل نوبت‌دهی سرویسی در clinicpro) **وضعیت کلی:** ⏳ شروع نشده **آخرین بازبینی:** — قواعد: [_shared/definition-of-done.md](../_shared/definition-of-done.md) · خط سرخ‌ها: [_shared/red-lines.md](../_shared/red-lines.md) · UI: [_shared/ui-conventions.md](../_shared/ui-conventions.md) --- ## ۰. خط سرخ — منطق اسلاتی | # | مورد | وضعیت | یادداشت | |---|---|---|---| | ۰.۱ | `SlotModeFrozenTest` + سه fixture ساخته شد **پیش از** هر تغییر کد | ⏳ | ترتیب مهم است | | ۰.۲ | fixture ها با تاریخ ثابت‌اند، نه `time()` | ⏳ | | | ۰.۳ | کامنت «read-only، هیچ تسکی به‌روزش نمی‌کند» بالای هر سه fixture | ⏳ | | | ۰.۴ | هیچ متد موجود `SlotCalculatorService` ویرایش نشد | ⏳ | فقط پارامتر اختیاری `excludeAppointmentId` روی `getServiceStartTimes` | | ۰.۵ | `GET /appointment-slots` بیت‌به‌بیت دست‌نخورده | ⏳ | | | ۰.۶ | `GET /month-availability/{doctorUuid}` دست‌نخورده | ⏳ | | | ۰.۷ | `active_slot_key` و `refreshActiveSlotKey()` دست‌نخورده | ⏳ | تنها استثنا: صدا زدنش در `setIsReserve` | | ۰.۸ | `isSlotTaken` امضا و معنا دست‌نخورده | ⏳ | | | ۰.۹ | `--group=slot-mode-frozen` در پایان سبز | ⏳ | | ## ۱. بک‌اند | # | مورد | وضعیت | یادداشت | |---|---|---|---| | ۱.۱ | `ServiceBookingCalculator` ساخته شد | ⏳ | | | ۱.۲ | `serviceSlots()` موجود از آن استفاده می‌کند، **خروجی‌اش عوض نشده** | ⏳ | | | ۱.۳ | جمع سادهٔ `+=` **حفظ شد** (اصلاحش تسک ۰۴ است) | ⏳ | | | ۱.۴ | `ServiceRescheduleService` + `POST /appointment/{uuid}/service-reschedule` | ⏳ | | | ۱.۵ | `PATCH /appointment/{uuid}` توسعه یافت — منطق جدید داخل `isServiceMode()` | ⏳ | | | ۱.۶ | `PATCH` مقدار `service_item_uuids[]` می‌پذیرد | ⏳ | | | ۱.۷ | `ReserveConversionService` + `POST /appointment/{uuid}/convert-reserve` | ⏳ | | | ۱.۸ | نوبت رزرو در حالت سرویسی سرویس‌ها را ذخیره می‌کند | ⏳ | | | ۱.۹ | `excludeAppointmentId` روی `getServiceStartTimes` و `findBusyIntervals` | ⏳ | همان الگوی `isSlotTaken` | | ۱.۱۰ | `Appointment::replaceServiceItems()` + `currentServiceUuids()` | ⏳ | | | ۱.۱۱ | `replaceServiceItems` مقدار `serviceItem` تکی را هم‌گام می‌کند | ⏳ | چهار مصرف‌کننده رویش خوانده‌اند | | ۱.۱۲ | `setIsReserve()` صدا زدن `refreshActiveSlotKey()` | ⏳ | | | ۱.۱۳ | اعتبارسنجی زمان با **عضویت در `getServiceStartTimes`**، نه فقط `isSlotTaken` | ⏳ | | | ۱.۱۴ | `TenantOwnershipChecker` روی همهٔ uuid های سرویس، **پیش از** هر بررسی دیگر | ⏳ | | | ۱.۱۵ | `allowInactive` فقط برای سرویس‌های موجود نوبت، نه uuid های تازه | ⏳ | | | ۱.۱۶ | کنترلر نازک ماند — منطق در سرویس | ⏳ | | ## ۲. دیتابیس و مهاجرت | # | مورد | وضعیت | یادداشت | |---|---|---|---| | ۲.۱ | `service_total_minutes` و `service_buffer_minutes` (تهی‌پذیر) | ⏳ | | | ۲.۲ | هیچ ستون موجودی حذف/تغییر نوع/تغییر معنا نداد | ⏳ | | | ۲.۳ | دو کد خطای جدید در `ErrorCodes.php` با پیام فارسی | ⏳ | شمارهٔ واقعی از خود فایل | | ۲.۴ | `app:appointment:backfill-service-duration` — dry-run پیش‌فرض، idempotent | ⏳ | | | ۲.۵ | backfill مقدار را از خود نوبت می‌گیرد، نه بازمحاسبه از سرویس‌ها | ⏳ | | | ۲.۶ | migration اجرا شد و `TenantSchemaCoverageTest` سبز | ⏳ | | ## ۳. UI — پنل ادمین | # | مورد | وضعیت | یادداشت | |---|---|---|---| | ۳.۱ | `AppointmentEditPage`: حالت سرویسی `ServiceSlotPicker` نشان می‌دهد | ⏳ | | | ۳.۲ | `AppointmentEditPage`: حالت اسلاتی **دقیقاً** رفتار امروز | ⏳ | سه فیلد ساعت | | ۳.۳ | ورودی دستی ساعت در حالت سرویسی **پنهان**، نه disabled | ⏳ | | | ۳.۴ | `ServiceSlotPicker` موجود بازاستفاده شد؛ نسخهٔ موازی ساخته نشد | ⏳ | فقط prop `excludeAppointmentUuid` | | ۳.۵ | `ReserveAppointmentsPage`: سرویس‌ها + دکمهٔ تبدیل | ⏳ | | | ۳.۶ | `ReserveAppointmentsPage` از جدول خام به `DataTable` مهاجرت کرد | ⏳ | `` حذف شد | | ۳.۷ | مدت و بافر فارسی با واحد: «۳۵ دقیقه (+۱۰ دقیقه فاصله)» | ⏳ | | | ۳.۸ | هیچ رنگ/شعاع/سایهٔ hard-code — همه از توکن‌های `styles.css` | ⏳ | | | ۳.۹ | دارک‌مود (`data-theme="dark"`) بررسی شد | ⏳ | | | ۳.۱۰ | حالت فشرده (`data-density="compact"`) بررسی شد | ⏳ | | | ۳.۱۱ | انتخاب چند سرویس با `SearchableSelect`؛ هیچ `