- 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.
62 lines
3.7 KiB
Markdown
62 lines
3.7 KiB
Markdown
# تسک ۰۱ — شعبه (Branch) و اتاق (Room)
|
||
|
||
**فاز:** ۱ (هسته) · **وابستگی:** — · **زمان:** ۱۰-۱۲ ساعت
|
||
|
||
---
|
||
|
||
## هدف
|
||
|
||
سطح سوم مکان را به مدل اضافه کن: امروز `(entity_type, entity_id)` میگوید داده مال کدام
|
||
محیط است، ولی نمیگوید در کدام **ساختمان** و کدام **اتاق**. مستند بند ۴ سه سطح میخواهد
|
||
و «منابع همیشه مال شعبهاند چون فیزیکیاند» — بدون شعبه، تسک ۰۲ جایی برای نشستن ندارد.
|
||
|
||
## وضعیت فعلی
|
||
|
||
- محل مراجعه امروز `DoctorAddress` است و `location_id` هر شیفت در
|
||
`WeeklySchedule.setting[day].sessions[].location_id` به `doctor_addresses.id` اشاره میکند
|
||
(`SlotCalculatorService::buildSessionSlots()` آن را در هر اسلات کپی میکند).
|
||
- `Clinic` هیچ فیلد شعبهای ندارد؛ یک آدرس متنی تخت دارد.
|
||
- ساعت کاری شعبه وجود ندارد — ساعت کاری فقط روی برنامهٔ پزشک است.
|
||
|
||
## دامنه
|
||
|
||
**هست:** entity های `Branch` و `Room`، ساعت کاری هفتگی شعبه، CRUD پنل ادمین،
|
||
پل زدن `DoctorAddress.branch_id` برای اینکه شیفتهای موجود بدون تغییر به شعبه نگاشت شوند.
|
||
|
||
**نیست:** استفاده از شعبه در محاسبهٔ اسلات (تسک ۰۳)، اتاق بهعنوان منبع قابل رزرو (تسک ۰۲).
|
||
|
||
## Endpoint ها
|
||
|
||
| متد | مسیر | توضیح |
|
||
|---|---|---|
|
||
| GET | `/api/v1/branches` | لیست شعب محیط جاری (paginated) |
|
||
| POST | `/api/v1/branch` | ساخت شعبه |
|
||
| GET | `/api/v1/branch/{uuid}` | جزئیات + ساعت کاری |
|
||
| PATCH | `/api/v1/branch/{uuid}` | ویرایش |
|
||
| DELETE | `/api/v1/branch/{uuid}` | حذف (فقط بدون منبع/اتاق فعال) |
|
||
| PUT | `/api/v1/branch/{uuid}/working-hours` | ثبت ساعت کاری هفتگی |
|
||
| GET | `/api/v1/branch/{uuid}/rooms` | اتاقهای شعبه |
|
||
| POST/PATCH/DELETE | `/api/v1/room[/{uuid}]` | CRUD اتاق |
|
||
|
||
## معیار پذیرش
|
||
|
||
- ✅ موفق: کلینیک با توکن مالک `POST /api/v1/branch` میزند → `201` و شعبه با
|
||
`entity_type=clinic, entity_id=<id>` ثبت میشود. `GET /api/v1/branches` همان را برمیگرداند.
|
||
- ✅ موفق: `PUT /branch/{uuid}/working-hours` با هفت روز → `200`؛ `GET /branch/{uuid}` همان
|
||
ساختار را با کلیدهای `0..6` (۰=شنبه) برمیگرداند.
|
||
- ❌ خطا: کلینیک B با uuid شعبهٔ کلینیک A → `404` با `ERR_NOT_FOUND_001` (نه ۴۰۳ — طبق
|
||
رفتار `TenantFilter`).
|
||
- ❌ خطا: `DELETE` شعبهای که اتاق فعال دارد → `422` با پیام فارسی «شعبه دارای اتاق فعال است».
|
||
- ⚠️ مرزی: پزشک مستقل (محیط `doctor`) هم میتواند شعبه بسازد — «مطب» یک شعبه است.
|
||
اولین شعبه از روی `DoctorAddress` موجود ساخته میشود، نه دستی.
|
||
- ⚠️ مرزی: ساعت کاری با `end_time <= start_time` → `422`.
|
||
- ⚠️ مرزی: شعبه بدون ساعت کاری معتبر است (وراثت: تسک ۰۳ آن را «همیشه باز» تفسیر نمیکند،
|
||
«تعریفنشده» تفسیر میکند).
|
||
|
||
## خروجی
|
||
|
||
- `src/Branch/` کامل با تست
|
||
- `assets/admin/pages/BranchesPage.tsx` + `BranchFormPage.tsx` + `RoomsPage.tsx`
|
||
- `docs/api/branch.md`
|
||
- migration + دستور `app:branch:backfill` برای ساخت شعبهٔ اولیه از آدرسهای موجود
|