# تسک ۱۳ — سیاست لغو، عدم حضور، لیست انتظار **فاز:** ۳ (کسب‌وکار) · **وابستگی:** ۰۷ · **زمان:** ۱۰-۱۲ ساعت --- ## هدف مستند بند ۱۱: «هر کلینیک تنظیم می‌کند: تا چند ساعت قبل لغو رایگان است، جریمه چقدر است، بیعانه برمی‌گردد یا نه، بعد از چند بار عدم حضور بیمار پرریسک علامت بخورد.» و بند ۱۷: «رقابت روی ساعت‌های پرتقاضا → پیشنهاد خودکار ساعت جایگزین» و بند ۱۸ فاز ۳: «لیست انتظار». ## وضعیت فعلی - لغو کار می‌کند (`cancelled_by_user` / `cancelled_by_doctor`) ولی **بدون سیاست**: هیچ جریمه‌ای، هیچ محدودیت زمانی، هیچ رفتاری با بیعانه - `no_show` وضعیت هست ولی هیچ اثری ندارد - `Appointment.is_reserve` وجود دارد: «نوبت رزرو» روزی (بدون ساعت) — یک لیست انتظار ابتدایی که `ReserveAppointmentsPage.tsx` نمایشش می‌دهد - بیعانه ثبت می‌شود (`deposit_required`, `deposit_amount_rials`) ولی بازگشتش دستی است ## دامنه **هست:** - `CancellationPolicy` per محیط/سرویس: پنجرهٔ لغو رایگان، درصد/مبلغ جریمه، رفتار بیعانه - `NoShowPolicy`: بعد از N بار، برچسب پرریسک روی بیمار (استفاده از `TenantTag` موجود) - محاسبهٔ جریمه در لحظهٔ لغو + ثبت در دفتر مالی موجود - `Waitlist` — لیست انتظار برای بازهٔ زمانی مشخص (توسعهٔ `is_reserve` موجود) - اطلاع‌رسانی خودکار به لیست انتظار وقتی ظرفیت آزاد می‌شود **نیست:** پیش‌بینی عدم حضور (فاز ۴ مستند — خارج از دامنه). ## Endpoint ها | متد | مسیر | توضیح | |---|---|---| | GET/PUT | `/api/v1/cancellation-policy` | سیاست محیط | | PUT | `/api/v1/service-item/{uuid}/cancellation-policy` | override سرویس | | GET | `/api/v1/appointment/{uuid}/cancellation-preview` | جریمه و بازگشت **پیش از** لغو | | POST | `/api/v1/appointment/{uuid}/cancel` | لغو با اعمال سیاست | | GET/POST | `/api/v1/waitlist` | ثبت در لیست انتظار | | DELETE | `/api/v1/waitlist/{uuid}` | | | GET | `/api/v1/waitlist/matches` | (پنل) درخواست‌های قابل تطبیق با ظرفیت آزاد | ## معیار پذیرش - ✅ موفق: سیاست «لغو رایگان تا ۲۴ ساعت قبل، پس از آن ۵۰٪ جریمه، بیعانه برنمی‌گردد» → `GET /cancellation-preview` برای نوبت ۴۸ ساعت بعد: `penalty_rials: 0, deposit_refundable: true`؛ برای نوبت ۶ ساعت بعد: `penalty_rials: <۵۰٪>, deposit_refundable: false`. - ✅ موفق: `POST /cancel` جریمه را در `wallet_transactions` (الگوی موجود) ثبت می‌کند و اشغال منابع را آزاد می‌کند. - ✅ موفق: سومین `no_show` بیمار → برچسب «پرریسک» (`TenantTag`) خودکار اضافه می‌شود و در `PatientDetailPage` دیده می‌شود. - ✅ موفق: بیمار در لیست انتظار برای «۵ مرداد، بعدازظهر» است؛ نوبتی در آن بازه لغو می‌شود → یک پیامک به او می‌رود و رکورد `notified_at` پر می‌شود. - ✅ موفق: لغو دورهٔ درمان (تسک ۱۲) → اعتبار پکیج **طبق سیاست** برمی‌گردد، نه همیشه. - ❌ خطا: `cancel` نوبتی که قبلاً لغو شده → `409` idempotent (همان وضعیت برگردد). - ❌ خطا: `cancel` نوبت گذشته → `422`؛ برای گذشته `no_show` یا `completed` معنی دارد. - ❌ خطا: ثبت در لیست انتظار برای بازهٔ گذشته → `422`. - ⚠️ مرزی: جریمه بیشتر از مبلغ پرداختی → سقف = مبلغ پرداختی. - ⚠️ مرزی: لغو توسط **کلینیک** (`cancelled_by_doctor`) → هرگز جریمه ندارد و بیعانه کامل برمی‌گردد. - ⚠️ مرزی: نوبت بدون پرداخت (نقدی سر جلسه) → جریمه ثبت می‌شود به‌عنوان بدهی، نه کسر. - ⚠️ مرزی: لیست انتظار با ده نفر برای یک بازه → **همه** مطلع می‌شوند (اولین رزروکننده می‌برد) — نه صف انحصاری. تصمیم و دلیلش در implementation_notes. - ⚠️ مرزی: بیمار پرریسک → **مسدود نمی‌شود**؛ فقط برچسب. مسدودسازی یک قانون `eligibility` (تسک ۰۹) روی همان برچسب است. ## خروجی - `src/Cancellation/` + `src/Waitlist/` - `assets/admin/pages/CancellationPolicyPage.tsx` + `WaitlistPage.tsx` - توسعهٔ `AppointmentDetailPage.tsx` با پیش‌نمایش لغو - `docs/api/cancellation.md` + `docs/api/waitlist.md`