# مستند طراحی موتور نوبت‌دهی Clinic Pro

**نسخه ۲ — نگارش ساده**

---

## این مستند برای چیست؟

می‌خواهیم یک سیستم نوبت‌دهی بسازیم که برای همه نوع کلینیک کار کند. کلینیک زیبایی، دندانپزشکی، فیزیوتراپی، مرکز تصویربرداری و هر مرکز خدماتی دیگر.

نکته اصلی این است: برای هر کلینیک جدید نباید کد جدید بنویسیم. باید بتوانیم فقط تنظیمات را عوض کنیم و همان سیستم کار کند.

این مستند می‌گوید این سیستم چطور باید ساخته شود.

---

## ۱. چه چیزهایی در این مستند هست و چه چیزهایی نیست

**هست:**
تعریف خدمات، محاسبه زمان هر نوبت، مدیریت منابع کلینیک، قوانین اختصاصی هر کلینیک، پیدا کردن وقت آزاد، ثبت نوبت، محاسبه قیمت، مدیریت دوره‌های درمان.

**نیست:**
پرونده پزشکی بیمار، حسابداری، انبار، پیامک تبلیغاتی، گزارش‌های مدیریتی.

این‌ها سیستم‌های جداگانه‌ای هستند. سیستم نوبت‌دهی فقط به آن‌ها خبر می‌دهد که چه اتفاقی افتاده و کاری به کارشان ندارد.

---

## ۲. پنج قانون طلایی

هر تصمیمی که در این مستند گرفته شده، از این پنج قانون می‌آید:

**یک) تقویم مال منبع است، نه مال پزشک.**
خیلی از سیستم‌ها فقط برای پزشک تقویم می‌سازند. این اشتباه است. دستگاه لیزر هم تقویم دارد. اتاق هم تقویم دارد. تخت هم. پزشک فقط یکی از این‌هاست.

**دو) یک نوبت، یک تکه زمان پیوسته نیست.**
یک نوبت لیزر از چند بخش تشکیل شده. در هر بخش، منابع متفاوتی درگیرند. این را مفصل توضیح می‌دهیم چون مهم‌ترین نکته این مستند است.

**سه) اطلاعات را با قانون قاطی نکنیم.**
«فلان اپراتور می‌تواند با فلان دستگاه کار کند» یک اطلاعات است. باید در جدول ذخیره شود.
«اگر بیمار VIP بود ده درصد تخفیف بده» یک قانون است.
اگر این دو را قاطی کنیم، سیستم پر از قانون‌های الکی می‌شود و کند می‌شود.

**چهار) قانون‌ها باید ساده و از قبل مشخص باشند.**
نباید اجازه بدهیم کاربر هر کد دلخواهی به عنوان قانون بنویسد. چرا؟ چون وقتی می‌خواهیم وقت‌های آزاد یک ماه آینده را نشان بدهیم، سیستم باید هزاران حالت را بررسی کند. اگر هر قانون یک برنامه دلخواه باشد، این کار چند ثانیه طول می‌کشد و کاربر منتظر می‌ماند.

**پنج) هر چیزی که ثبت شد، باید همان‌طور بماند.**
اگر فردا قیمت لیزر را عوض کردیم، نوبتی که دیروز ثبت شده نباید تغییر کند. اگر قانونی را عوض کردیم، نوبت‌های قبلی نباید خراب شوند.

---

## ۳. سیستم از چه لایه‌هایی تشکیل شده

سیستم مثل یک خط تولید کار می‌کند. هر لایه کار خودش را می‌کند و نتیجه را به لایه بعدی می‌دهد:

```
۱. کاتالوگ      →  چه خدماتی داریم؟
۲. انتخاب       →  بیمار چه چیزی خواسته؟
۳. برنامه‌ریزی   →  این کار چقدر طول می‌کشد و چه منابعی می‌خواهد؟
۴. قوانین       →  قوانین این کلینیک چه تغییری در برنامه می‌دهند؟
۵. زمان‌یابی     →  چه ساعت‌هایی آزاد است؟
۶. ثبت نوبت     →  رزرو کن و مطمئن شو کس دیگری همان وقت را نگرفته
۷. قیمت‌گذاری   →  چقدر باید پرداخت شود؟
```

---

## ۴. کلینیک، شعبه، اتاق

سیستم قرار است به شکل سرویس اشتراکی (SaaS) فروخته شود. یعنی چند کلینیک مختلف روی یک سیستم کار می‌کنند و هیچ‌کدام نباید اطلاعات دیگری را ببیند.

سه سطح داریم:

| سطح | یعنی چه |
|---|---|
| کلینیک (Tenant) | مشتری ما — کسی که اشتراک خریده |
| شعبه (Branch) | یک ساختمان واقعی با منابع و ساعت کاری خودش |
| اتاق (Room) | فضای داخل شعبه |

**نکته مهم:** شناسه کلینیک باید از همان روز اول در تمام جدول‌ها باشد. این چیزی نیست که بعداً اضافه شود. اگر اول سیستم را تک‌کلینیکی بسازیم، بعداً باید همه چیز را از نو بنویسیم.

خدمات و قیمت‌ها را می‌شود در سطح کلینیک تعریف کرد و در شعبه‌ها تغییر داد. مثلاً لیزر در شعبه مرکزی گران‌تر باشد.

منابع همیشه مال شعبه هستند، چون فیزیکی‌اند.

---

## ۵. تعریف خدمات

### دسته‌بندی

فقط برای مرتب کردن و نمایش است. مثلاً:

```
زیبایی
   لیزر
   تزریق
دندانپزشکی
   ترمیم
   جراحی
```

هیچ منطق نوبت‌دهی به دسته‌بندی وابسته نیست. فقط قوانین می‌توانند به آن اشاره کنند، مثلاً «همه خدمات دسته جراحی به جراح نیاز دارند».

### سرویس

هر چیزی که بیمار می‌تواند رزرو کند. مثلاً «لیزر کندلا» یا «ترمیم دندان».

هر سرویس این‌ها را دارد:

- عنوان و دسته‌بندی
- تک‌جلسه است یا دوره‌ای؟ (لیزر معمولاً هشت جلسه است)
- الگوی بخش‌های نوبت (بخش ۷ توضیح می‌دهد)
- قیمت پایه
- گروه‌های آیتم قابل انتخاب
- توضیحات آماده‌سازی بیمار
- فعال یا غیرفعال

### گروه آیتم

اینجا یک اشکال مهم در طراحی قبلی بود. قبلاً آیتم‌ها یک لیست ساده بودند. اما در واقعیت، انتخاب آیتم قانون دارد:

- «حتماً یک سطح انرژی انتخاب کن، فقط یکی»
- «بین یک تا هشت دندان انتخاب کن»
- «اگر بیکینی را انتخاب کردی، نمی‌توانی فول‌بادی را هم انتخاب کنی»

این‌ها را نباید به موتور قوانین سپرد. باید در خود تعریف آیتم باشند.

```
گروه: دندان‌های موردنظر
   حداقل انتخاب: ۱
   حداکثر انتخاب: ۸

گروه: سطح انرژی
   حداقل انتخاب: ۱
   حداکثر انتخاب: ۱
```

### آیتم

هر آیتم این‌ها را دارد:

| فیلد | یعنی چه |
|---|---|
| عنوان | مثلاً «صورت» یا «دندان شماره ۵» |
| زمان تنها | اگر تنها آیتم انتخابی باشد چقدر طول می‌کشد |
| زمان اضافه | اگر همراه آیتم‌های دیگر باشد چقدر به کل اضافه می‌کند |
| قیمت | |
| منابع اضافه | اگر منبع خاصی می‌خواهد |
| ناسازگار با | آیتم‌هایی که با آن جمع نمی‌شوند |
| پیش‌نیاز | آیتم‌هایی که باید قبلش انتخاب شوند |

**چرا دو تا فیلد زمان؟**

لیزر صورت به تنهایی پانزده دقیقه است. اما این پانزده دقیقه شامل آماده کردن بیمار، تنظیم دستگاه و توضیح دادن است.

حالا اگر بیمار صورت و بیکینی را با هم بخواهد، آماده‌سازی دو بار انجام نمی‌شود. بیکینی فقط هشت دقیقه به کل زمان اضافه می‌کند، نه پانزده دقیقه.

فرمول قدیمی که می‌گفت «زمان پایه + جمع زمان آیتم‌ها» همیشه زمان را بیشتر از واقعیت حساب می‌کند. یعنی ظرفیت کلینیک را الکی پر می‌کند و درآمد از دست می‌رود.

---

## ۶. منابع کلینیک

### منبع چیست

هر چیزی که برای انجام کار لازم است و ممکن است اشغال باشد: پزشک، اپراتور، دستیار، دستگاه، اتاق، تخت، یونیت دندانپزشکی.

نوع منابع را خود کلینیک تعریف می‌کند. ما در کد چیزی را ثابت نمی‌کنیم.

هر منبع این‌ها را دارد:

- متعلق به کدام شعبه
- چه نوعی است
- ظرفیت همزمان چقدر است
- چه مهارت‌هایی دارد
- ویژگی‌های آزاد: جنسیت، مدل دستگاه، طبقه
- تقویم کاری
- زمان آماده‌سازی و تمیزکاری بین دو بیمار

### ظرفیت همزمان

اتاق تزریق با سه تخت را چطور مدل کنیم؟

**غلط:** سه منبع جداگانه بسازیم.
**درست:** یک منبع با ظرفیت سه.

این کار مدل‌سازی را خیلی ساده‌تر می‌کند.

### زمان تمیزکاری

بین دو بیمار، یونیت دندانپزشکی ده دقیقه ضدعفونی می‌خواهد. این ده دقیقه جزو نوبت بیمار نیست، اما یونیت در این مدت اشغال است.

طراحی قبلی این را در نظر نگرفته بود.

### استخر منابع

کلینیک سه دستگاه لیزر مشابه دارد. وقتی بیمار نوبت می‌گیرد، فرقی نمی‌کند کدام دستگاه.

پس باید بتوانیم بگوییم «هر کدام از دستگاه‌های استخر لیزر آلکساندرایت». طراحی قبلی فقط می‌توانست به یک دستگاه مشخص اشاره کند که در عمل جواب نمی‌دهد.

### جدول مهارت‌ها

کدام اپراتور مجاز است با کدام دستگاه کار کند؟ این یک جدول ساده است.

طراحی قبلی این را به موتور قوانین سپرده بود. مشکل: اگر کلینیک پنجاه اپراتور و دویست سرویس داشته باشد، ده هزار قانون لازم می‌شود. غیرقابل مدیریت است.

### نیازمندی منبع

قلب انعطاف سیستم اینجاست. برای هر بخش از کار می‌گوییم چه منابعی لازم است:

```
نیاز اول:
   نقش: اپراتور
   تعداد: ۱
   شرط: باید مهارت لیزر آلکساندرایت داشته باشد
   قید: هم‌جنس با بیمار
   نوع اشغال: انحصاری

نیاز دوم:
   نقش: دستگاه
   تعداد: ۱
   شرط: هر عضو استخر لیزرهای آلکساندرایت
   نوع اشغال: انحصاری

نیاز سوم:
   نقش: اتاق
   تعداد: ۱
   شرط: اتاقی که نوعش لیزر باشد
   نوع اشغال: انحصاری
```

**قید جنسیت** در کلینیک‌های زیبایی ایران یک الزام جدی است، نه یک ترجیح. باید در هسته سیستم باشد.

**نوع اشغال** سه حالت دارد:
- انحصاری: منبع کامل اشغال است
- اشتراکی: یک واحد از ظرفیت منبع مصرف می‌شود
- منفعل: منبع رزرو است ولی کسی فعالانه کار نمی‌کند

---

## ۷. مهم‌ترین بخش: نوبت از چند تکه تشکیل شده

### مشکل چیست

طراحی قبلی فکر می‌کرد یک نوبت، یک بازه زمانی است که همه منابعش را در کل آن بازه اشغال می‌کند.

بیایید یک نوبت لیزر واقعی را نگاه کنیم:

| بخش | مدت | اتاق | اپراتور | دستگاه |
|---|---|---|---|---|
| مالیدن کرم بی‌حسی | ۵ دقیقه | اشغال | اشغال | آزاد |
| منتظر ماندن تا کرم اثر کند | ۳۰ دقیقه | اشغال | **آزاد** | آزاد |
| خود لیزر | ۲۰ دقیقه | اشغال | اشغال | اشغال |
| مراقبت بعد از لیزر | ۵ دقیقه | اشغال | اشغال | آزاد |

با طراحی قبلی، اپراتور شصت دقیقه قفل می‌شود. در حالی که واقعاً فقط سی دقیقه کار می‌کند.

یعنی نصف ظرفیت اپراتور الکی هدر می‌رود. برای یک کلینیک زیبایی، این تفاوت بین سود و ضرر است.

### راه‌حل

هر نوبت را به چند بخش تقسیم می‌کنیم. هر بخش مدت خودش، منابع خودش و ترتیب خودش را دارد:

```
بخش: انتظار اثر بی‌حسی
   مدت: ۳۰ دقیقه
   ترتیب: بعد از بخش قبلی
   منابع: فقط اتاق
   بیمار حاضر است: بله
   قابل ادغام با: بخش‌های انتظار دیگر
```

### چطور برنامه نوبت ساخته می‌شود

```
ورودی: سرویس، آیتم‌های انتخابی، بیمار، شعبه

۱. بخش‌های پایه سرویس را بردار
۲. بخش‌های اضافه هر آیتم انتخابی را اضافه کن
۳. بخش‌های هم‌نوع را ادغام کن
   (آماده‌سازی یک بار انجام می‌شود، نه به تعداد آیتم‌ها)
۴. مدت هر بخش را حساب کن
   - اولین آیتم هر گروه: زمان تنها
   - بقیه: زمان اضافه
۵. بخش‌ها را به ترتیب درست بچین
۶. قوانین مربوط به زمان را اعمال کن
۷. زمان آماده‌سازی و تمیزکاری هر منبع را اضافه کن

خروجی: برنامه نوبت
```

نتیجه چیزی شبیه این می‌شود:

```
کل مدت: ۶۰ دقیقه

بخش ۱ — دقیقه ۰ تا ۵    — اتاق، اپراتور
بخش ۲ — دقیقه ۵ تا ۳۵   — فقط اتاق
بخش ۳ — دقیقه ۳۵ تا ۵۵  — اتاق، اپراتور، دستگاه
بخش ۴ — دقیقه ۵۵ تا ۶۰  — اتاق، اپراتور
```

حالا اپراتور در آن سی دقیقه انتظار، آزاد است و می‌تواند بیمار دیگری را ببیند.

---

## ۸. قوانین اختصاصی

### چرا طراحی قبلی جواب نمی‌داد

طراحی قبلی همه قوانین را در یک کیسه ریخته بود. سه اشکال داشت:

**اول:** قانون‌ها جنس‌های کاملاً متفاوتی دارند و در زمان‌های مختلفی باید اجرا شوند.

**دوم:** معلوم نبود اگر دو قانون با هم تناقض داشتند، کدام برنده است. مثلاً اگر دو تخفیف همزمان اعمال شوند، جمع می‌شوند یا ضرب؟ نتیجه غیرقابل پیش‌بینی می‌شد.

**سوم:** اگر قانون بتواند هر کاری بکند، پیدا کردن وقت آزاد کند می‌شود.

### شش دسته قانون

| دسته | کی اجرا می‌شود | نمونه |
|---|---|---|
| انتخاب | موقع انتخاب آیتم | «اگر سرویس الف را انتخاب کردی، ب هم لازم است» |
| صلاحیت بیمار | قبل از جستجوی وقت | «بیمار زیر ۱۸ سال بدون رضایت والدین نمی‌شود» |
| منبع | موقع ساخت برنامه | «خدمات جراحی به جراح نیاز دارند» |
| زمان | موقع ساخت برنامه | «حداقل مدت درمان پیچیده یک ساعت است» |
| فاصله زمانی | موقع جستجوی وقت | «حداقل هفت روز از جلسه قبلی فاصله باشد» |
| قیمت | بعد از نهایی شدن برنامه | «بیمار VIP ده درصد تخفیف» |

هر دسته موتور خودش را دارد و در نقطه مشخصی اجرا می‌شود.

### شکل یک قانون

```
شناسه: جراحی نیاز به جراح دارد
کلینیک: ۰۰۱
شعبه: همه شعب
دسته: منبع
اولویت: ۱۰۰
از تاریخ: ۱۴۰۵/۰۱/۰۱
نسخه: ۳

شرط:
   دسته‌بندی سرویس شامل «جراحی» باشد

نتیجه:
   یک منبع با نقش جراح و مهارت جراحی عمومی اضافه کن
```

### قانون‌ها به چه چیزهایی دسترسی دارند

فقط به این فهرست مشخص. هر چیز جدیدی باید صریحاً اضافه شود:

```
سرویس: شناسه، دسته‌بندی، برچسب‌ها
آیتم‌ها: شناسه، گروه، تعداد
بیمار: سن، جنسیت، برچسب‌ها، تاریخ آخرین جلسه، تعداد جلسات انجام‌شده
رزرو: تاریخ و ساعت، روز هفته، شعبه، کانال رزرو
برنامه: کل مدت، کل قیمت
```

عملگرها هم مشخص است: مساوی، نامساوی، بزرگ‌تر، کوچک‌تر، عضو مجموعه، بین دو مقدار، تعداد روز گذشته.

**نوشتن کد دلخواه ممنوع است.** این محدودیت عمدی است. قوانین مربوط به فاصله زمانی باید قابل تبدیل به کوئری دیتابیس باشند، وگرنه جستجوی وقت آزاد کند می‌شود.

### وقتی چند قانون با هم تناقض دارند

ترتیب انتخاب:

۱. قانون با اولویت بالاتر برنده است
۲. اگر اولویت مساوی بود، قانون اختصاصی‌تر برنده است (شعبه بر کلینیک، سرویس بر دسته‌بندی)
۳. اگر باز هم مساوی بود، قانون قدیمی‌تر برنده است

و وقتی چند قانون هم‌نوع همزمان اعمال می‌شوند:

| نوع اثر | قاعده |
|---|---|
| حداقل مدت | بیشترین مقدار برنده است |
| اضافه کردن زمان | همه با هم جمع می‌شوند |
| اضافه کردن منبع | همه اضافه می‌شوند، تکراری‌ها حذف |
| محدود کردن منبع | اشتراک محدودیت‌ها |
| تخفیف درصدی | به ترتیب اولویت پشت سر هم، با یک سقف قابل تنظیم |
| ممنوعیت | یکی کافی است — کل عملیات رد می‌شود |

### نسخه‌بندی

قانون‌ها ویرایش نمی‌شوند. هر تغییر، یک نسخه جدید با تاریخ شروع می‌سازد.

هر نوبت، فهرست قانون‌هایی که رویش اعمال شده را ذخیره می‌کند. پس اگر فردا قانون عوض شد، نوبت دیروز دست نخورده می‌ماند.

### محیط آزمایش

قبل از اینکه یک قانون واقعاً فعال شود، باید بشود آن را روی داده واقعی اجرا کرد و نتیجه را دید، بدون اینکه چیزی ثبت شود.

---

## ۹. تقویم و ساعت‌های آزاد

### چطور حساب می‌شود

ساعت‌های آزاد یک منبع، از کم کردن لایه‌ها به دست می‌آید:

```
ساعت کاری شعبه
  منهای ساعت‌های خارج از شیفت منبع
  منهای تعطیلات رسمی
  منهای مرخصی و غیبت
  منهای زمان سرویس دوره‌ای دستگاه
  منهای نوبت‌های ثبت‌شده
  منهای رزروهای موقت
  منهای زمان آماده‌سازی و تمیزکاری
────────────────────────────────
  = ساعت‌های واقعاً آزاد
```

### تقویم شمسی

- ذخیره‌سازی همیشه میلادی و به وقت جهانی است
- تبدیل به شمسی فقط در لحظه نمایش انجام می‌شود
- جدول تعطیلات رسمی کشور داریم، ولی هر کلینیک می‌تواند تغییرش بدهد (بعضی کلینیک‌ها پنجشنبه‌ها کار می‌کنند)
- شیفت‌های تکرارشونده با الگوی استاندارد تعریف می‌شوند

---

## ۱۰. پیدا کردن وقت آزاد

### مراحل

```
ورودی: برنامه نوبت، بازه تاریخ، شعبه

۱. برای هر نیازمندی، منابع مناسب را پیدا کن
   منابعی که شرط را دارند، قوانین اجازه می‌دهند و قیدها را دارند
   اگر برای یک نیازمندی هیچ منبعی پیدا نشد،
   خطای واضح بده: «هیچ اپراتور خانمی با مهارت لیزر در این شعبه نیست»

۲. ساعت‌های آزاد هر منبع را در بازه تاریخ حساب کن

۳. نقطه‌های شروع ممکن را بساز (پیش‌فرض: هر ۱۵ دقیقه)
   نقطه‌هایی که از همان اول قطعاً جواب نمی‌دهند را حذف کن

۴. برای هر نقطه شروع:
     برای هر بخش از برنامه:
       ببین در آن بازه، منابع لازم آزاد هستند یا نه
     قوانین فاصله زمانی را چک کن
     اگر همه چیز درست بود، این یک وقت معتبر است

۵. وقت‌های پیدا شده را مرتب کن

خروجی: لیست وقت‌های آزاد به همراه پیشنهاد اینکه کدام منبع استفاده شود
```

### کدام منبع را انتخاب کنیم

وقتی چند منبع آزاد است، انتخاب مهم است. کلینیک می‌تواند یکی از این‌ها را تنظیم کند:

- **کمترین شکاف:** منبعی که کمترین وقت خالی بلااستفاده ایجاد کند (پیش‌فرض)
- **توزیع متعادل:** کار بین منابع پخش شود
- **حفظ متخصص‌ها:** اپراتور ماهر برای کارهای ساده مصرف نشود
- **همان منبع قبلی:** در دوره‌های درمان، همان اپراتور جلسات قبل

### سرعت

- ایندکس مخصوص بازه زمانی روی جدول رزروها
- ذخیره موقت ساعت‌های آزاد هر روز و هر منبع
- محدود کردن جستجو به نود روز آینده
- **هدف: جستجوی یک ماهه زیر نیم ثانیه پاسخ بدهد**

---

## ۱۱. ثبت نوبت

### سه مرحله

```
جستجو  ←  رزرو موقت  ←  ثبت نهایی
```

طراحی قبلی فقط «ثبت نوبت» داشت. مشکل: دو نفر همزمان یک ساعت را انتخاب می‌کنند، هر دو می‌روند پرداخت کنند، و نفر دوم موقع پرداخت با خطا مواجه می‌شود.

### رزرو موقت

- به محض اینکه بیمار ساعتی را انتخاب کرد، آن ساعت برای همه منابعش قفل می‌شود
- قفل ده دقیقه اعتبار دارد (برای پرداخت آنلاین بیشتر)
- تضمین این کار در سطح دیتابیس انجام می‌شود، نه در کد برنامه

این نکته فنی مهم است: اگر جلوگیری از رزرو تکراری را در کد برنامه بگذاریم، همیشه یک شکاف زمانی می‌ماند که دو درخواست همزمان از آن رد می‌شوند. دیتابیس باید این را تضمین کند.

### ثبت نهایی

همه این کارها با هم و یکجا انجام می‌شوند. اگر یکی شکست بخورد، همه لغو می‌شوند:

۱. چک کن رزرو موقت هنوز معتبر است
۲. قوانین صلاحیت و فاصله زمانی را دوباره چک کن
۳. نوبت و بخش‌هایش را ثبت کن
۴. قفل موقت را به رزرو دائمی تبدیل کن
۵. قیمت و قوانین اعمال‌شده را ذخیره کن
۶. به بقیه سیستم خبر بده

### وضعیت‌های یک نوبت

```
پیش‌نویس → رزرو موقت → ثبت‌شده → پذیرش → در حال انجام → تمام‌شده
                            ↓          ↓
                          لغو      عدم حضور
                            ↓
                      جابجا شده
```

هر تغییر وضعیت ثبت می‌شود تا بعداً بشود فهمید چه اتفاقی افتاده.

### لغو و عدم حضور

هر کلینیک تنظیم می‌کند: تا چند ساعت قبل لغو رایگان است، جریمه چقدر است، بیعانه برمی‌گردد یا نه، بعد از چند بار عدم حضور بیمار پرریسک علامت بخورد.

---

## ۱۲. قیمت‌گذاری

### چرا لایه جداست

قیمت زندگی خودش را دارد: تاریخ اعتبار، مالیات، بیمه، پکیج، بیعانه. طراحی قبلی قیمت را داخل موتور قوانین گذاشته بود که هر دو را خراب می‌کند.

### مراحل محاسبه

```
۱. قیمت پایه سرویس (از لیست قیمت معتبر در تاریخ رزرو)
۲. جمع قیمت آیتم‌های انتخابی
۳. اعمال قوانین قیمت به ترتیب اولویت
۴. کسر از اعتبار پکیج (اگر بیمار پکیج دارد)
۵. محاسبه مالیات و سهم بیمه
۶. تعیین مبلغ بیعانه
۷. ذخیره فاکتور تفکیک‌شده
```

### لیست قیمت

- هر لیست قیمت تاریخ شروع و پایان دارد
- هر شعبه می‌تواند قیمت خودش را داشته باشد
- **تغییر قیمت هرگز نوبت‌های ثبت‌شده را عوض نمی‌کند**

### پکیج

خیلی رایج در کلینیک زیبایی: «پکیج شش جلسه لیزر». بیمار یکجا پول می‌دهد و بعداً جلساتش را رزرو می‌کند.

```
خرید پکیج  →  اعتبار جلسه ثبت می‌شود
ثبت نوبت   →  یک واحد اعتبار مصرف می‌شود
لغو نوبت   →  اعتبار برمی‌گردد (طبق سیاست لغو)
```

**نکته فنی:** اعتبار را به صورت دفتر حساب نگه می‌داریم، نه یک عدد شمارنده. یعنی هر تراکنش ثبت می‌شود و مانده از جمع آن‌ها حساب می‌شود. اگر فقط یک عدد نگه داریم، اولین اشتباه هرگز قابل ردیابی نیست.

---

## ۱۳. دوره درمان

لیزر معمولاً شش تا هشت جلسه است. طراحی قبلی فقط نوبت تکی می‌شناخت، در حالی که این حالت اصلی کسب‌وکار است.

### پروتکل دوره

```
سرویس: لیزر فول‌بادی
تعداد جلسات: ۸
فاصله بین جلسات:
   حداقل: ۲۱ روز
   ایده‌آل: ۲۸ روز
   حداکثر: ۴۵ روز
سطح انرژی هر جلسه: ۱۲، ۱۴، ۱۶، ۱۸، ۲۰، ۲۰، ۲۲، ۲۲
```

### رفتار سیستم

- بیمار می‌تواند کل دوره را یکجا رزرو کند، یا جلسه به جلسه پیش برود
- بعد از هر جلسه، تاریخ جلسه بعدی پیشنهاد داده می‌شود
- اگر بیمار از حداکثر فاصله عبور کرد، هشدار داده می‌شود
- پیشرفت دوره ردیابی می‌شود: جلسه چندم از چند، پارامترهای هر جلسه
- به صورت پیش‌فرض سعی می‌شود همان اپراتور قبلی انتخاب شود

---

## ۱۴. جدول‌های دیتابیس

فرض: PostgreSQL

```
کلینیک و شعبه
   tenant, branch, room

خدمات
   service_category          دسته‌بندی درختی
   service                   سرویس
   service_branch_override   قیمت و مدت اختصاصی شعبه
   item_group                گروه آیتم با حداقل و حداکثر انتخاب
   service_item              آیتم با دو نوع زمان
   service_item_relation     ناسازگاری و پیش‌نیاز
   segment_template          الگوی بخش‌های نوبت
   segment_requirement       نیازمندی منبع هر بخش

منابع
   resource_type             نوع منبع
   resource                  منبع با ظرفیت و ویژگی‌ها
   resource_pool             استخر منابع قابل جایگزینی
   skill / resource_skill    جدول مهارت‌ها
   work_calendar             تقویم کاری با الگوی تکرار
   resource_exception        مرخصی و سرویس دوره‌ای
   holiday                   تعطیلات

قوانین
   policy                    قانون با شرط و نتیجه
   policy_version_log        تاریخچه نسخه‌ها

نوبت‌ها
   appointment               نوبت اصلی
   appointment_item          آیتم‌های انتخابی
   appointment_segment       بخش‌های نوبت
   resource_occupancy        اشغال منابع ← مهم‌ترین جدول
   appointment_audit         تاریخچه تغییرات

قیمت
   price_list                لیست قیمت تاریخ‌دار
   price_snapshot            فاکتور ثبت‌شده
   package                   پکیج
   session_credit_ledger     دفتر اعتبار جلسات
   payment / deposit         پرداخت و بیعانه

دوره درمان
   course_protocol           پروتکل دوره
   treatment_course          دوره بیمار
   course_session            جلسات دوره
```

**نکته کلیدی:** جدول `resource_occupancy` تنها مرجع حقیقت برای اشغال منابع است. هم رزرو موقت و هم نوبت نهایی در همین جدول ثبت می‌شوند و فقط وضعیت‌شان فرق می‌کند.

با این طراحی، جلوگیری از رزرو تکراری به یک محدودیت ساده دیتابیسی تبدیل می‌شود و دیگر لازم نیست در کد نگرانش باشیم.

---

## ۱۵. مسیر کامل یک رزرو

```
 ۱. بیمار شعبه را انتخاب می‌کند
 ۲. دسته‌بندی و سرویس را انتخاب می‌کند
 ۳. آیتم‌ها را انتخاب می‌کند
       سیستم قیدهای گروه را چک می‌کند
       قوانین انتخاب اجرا می‌شوند
 ۴. برنامه نوبت ساخته می‌شود
       تقسیم به بخش‌ها، ادغام، محاسبه مدت
       قوانین منبع و زمان اعمال می‌شوند
 ۵. صلاحیت بیمار بررسی می‌شود
       اگر رد شد، دلیل قابل فهم نشان داده می‌شود
 ۶. قیمت اولیه محاسبه می‌شود
 ۷. وقت‌های آزاد پیدا می‌شوند
 ۸. وقت‌ها به بیمار نشان داده می‌شوند
 ۹. بیمار وقت را انتخاب می‌کند و رزرو موقت ایجاد می‌شود
۱۰. پرداخت یا بیعانه (اگر لازم باشد)
۱۱. ثبت نهایی همراه با ذخیره قیمت و قوانین
۱۲. اطلاع‌رسانی به بیمار و بقیه سیستم
```

---

## ۱۶. خبرهایی که سیستم منتشر می‌کند

سیستم‌های دیگر (پیامک، حسابداری، گزارش) به این خبرها گوش می‌دهند:

```
رزرو موقت ایجاد شد        نوبت ثبت شد
نوبت لغو شد               نوبت جابجا شد
بیمار نیامد               نوبت تمام شد
منبع مسدود شد             منبع آزاد شد
دوره درمان شروع شد        یک جلسه دوره تمام شد
```

---

## ۱۷. ریسک‌ها

| ریسک | چه اتفاقی می‌افتد | چه کنیم |
|---|---|---|
| کند شدن جستجوی وقت با زیاد شدن منابع | کاربر منتظر می‌ماند و می‌رود | ساده نگه داشتن قوانین، ذخیره موقت، محدود کردن بازه جستجو، اندازه‌گیری سرعت از فاز اول |
| کاربر غیرفنی نمی‌تواند قانون درست تعریف کند | قانون‌های اشتباه، رفتار عجیب | ساخت قانون با فرم آماده، الگوهای از پیش تعریف‌شده، آزمایش اجباری قبل از فعال شدن |
| کلینیک بخش‌های نوبت را اشتباه تعریف کند | ظرفیت غلط حساب می‌شود | الگوی آماده برای هر نوع کلینیک، گزارش بهره‌وری منابع برای پیدا کردن اشکال |
| رقابت روی ساعت‌های پرتقاضا | رزرو شکست می‌خورد | رزرو موقت کوتاه، پیشنهاد خودکار ساعت جایگزین |
| اضافه کردن چندکلینیکی بعد از راه‌اندازی | بازنویسی کامل دیتابیس | از همان روز اول در تمام جدول‌ها |

---

## ۱۸. ترتیب ساخت

**مرحله اول — هسته**
کلینیک و شعبه، تعریف کامل خدمات، منابع و مهارت‌ها، مدل بخش‌های نوبت، تقویم، جستجوی وقت، رزرو موقت و ثبت، قیمت پایه.

**مرحله دوم — قوانین**
موتور قوانین با شش دسته، فرم ساخت قانون، محیط آزمایش، نسخه‌بندی.

**مرحله سوم — کسب‌وکار**
دوره درمان، پکیج، بیعانه، سیاست لغو، لیست انتظار.

**مرحله چهارم — بهینه‌سازی**
استراتژی انتخاب منبع، پیشنهاد هوشمند وقت، گزارش بهره‌وری، پیش‌بینی عدم حضور.

---

## ۱۹. جمع‌بندی

سیستم از شش قدم تشکیل شده:

```
تعریف خدمات → ساخت برنامه نوبت → اعمال قوانین
        → پیدا کردن وقت → ثبت → قیمت‌گذاری
```

اگر بخواهیم سه چیز را از این مستند به یاد نگه داریم:

**۱. نوبت از چند بخش تشکیل شده، نه یک تکه.**
بدون این، ظرفیت واقعی کلینیک نصف نشان داده می‌شود.

**۲. قوانین باید ساده، دسته‌بندی‌شده و اولویت‌دار باشند.**
بدون این، جستجوی وقت کند می‌شود و رفتار سیستم غیرقابل پیش‌بینی.

**۳. جلوگیری از رزرو تکراری کار دیتابیس است، نه کار کد.**
بدون این، دیر یا زود دو نفر یک ساعت را می‌گیرند.

کلینیک زیبایی فقط یکی از کاربردهای این سیستم است. همین موتور بدون تغییر کد، دندانپزشکی، فیزیوتراپی و تصویربرداری را هم پوشش می‌دهد.
