Files
clinicpro/TEST_USERS.md
T
hamedandClaude Opus 5 1972fdd20f Document the resource-first model and retire the deleted tasks' checklists
docs/architecture/resource-first-model.md describes the shape: the three
entities, why an option is a ServiceItem rather than a fourth table, the
four-level resolution chain, the two conditions on the eligibility filter and
what each of them prevented, and why containment is a graph beside the display
tree rather than the tree itself.

docs/api/resource.md gains both offering endpoints with the response captured
from a real call, including a row where the price comes from the branch and one
where it comes from the resource — the two cases the *_source fields exist for.
docs/api/appointment.md documents resource_uuid, the doctor inference, and the
nullable resource/service_option in the response.

The checklists for tasks 9 to 14 keep their rows but open with a banner saying
the task was removed, when, by whose decision, and which commit to revert. They
are history now; deleting them would erase the record of work that shipped and
was then withdrawn.

Verified end to end: 1304 tests, slot-mode-frozen green, phpstan at 14, tsc
clean, 648 panel tests, and app:seed-scenarios --reset builds all three
environments.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 23:05:33 +03:30

138 lines
10 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.
# کاربران تستی
**پنل ادمین:** https://clinic-pro.ddev.site/admin — **سایت عمومی:** `yasuj-nobat.localhost:3000`
> رمز عبور همهٔ حساب‌های کارکنان: `QaTest@1234` · کد OTP در dev همیشه `12345`
کل این محیط با **یک دستور** ساخته می‌شود:
```bash
ddev exec php bin/console app:seed-scenarios --reset -n
```
`--reset` دیتابیس را کامل خالی می‌کند، migrationها را از صفر می‌زند، دادهٔ پایه
(نماینده‌ها → دسته‌بندی‌ها → کاتالوگ بیمه → خاموش‌کردن کپچا) را می‌سازد و بعد سه سناریو
را می‌چیند. بدون `--reset` فقط سناریوها ساخته می‌شوند و روی دیتابیسی که قبلاً seed شده
با خطا برمی‌گردد.
> **UUIDها با هر اجرا عوض می‌شوند.** جدول‌های زیر شکل داده را نشان می‌دهند نه شناسه‌های
> ثابت؛ برای گرفتن uuidهای فعلی از خود API یا دیتابیس بپرسید.
---
## سناریوی ۱ — پزشک مستقل، نوبت‌دهی سرویسی
| نقش | موبایل | توضیح |
|---|---|---|
| پزشک | `0912000101` | سارا مرادی — مطب شخصی، بدون کلینیک |
| منشی | `0912000109` | منشیِ همان پزشک |
| بیماران | `09120001100``09120001104` | ۵ بیمار با پرونده |
- **حالت نوبت‌دهی:** `service` · بافر ۱۰ دقیقه · شنبه تا چهارشنبه ۰۹:۰۰–۱۷:۰۰
- **سرویس‌ها:** مشاوره پوست (۲۰د) · لیزر صورت (۳۰د، additional ۲۰) · تزریق ژل (۴۵د) ·
میکرونیدلینگ (۶۰د، additional ۴۰)
- **بیمه:** تامین اجتماعی، بیمه ایران
- **نوبت‌ها:** ۹ نوبت در ۵ وضعیت (انجام‌شده، لغو کاربر، عدم حضور، تأییدشده، در انتظار پرداخت)
که دو تای آن‌ها **امروز** است
## سناریوی ۲ — پزشکی که مالک کلینیک است
| نقش | موبایل | توضیح |
|---|---|---|
| پزشک + مالک کلینیک | `0912000201` | امیر کاظمی — مالک «کلینیک تخصصی مهر»، خودش هم در کلینیک نوبت می‌دهد |
| پزشک عضو (سرویسی) | `0912000202` | نگار سلطانی |
| پزشک عضو (اسلاتی) | `0912000203` | بهرام فتحی |
| پزشک عضو (اسلاتی) | `0912000204` | الهام قاسمی |
| منشی | `0912000209` | روی هر ۴ پزشک |
| بیماران | `09120001200``09120001207` | ۸ بیمار |
- **ترکیب حالت‌ها:** ۲ سرویسی + ۲ اسلاتی، همه شنبه تا چهارشنبه ۱۶:۰۰–۲۱:۰۰
- **دستگاه‌ها:** ۲ لیزر (الکساندرایت، دایود) با setup/cleanup و تقویم کاری + ۲ اتاق درمان
- **سرویس‌ها:** لیزر کامل بدن (۹۰د) · لیزر زیربغل (۲۰د) · ویزیت پوست (۱۵د) · هیدرودرم (۴۵د)
- **وابستگی به دستگاه:** دو سرویس لیزری هرکدام یک بخش (`SegmentTemplate`) با نیازمندی
انحصاری روی نوع منبع «دستگاه لیزر» دارند
- **بیمه:** تامین اجتماعی، سلامت ایرانیان، بیمه آسیا
این حساب **دو محیط کاری** دارد (مطب شخصی + کلینیک). سرویس‌ها و دستگاه‌ها زیر محیط
*کلینیک* اند، پس تا وقتی محیط عوض نشود لیستشان خالی است — این درست است، نه باگ:
```bash
POST /api/v1/auth/switch-context {"db_uuid": "<clinic_uuid>"}
```
## سناریوی ۳ — کلینیک مستقل با مالکِ غیرپزشک
| نقش | موبایل | توضیح |
|---|---|---|
| مالک کلینیک | `0912000301` | رضا شریفی — **پزشک نیست**، فقط `ROLE_CLINIC` |
| پزشک (اسلاتی) | `0912000302` | پیمان اکبری |
| پزشک (سرویسی) | `0912000303` | مینا یوسفی |
| پزشک (منبع‌محور) | `0912000304` | آرش نوری |
| منشی | `0912000309` | روی هر ۳ پزشک |
| بیماران | `09120001300``09120001307` | ۸ بیمار |
- **هر سه حالت نوبت‌دهی** اینجا زنده‌اند: `slot`، `service` و `resource`
- **ساعت کاری:** شنبه تا پنجشنبه ۰۸:۰۰–۱۴:۰۰
- **دستگاه‌ها:** ۳ لیزر (CO2 فرکشنال، NdYAG، دایود) + دستگاه RF + دستگاه کرایو
- **سرویس‌ها:** ویزیت عمومی (۱۵د) · لیزر CO2 (۴۰د) · کرایوتراپی (۲۵د) · RF فرکشنال (۵۰د)
- **بیمه:** تامین اجتماعی، سلامت ایرانیان، بیمه دی
مالکِ غیرپزشک عمدی است: هر مسیری که فرض کند مالکِ کلینیک یک `Doctor` دارد، باید
همین‌جا بشکند نه در محیط واقعی.
---
## موتور نوبت‌دهی جدید (تسک‌های `docs/new_feture`)
هر سه محیط، علاوه بر داده‌های بالا، دادهٔ زندهٔ موتور جدید هم دارند:
| تسک | چه چیزی seed می‌شود | کجا دیده می‌شود |
|---|---|---|
| ۰۱ شعبه و اتاق | `DoctorAddress` به‌عنوان شعبه + منبع اتاق با تقویم | `GET /api/v1/resources` |
| ۰۲ مدل منبع | نوع منبع، دستگاه، **مهارت** (`کار با لیزر`) با سطح، **استخر منبع** با اولویت | `GET /api/v1/resources` · `/skills` |
| ۰۳ تقویم منبع | تقویم هفتگی هر دستگاه + یک **استثنای تعمیرات** هفتهٔ بعد | جستجوی آزاد آن بازه را رد می‌کند |
| ۰۴ کاتالوگ نسل دوم | دستهٔ درختی، **گروه انتخاب** با بازهٔ ۱ تا ۲، **ناسازگاری** دو سرویس، **override شعبه**، مدت solo/additional | `GET /api/v1/service-items` |
| ۰۵ برنامهٔ چندبخشی | سرویس اصلی هر محیط سه بخش دارد: بی‌حسی ۵د (اتاق انحصاری) → انتظار ۳۰د (اتاق **passive**) → لیزر ۲۰د (اتاق + دستگاه) | `GET /api/v1/service-item/{uuid}/segments` |
| ۰۶ موتور دسترس‌پذیری | همان برنامه با منابع واقعی جستجو می‌شود | `POST /api/v1/appointment-availability` |
| ۰۷ نگه‌داشتن و ثبت | **۲ نوبت در هر محیط از مسیر واقعی** hold → confirm، با بخش و اشغال منبع | `GET /api/v1/appointment/{uuid}/segments` |
| **منبع↔سرویس** | رابطهٔ چند‌به‌چند با مدت و قیمت اختصاصی: دو دستگاه یک سرویس را با اعداد متفاوت می‌دهند | `GET /api/v1/resource/{uuid}/services` |
| **دستهٔ مشترک** | دسته روی سرویس و منبع؛ یال «شامل بودن» بین دسته‌ها | مودال «سرویس‌ها» در صفحهٔ منابع |
| ۰۸ عکس قیمت | لیست قیمت فعال + `PriceSnapshot` روی نوبت‌های واقعی با بیعانه | `GET /api/v1/price-lists` |
> **تسک‌های ۹ تا ۱۴ (سیاست، پکیج، دوره، لغو/انتظار، رویداد و گزارش) به تصمیم مالک محصول
> از محصول حذف شده‌اند.** مدل فعلی فقط منبع، سرویس و گزینه است —
> [`docs/architecture/resource-first-model.md`](docs/architecture/resource-first-model.md).
نوبت‌های موتور جدید **از `new Appointment(...)` ساخته نمی‌شوند**؛ از
`AppointmentPlanBuilder``AvailabilityEngine``HoldService``BookingService` رد
می‌شوند. برای همین اشغال منبع واقعی است و تقویم دستگاه واقعاً پر است — نه ردیف‌هایی که
با INSERT ساخته شده‌اند و هیچ‌وقت از موتور رد نشده‌اند.
## چه چیزی با این داده قابل تست است
| قابلیت | کجا |
|---|---|
| نوبت‌دهی اسلاتی | `0912000203` · `0912000204` · `0912000302` |
| نوبت‌دهی سرویسی | `0912000101` · `0912000201` · `0912000202` · `0912000303` |
| نوبت‌دهی منبع‌محور | `0912000304` (با تخصیص واقعی دستگاه) |
| مطب شخصی در برابر کلینیک | سناریوی ۲ (یک کاربر، دو محیط) |
| مالک پزشک در برابر مالک اداری | سناریوی ۲ در برابر سناریوی ۳ |
| دستگاه و وابستگی سرویس به دستگاه | سناریوی ۲ و ۳ |
| بیمه (پایه و تکمیلی، فرانشیز، سقف) | هر سه محیط |
| پرداخت | ۳۲ پرداخت موفق روی نوبت‌های پرداخت‌شده |
| پرونده بیمار | ۲۱ پرونده با کد ملی روی پروفایل |
## نکته‌ها
- **کپچا:** روی دیتابیس تازه پیش‌فرضش **روشن** است و هیچ‌کس نمی‌تواند وارد شود.
سیدر ردیف `site_config.altcha_enabled = '0'` را می‌گذارد تا محیط قابل ورود بماند.
- **لاگین با رمز فقط برای کارکنان است.** فیلد درخواست `mobile_number` است نه `mobile`:
`POST /api/v1/user/login {"mobile_number": "...", "password": "..."}`.
بیماران (`ROLE_USER`) عمداً فقط با OTP وارد می‌شوند
(`send-code``verify-code` با `12345``otp-login`).
- **`send-code` سقف ۵ درخواست در ساعت به‌ازای هر IP دارد.**
- **نام پزشک بدون عنوان ذخیره می‌شود** — «دکتر» را لایهٔ نمایش اضافه می‌کند
(`PersianText::stripDoctorTitle`).
- **دادهٔ انبوه** جداست: `app:seed-demo-data` حدود ۵۰۰ پزشک و ۲۰هزار نوبت با INSERT خام
می‌سازد و برای تست کارایی و ماژول نمایندگان است، نه برای تست سناریویی.