Files
clinicpro/docs/new_feture/taskes/task-05-appointment-plan/user_flow.md
T
hamed 021d0eb6b2 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.
2026-07-30 11:43:58 +03:30

124 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# جریان کاربری — تسک ۰۵
## الف) کلینیک الگوی بخش‌های یک سرویس را تعریف می‌کند
```
پنل › خدمات › لیزر کندلا › تب «بخش‌های نوبت»
├─ «افزودن بخش»
│ نام: مالیدن کرم بی‌حسی
│ نوع (کلید ادغام): آماده‌سازی
│ مدت: ثابت — ۵ دقیقه
│ بیمار حاضر است: بله
│ با بخش‌های هم‌نوع ادغام شود: بله
│ └─ نیازمندی‌ها:
│ [اتاق] × ۱ — انحصاری
│ [اپراتور] × ۱ — انحصاری — مهارت: لیزر آلکساندرایت — قید: هم‌جنس با بیمار
├─ بخش ۲: انتظار اثر بی‌حسی — ثابت ۳۰ — ادغام‌پذیر
│ نیازمندی: فقط [اتاق] × ۱ انحصاری ← اپراتور اینجا آزاد است
├─ بخش ۳: خود لیزر — سهمی ۱۰۰٪
│ نیازمندی: [اتاق] × ۱ · [اپراتور] × ۱ · [دستگاه] × ۱ از استخر «لیزرهای آلکساندرایت»
└─ بخش ۴: مراقبت بعد — ثابت ۵
نیازمندی: [اتاق] × ۱ · [اپراتور] × ۱
نوار پیش‌نمایش زمانی (زیر فرم، زنده):
┌─────┬───────────────────┬─────────────┬─────┐
۵' │ ۳۰' │ ۲۰' │ ۵' │
│🏠👤 │ 🏠 │ 🏠 👤 🔧 │🏠👤 │
└─────┴───────────────────┴─────────────┴─────┘
کل: ۶۰ دقیقه · اپراتور واقعاً درگیر: ۳۰ دقیقه
«ذخیره» → 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` برگردند.
---
## ج) منشی از پنل نوبت می‌سازد
همان جریان ب، با دو تفاوت:
1. `forManagement = true` — بازهٔ رزرو و خاموش بودن نوبت‌دهی آنلاین اعمال نمی‌شود
(همان رفتاری که `SlotCalculatorService::isWithinBookingWindow()` امروز دارد)
2. منشی می‌تواند **منبع را دستی انتخاب کند**: پاسخ `preview` برای هر نیازمندی
`candidates` را با نام برمی‌گرداند و پنل یک `SearchableSelect` اختیاری نشان می‌دهد.
خالی گذاشتن یعنی «تو انتخاب کن» (استراتژی تسک ۰۶).
---
## د) حالت خطا — هیچ منبعی موجود نیست
```
POST /appointment-plan/preview
422 {
"success": false,
"errors": [{
"code": "ERR_NO_ELIGIBLE_RESOURCE",
"message": "هیچ اپراتور خانمی با مهارت لیزر آلکساندرایت در شعبهٔ مرکزی موجود نیست",
"meta": { "segment": "خود لیزر", "role": "اپراتور", "branch_uuid": "…" }
}]
}
```
`meta` اجباری است: پنل با آن می‌تواند مستقیم به صفحهٔ منابع همان شعبه لینک بدهد
(«افزودن اپراتور») و کلینیک در سه کلیک مشکل را حل کند، به‌جای اینکه با یک پیام
بن‌بست بماند.