Files
clinicpro/docs/new_feture/taskes/task-02-resource-model/task.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

76 lines
4.4 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.
# تسک ۰۲ — مدل منبع: نوع منبع، منبع، مهارت، استخر
**فاز:** ۱ (هسته) · **وابستگی:** ۰۱ · **زمان:** ۱۴-۱۸ ساعت
---
## هدف
قانون طلایی اول مستند: «تقویم مال منبع است، نه مال پزشک». امروز تنها موجودیتی که
می‌تواند اشغال شود پزشک است و پرسنل (`ClinicStaff`) فقط یک برچسب روی سرویس و نوبت است.
این تسک لایهٔ منبع را می‌سازد: هر چیزی که ممکن است اشغال باشد — پزشک، اپراتور، دستیار،
دستگاه، اتاق، تخت، یونیت.
## وضعیت فعلی
```php
// src/Staff/Entity/ClinicStaff.php — تنها «منبع» امروز
private string $fullName;
private ?string $jobTitle; // متن آزاد، بدون معنای ساختاری
private bool $active;
private ?User $user; // برای ورود به پنل
```
بدون تقویم، بدون ظرفیت، بدون مهارت. `ServiceItem.staffMembers` یک ManyToMany به همین است
و `Appointment.staff_id` یک ارجاع تکی — هیچ‌کدام تداخل زمانی را بررسی نمی‌کنند.
## دامنه
**هست:** `ResourceType`، `Resource`، `Skill`، `ResourceSkill`، `ResourcePool`،
`ResourcePoolMember`، ویژگی‌های آزاد (`attributes` JSON)، ظرفیت هم‌زمان،
زمان آماده‌سازی/تمیزکاری per منبع، CRUD پنل، و **پل زدن `ClinicStaff` و `Doctor` و `Room`
به `Resource`**.
**نیست:** تقویم و مرخصی (تسک ۰۳)، نیازمندی منبع per بخش (تسک ۰۵)، محاسبهٔ اشغال (تسک ۰۶/۰۷).
## Endpoint ها
| متد | مسیر | توضیح |
|---|---|---|
| GET/POST | `/api/v1/resource-types` | نوع منبع (کلینیک خودش تعریف می‌کند) |
| PATCH/DELETE | `/api/v1/resource-type/{uuid}` | |
| GET | `/api/v1/resources` | لیست با فیلتر `branch_uuid`, `type_uuid`, `active` |
| POST | `/api/v1/resource` | ساخت منبع |
| GET/PATCH/DELETE | `/api/v1/resource/{uuid}` | |
| GET/POST | `/api/v1/skills` | مهارت‌ها |
| PATCH/DELETE | `/api/v1/skill/{uuid}` | |
| PUT | `/api/v1/resource/{uuid}/skills` | جایگزینی کامل مهارت‌های منبع |
| GET/POST | `/api/v1/resource-pools` | استخر منابع قابل جایگزینی |
| PATCH/DELETE | `/api/v1/resource-pool/{uuid}` | |
| PUT | `/api/v1/resource-pool/{uuid}/members` | جایگزینی کامل اعضا |
## معیار پذیرش
- ✅ موفق: کلینیک نوع منبع «دستگاه لیزر» می‌سازد، سه منبع از آن نوع در شعبهٔ مرکزی ثبت
می‌کند، یک استخر «لیزرهای آلکساندرایت» می‌سازد و هر سه را عضو می‌کند →
`GET /api/v1/resource-pool/{uuid}` هر سه را با `branch_uuid` برمی‌گرداند.
- ✅ موفق: مهارت «لیزر آلکساندرایت» ساخته و به دو اپراتور داده می‌شود →
`GET /api/v1/resources?skill_uuid=…` فقط همان دو را برمی‌گرداند.
- ✅ موفق: بعد از اجرای `app:resource:backfill`، هر `ClinicStaff` فعال یک `Resource` با
`type=staff` و هر `Doctor` دارای برنامه یک `Resource` با `type=doctor` دارد.
- ❌ خطا: منبع با `branch_uuid` متعلق به محیط دیگر → `404`.
- ❌ خطا: عضو کردن منبعی از شعبهٔ A در استخری که منابعش در شعبهٔ B هستند → `422`
«همهٔ اعضای استخر باید در یک شعبه باشند».
- ⚠️ مرزی: `capacity = 3` روی اتاق تزریق → یک ردیف، نه سه. `GET` مقدار ۳ را برمی‌گرداند.
- ⚠️ مرزی: `setup_minutes = 0, cleanup_minutes = 10` → معتبر.
- ⚠️ مرزی: حذف مهارتی که به منبعی داده شده → `422`؛ باید اول از منابع برداشته شود.
- ⚠️ مرزی: `attributes` با کلید ناشناخته → پذیرفته می‌شود (عمداً آزاد)، ولی مقدار غیر
اسکالر → `422`.
## خروجی
- `src/Resource/` کامل با تست
- صفحات پنل: `ResourcesPage`, `ResourceFormPage`, `ResourceTypesPage`, `SkillsPage`, `ResourcePoolsPage`
- `docs/api/resource.md`
- `app:resource:backfill` (dry-run پیش‌فرض)