feat: implement cancellation policy, no-show tracking, and waitlist management

- Add implementation notes for cancellation and waitlist features.
- Create task documentation outlining goals, current status, and acceptance criteria for cancellation policy and resource utilization reporting.
- Establish architecture for domain events and outbox pattern to ensure reliable event publishing.
- Define database schema for domain events and necessary queries for resource utilization and plan accuracy reports.
- Implement detailed implementation notes covering edge cases, testing strategies, and documentation requirements.
This commit is contained in:
hamed
2026-07-30 11:43:58 +03:30
parent 1d338503c8
commit 021d0eb6b2
62 changed files with 8098 additions and 0 deletions
@@ -0,0 +1,134 @@
# جریان کاربری — تسک ۰۶
## الف) بیمار وقت انتخاب می‌کند (سایت عمومی)
```
[از تسک ۰۵] برنامهٔ نوبت ساخته شد: ۶۸ دقیقه، ۵ بخش
GET /api/v1/appointment-availability/month?…&month=1405-05
→ { "1405-05-03": true, "1405-05-04": false, … }
تقویم شمسی: روزهای بدون ظرفیت خاکستری
بیمار روز ۳ مرداد را می‌زند
POST /api/v1/appointment-availability
{
"doctor_uuid": "…", "branch_uuid": "…",
"service_item_uuid": "…", "option_uuids": ["…","…"],
"from": "1405-05-03", "to": "1405-05-03", "limit": 50
}
{
"data": {
"total_minutes": 68,
"patient_facing_minutes": 63,
"slots": [
{ "start": 1754…, "start_time": "09:00", "end_time": "10:08",
"assignment": { "room": "اتاق ۲", "operator": "مریم …", "device": "کندلا ۱" } },
{ "start": 1754…, "start_time": "10:15", … }
]
}
}
```
**بیمار `assignment` را نمی‌بیند.** فقط ساعت. تخصیص برای پنل و برای مرحلهٔ رزرو موقت است.
(استثنا: اگر کلینیک «انتخاب پزشک/اپراتور توسط بیمار» را فعال کرده باشد — خارج از دامنهٔ
این تسک.)
```
بیمار ۰۹:۰۰ را می‌زند → تسک ۰۷ (رزرو موقت)
```
---
## ب) هیچ وقتی نیست — سه پیام متفاوت
```
POST /appointment-availability → data.slots = []
data.reason = ?
```
| `reason` | پیام فارسی | دکمهٔ پیشنهادی |
|---|---|---|
| `no_resource` | «برای این خدمت، منبع لازم در این شعبه تعریف نشده است» | (پنل) «افزودن منبع» |
| `no_calendar` | «برای منابع این خدمت ساعت کاری تعریف نشده است» | (پنل) «تنظیم تقویم» |
| `fully_booked` | «در بازهٔ انتخابی وقت خالی نیست» | «جستجو در ۳۰ روز آینده» |
| `outside_window` | «رزرو آنلاین فقط تا ۳ ماه آینده ممکن است» | — |
پیام واحد «وقتی موجود نیست» بدترین حالت است: بیمار فکر می‌کند کلینیک پر است در حالی که
کلینیک اصلاً تقویم تعریف نکرده.
---
## ج) منشی از پنل — با انتخاب دستی منبع
```
پنل نوبت جدید
├─ بیمار (جستجو یا ثبت جدید)
├─ شعبه · سرویس · آیتم‌ها
│ └─ اعتبارسنجی زنده (تسک ۰۴)
POST /appointment-availability با forManagement=true
│ (بازهٔ رزرو آنلاین و خاموش‌بودن نوبت‌دهی اعمال نمی‌شود — رفتار امروزی)
جدول وقت‌ها با ستون «منابع پیشنهادی»
ساعت مدت اتاق اپراتور دستگاه
─────────────────────────────────────────────
۰۹:۰۰ ۶۸' اتاق ۲ ▾ مریم ▾ کندلا ۱ ▾
۱۰:۱۵ ۶۸' اتاق ۱ ▾ سارا ▾ کندلا ۲ ▾
هر ▾ یک SearchableSelect است با فقط منابع آزادِ همان بازه.
عوض کردن یکی → درخواست دوباره برای اعتبارسنجی همان زمان (نه کل لیست).
«ثبت نوبت» → تسک ۰۷
```
---
## د) کلینیک به حالت چندمنبعی ارتقا می‌دهد
```
پنل › تنظیمات نوبت‌دهی
وضعیت فعلی: «نوبت‌دهی سرویسی» (قفل‌شده)
├─ بنر: «ارتقا به نوبت‌دهی چندمنبعی»
│ ✓ ۵ منبع فعال دارید
│ ✓ ۳ سرویس با مدت معتبر
│ ✗ ۲ نوبت فعال در آینده دارید — ابتدا تعیین تکلیف کنید
│ [مشاهدهٔ نوبت‌ها]
▼ (بعد از رفع همهٔ شرط‌ها)
├─ ☑ می‌دانم این تغییر برگشت‌ناپذیر است
└─ [ارتقا]
POST /api/v1/appointment-settings/upgrade-booking-mode
حالا تنظیمات جدید فعال می‌شوند:
گام زمانی: ۱۵ دقیقه ▾
استراتژی انتخاب منبع: کمترین شکاف ▾
```
چک‌لیست پیش از ارتقا اجباری است. بدون آن، کلینیک ارتقا می‌دهد، نوبت‌های قدیمی‌اش
نمایش نادرست می‌گیرند و هیچ راه بازگشتی نیست.
---
## ه) چه چیزی در این جریان **تغییر نمی‌کند**
```
پزشک در حالت slot → GET /api/v1/appointment-slots بدون تغییر
پزشک در حالت service → GET /api/v1/appointment-service-slots بدون تغییر
تقویم ماهانهٔ قدیمی → GET /api/v1/appointment-settings/month-availability/{uuid} بدون تغییر
```
سایت عمومی و اپ دسکتاپ تا وقتی کلینیک ارتقا نداده، هیچ کد جدیدی لازم ندارند.
پس از ارتقا، `GET /appointment-booking-services` مقدار `booking_mode: "resource"` می‌دهد و
کلاینت باید مسیر جدید را صدا بزند — **این تنها نقطه‌ای است که کلاینت‌ها باید به‌روز شوند**
و باید در `docs/api/appointment.md` برجسته نوشته شود.