- Created checklist for task 11: Package and Credit Ledger - Created checklist for task 12: Treatment Course - Created checklist for task 13: Cancellation Policy, No-Show, and Waitlist - Created checklist for task 14: Domain Events and Utilization Reports
7.9 KiB
7.9 KiB
چکلیست — تسک ۰۷ (رزرو موقت و ثبت نهایی چندمنبعی)
وضعیت کلی: ⏳ شروع نشده · آخرین بازبینی: —
قواعد: _shared/definition-of-done.md · red-lines.md · ui-conventions.md
۰. خط سرخ
| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۰.۱ | --group=slot-mode-frozen سبز |
⏳ | |
| ۰.۲ | active_slot_key و refreshActiveSlotKey() دستنخورده و فعال |
⏳ | دو تور ایمنی موازی |
| ۰.۳ | slot_start/slot_end باقی ماندند |
⏳ | چهار مصرفکننده رویشان کوئری میزنند |
| ۰.۴ | is_reserve دستنخورده — رزرو هیچ ردیف اشغالی نمیسازد |
⏳ | |
| ۰.۵ | POST /api/v1/appointment قدیمی بیتبهبیت کار میکند |
⏳ | LegacyBookingUnchangedTest |
| ۰.۶ | PAYMENT_TTL و رفتار انقضای موجود حفظ شد |
⏳ |
۱. تضمین همزمانی — قلب تسک
| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۱.۱ | resource_occupancy_slot با UNIQUE(resource_id, bucket, unit_index) |
⏳ | ⭐ کل تضمین اینجاست |
| ۱.۲ | BUCKET_SECONDS = 300 ثابت + کامنت هشدار تغییرش |
⏳ | |
| ۱.۳ | سطلها با intdiv($end - 1, 300) — نه بدون -1 |
⏳ | ⭐ وگرنه نوبت مجاور رد میشود |
| ۱.۴ | unit_index با INSERT پشتسرهم، نه SELECT قبلش |
⏳ | ⭐ پنجرهٔ رقابت |
| ۱.۵ | ردیفها مرتب بر (resource_id, bucket, unit_index) درج میشوند |
⏳ | ⭐ جلوگیری از deadlock |
| ۱.۶ | SlotTakenException موجود بازاستفاده شد |
⏳ | |
| ۱.۷ | محدودیت گرانولاریتی ۵ دقیقه در مستندات صریح | ⏳ |
۲. بکاند
| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۲.۱ | ResourceOccupancy · AppointmentSegment |
⏳ | |
| ۲.۲ | OccupancyWriter — تنها نویسندهٔ resource_occupancy |
⏳ | |
| ۲.۳ | HoldService · BookingService · RescheduleService |
⏳ | |
| ۲.۴ | یک ردیف per (بخش × منبع) — نه per نوبت | ⏳ | ⭐ آزادسازی ظرفیت |
| ۲.۵ | برنامه در hold دوباره ساخته میشود؛ assignment کلاینت فقط اعتبارسنجی میشود |
⏳ | ⭐ سه نشتی ثبتشده از همین شکل بودند |
| ۲.۶ | منبع باید کاندید همان نیازمندی باشد، نه فقط هممحیط | ⏳ | |
| ۲.۷ | confirm هفت مرحله در یک تراکنش |
⏳ | |
| ۲.۸ | confirm idempotent — دوباره روی همان hold خطا نمیدهد |
⏳ | |
| ۲.۹ | رویداد بعد از commit (DispatchAfterCurrentBusStamp) با uuid در payload |
⏳ | ⭐ تسک ۱۲ رویش حساب میکند |
| ۲.۱۰ | reschedule: اول hold جدید، بعد آزادسازی قدیم |
⏳ | ⭐ ترتیب |
| ۲.۱۱ | لغو = status='released' + حذف فیزیکی ردیفهای سطل |
⏳ | |
| ۲.۱۲ | setup/cleanup در بازهٔ اشغال، نه در appointment_segments |
⏳ | |
| ۲.۱۳ | STATUS_RESCHEDULED + گذارهای مجاز |
⏳ | |
| ۲.۱۴ | ExpireAppointmentsHandler موجود توسعه یافت |
⏳ | آزادسازی + حذف سطل |
| ۲.۱۵ | قلابهای تسک ۰۸ و ۰۹ در confirm (مراحل ۳ و ۶) |
⏳ | |
| ۲.۱۶ | چهار endpoint | ⏳ | |
| ۲.۱۷ | دو کد خطا در ErrorCodes.php با پیام فارسی |
⏳ | ERR_SLOT_TAKEN · ERR_HOLD_EXPIRED |
۳. دیتابیس
| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۳.۱ | resource_occupancy (BIGINT id) با چهار ایندکس |
⏳ | |
| ۳.۲ | resource_occupancy_slot با UNIQUE |
⏳ | |
| ۳.۳ | appointment_segments با snapshot name/segment_type |
⏳ | قانون پنجم |
| ۳.۴ | سه ستون تهیپذیر روی appointments |
⏳ | branch_id · plan_total_minutes · patient_facing_minutes |
| ۳.۵ | ترتیب ستون ایندکسها دستی در migration | ⏳ | |
| ۳.۶ | app:occupancy:backfill --force — idempotent، نوبتهای بیمنبع را گزارش میکند |
⏳ | ⭐ بدون آن رزرو جدید روی نوبت قدیم مینشیند |
| ۳.۷ | app:occupancy:prune --older-than=90d |
⏳ | |
| ۳.۸ | resource_occupancy_slot در AGGREGATE_CHILDREN + هرگز کوئری مستقیم |
⏳ | |
| ۳.۹ | TenantSchemaCoverageTest سبز |
⏳ |
۴. UI
| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۴.۱ | تایمر شمارش معکوس hold در UI رزرو | ⏳ | |
| ۴.۲ | خطای 409 با پیام «این ساعت همین لحظه رزرو شد» + لیست جایگزین خودکار |
⏳ | ⭐ مستند بند ۱۷ |
| ۴.۳ | خطای reschedule شامل «نوبت فعلی تغییری نکرد» |
⏳ | ⭐ |
| ۴.۴ | مسدودسازی موردی منبع از صفحهٔ منابع | ⏳ | |
| ۴.۵ | تفکیک «مسدودسازی موردی» (occupancy) از «بلندمدت» (exception) در UI روشن است | ⏳ | دو راه یک کار گیجکننده است |
| ۴.۶ | هیچ رنگ/شعاع hard-code | ⏳ | |
| ۴.۷ | دارکمود و حالت فشرده | ⏳ | |
| ۴.۸ | RTL و موبایل | ⏳ | |
| ۴.۹ | همهٔ رشتهها فارسی | ⏳ | |
| ۴.۱۰ | AppointmentDetailPage بخش بخشهای نوبت (فقط حالت resource) |
⏳ |
۵. تست
| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۵.۱ | ConcurrentHoldTest — دو اتصال واقعی، دقیقاً یکی موفق |
⏳ | ⭐⭐ mock قبول نیست |
| ۵.۲ | OccupancyWriterTest — بازهٔ مماس، capacity، ترتیب INSERT |
⏳ | |
| ۵.۳ | HoldLifecycleTest — hold/انقضا/آزادسازی زودهنگام |
⏳ | |
| ۵.۴ | BookingConfirmTest — hold دیگری ۴۰۴، منقضی ۴۰۹، idempotent |
⏳ | |
| ۵.۵ | CapacityReleaseIntegrationTest |
⏳ | ⭐⭐ اپراتور در بازهٔ انتظار ردیف ندارد |
| ۵.۶ | RescheduleTest — شکست hold جدید → نوبت قدیم سالم |
⏳ | |
| ۵.۷ | OccupancyBackfillTest — idempotent |
⏳ | |
| ۵.۸ | LegacyBookingUnchangedTest |
⏳ | ⭐ |
| ۵.۹ | BookingTenantTest موجود سبز |
⏳ |
۶. مستندات
| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۶.۱ | docs/api/appointment-booking.md |
⏳ | |
| ۶.۲ | گرانولاریتی ۵ دقیقه و محدودیتش | ⏳ | |
| ۶.۳ | قرارداد hold_uuid و TTL |
⏳ | |
| ۶.۴ | تفکیک مسدودسازی موردی/بلندمدت | ⏳ | |
| ۶.۵ | docs/architecture/booking-concurrency.md — سطل زمانی + دلیل رد دو گزینهٔ دیگر |
⏳ | ⭐ شش ماه بعد زیر سؤال میرود |
۷. بازبینی پایانی
| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۷.۱ | هیچ 🔄 و ⏳ بیدلیل نمانده | ⏳ | |
| ۷.۲ | bin/phpunit کامل سبز |
⏳ | |
| ۷.۳ | --group=slot-mode-frozen سبز |
⏳ | |
| ۷.۴ | phpstan بدون خطای جدید |
⏳ | |
| ۷.۵ | npx tsc --noEmit و yarn test سبز |
⏳ | |
| ۷.۶ | تستهای tenant سبز | ⏳ | |
| ۷.۷ | docs/api/* بهروز |
⏳ | |
| ۷.۸ | چکلیست UI کامل | ⏳ | |
| ۷.۹ | دو کلاینت دیگر بررسی شدند | ⏳ | slot_start/slot_end سالم است؟ |
| ۷.۱۰ | commit، سپس graphify update . |
⏳ | |
| ۷.۱۱ | موارد بهتعویق با دلیل و تسک مقصد | ⏳ |