- 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.
5.9 KiB
5.9 KiB
جریان کاربری — تسک ۰۵
الف) کلینیک الگوی بخشهای یک سرویس را تعریف میکند
پنل › خدمات › لیزر کندلا › تب «بخشهای نوبت»
│
├─ «افزودن بخش»
│ نام: مالیدن کرم بیحسی
│ نوع (کلید ادغام): آمادهسازی
│ مدت: ثابت — ۵ دقیقه
│ بیمار حاضر است: بله
│ با بخشهای همنوع ادغام شود: بله
│ └─ نیازمندیها:
│ [اتاق] × ۱ — انحصاری
│ [اپراتور] × ۱ — انحصاری — مهارت: لیزر آلکساندرایت — قید: همجنس با بیمار
│
├─ بخش ۲: انتظار اثر بیحسی — ثابت ۳۰ — ادغامپذیر
│ نیازمندی: فقط [اتاق] × ۱ انحصاری ← اپراتور اینجا آزاد است
│
├─ بخش ۳: خود لیزر — سهمی ۱۰۰٪
│ نیازمندی: [اتاق] × ۱ · [اپراتور] × ۱ · [دستگاه] × ۱ از استخر «لیزرهای آلکساندرایت»
│
└─ بخش ۴: مراقبت بعد — ثابت ۵
نیازمندی: [اتاق] × ۱ · [اپراتور] × ۱
│
▼
نوار پیشنمایش زمانی (زیر فرم، زنده):
┌─────┬───────────────────┬─────────────┬─────┐
│ ۵' │ ۳۰' │ ۲۰' │ ۵' │
│🏠👤 │ 🏠 │ 🏠 👤 🔧 │🏠👤 │
└─────┴───────────────────┴─────────────┴─────┘
کل: ۶۰ دقیقه · اپراتور واقعاً درگیر: ۳۰ دقیقه
│
▼
«ذخیره» → PUT /api/v1/service-item/{uuid}/segments
خط «اپراتور واقعاً درگیر: ۳۰ دقیقه» مهمترین بازخورد این صفحه است: کلینیک آنجا میفهمد چرا این کار ارزشش را دارد.
ب) بیمار سرویس و آیتم انتخاب میکند (سایت عمومی)
انتخاب پزشک/کلینیک
│
▼
GET /api/v1/appointment-booking-services/{doctorUuid}
→ booking_mode = "resource" ← حالت جدید
→ services[] با گروههای آیتم
│
▼
بیمار انتخاب میکند: ناحیه = صورت + بیکینی · سطح انرژی = ۱۶
│
▼
POST /api/v1/service-selection/validate (تسک ۰۴، debounce)
→ valid: true · total_duration_minutes: 23 · total_price_rials: …
│
│ اگر valid=false:
│ خطاها زیر همان گروه نمایش داده میشوند
│ «انتخاب حداقل یک مورد از نواحی الزامی است»
│ «صورت و فولبادی با هم قابل انتخاب نیستند»
│ و دکمهٔ «ادامه» غیرفعال میماند
▼
POST /api/v1/appointment-plan/preview
→ total_minutes: 68
segments: [آمادهسازی ۵ · انتظار ۳۰ · لیزر ۲۳ · مراقبت ۵ · تمیزکاری ۵]
│
│ اگر NoEligibleResourceException:
│ «هیچ اپراتور خانمی با مهارت لیزر آلکساندرایت در شعبهٔ مرکزی موجود نیست»
│ + پیشنهاد شعبهٔ دیگر (اگر داشته باشد)
▼
مرحلهٔ انتخاب زمان → تسک ۰۶
نکته UX: برنامهٔ نوبت به بیمار نمایش داده نمیشود. بیمار فقط «۶۸ دقیقه» و «توضیحات آمادهسازی» را میبیند. بخشها جزئیات عملیاتی کلینیکاند؛ نشان دادنشان به بیمار فقط سؤال میسازد.
استثنا: بخشهایی با patient_present = false نباید در مدت اعلامی به بیمار بیایند
(«تمیزکاری یونیت» ۵ دقیقهٔ بعد از رفتن بیمار است). پس دو عدد وجود دارد:
total_minutes= ۶۸ (اشغال کلینیک) — برای موتورpatient_facing_minutes= ۶۳ — برای نمایش
هر دو در پاسخ preview برگردند.
ج) منشی از پنل نوبت میسازد
همان جریان ب، با دو تفاوت:
forManagement = true— بازهٔ رزرو و خاموش بودن نوبتدهی آنلاین اعمال نمیشود (همان رفتاری کهSlotCalculatorService::isWithinBookingWindow()امروز دارد)- منشی میتواند منبع را دستی انتخاب کند: پاسخ
previewبرای هر نیازمندیcandidatesرا با نام برمیگرداند و پنل یکSearchableSelectاختیاری نشان میدهد. خالی گذاشتن یعنی «تو انتخاب کن» (استراتژی تسک ۰۶).
د) حالت خطا — هیچ منبعی موجود نیست
POST /appointment-plan/preview
▼
422 {
"success": false,
"errors": [{
"code": "ERR_NO_ELIGIBLE_RESOURCE",
"message": "هیچ اپراتور خانمی با مهارت لیزر آلکساندرایت در شعبهٔ مرکزی موجود نیست",
"meta": { "segment": "خود لیزر", "role": "اپراتور", "branch_uuid": "…" }
}]
}
meta اجباری است: پنل با آن میتواند مستقیم به صفحهٔ منابع همان شعبه لینک بدهد
(«افزودن اپراتور») و کلینیک در سه کلیک مشکل را حل کند، بهجای اینکه با یک پیام
بنبست بماند.