Files
clinicpro/docs/new_feture/taskes/task-03-resource-calendar/database.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

113 lines
4.8 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.
# دیتابیس — تسک ۰۳
## `resource_calendars`
شیفت تکرارشوندهٔ هفتگی یک منبع.
| ستون | نوع | توضیح |
|---|---|---|
| `id` | INT PK AI | |
| `resource_id` | INT NOT NULL | FK → `clinic_resources.id` ON DELETE CASCADE |
| `day_of_week` | TINYINT NOT NULL | ۰=شنبه … ۶=جمعه |
| `sequence` | TINYINT NOT NULL DEFAULT 0 | |
| `start_minute` | SMALLINT NOT NULL | |
| `end_minute` | SMALLINT NOT NULL | |
| `valid_from` | INT NULL | شیفت فصلی؛ NULL = از همیشه |
| `valid_to` | INT NULL | NULL = تا همیشه |
| `active` | TINYINT(1) NOT NULL DEFAULT 1 | |
```sql
UNIQUE KEY uniq_rc_resource_day_seq (resource_id, day_of_week, sequence)
KEY idx_rc_resource_day (resource_id, day_of_week, active)
```
`valid_from/valid_to` از روز اول: شیفت تابستانی/زمستانی حالت رایج کلینیک است و
افزودنش بعداً یعنی یا حذف و ثبت دوبارهٔ شیفت‌ها یا یک جدول موازی.
فرزند aggregate با ریشهٔ `ClinicResource`.
## `resource_exceptions`
| ستون | نوع | توضیح |
|---|---|---|
| `id` | INT PK AI | |
| `uuid` | VARCHAR(36) UNIQUE | **از request می‌آید** → جفت tenant خودش را دارد |
| `entity_type` / `entity_id` | VARCHAR(10) / INT NOT NULL | از منبع مشتق می‌شود |
| `resource_id` | INT NOT NULL | FK ON DELETE CASCADE |
| `type` | VARCHAR(20) NOT NULL | `leave` \| `absence` \| `maintenance` \| `blocked` |
| `start_at` | INT NOT NULL | Unix |
| `end_at` | INT NOT NULL | Unix، `> start_at` |
| `reason` | VARCHAR(255) NULL | |
| `created_by` | INT NULL | FK → `users.id` ON DELETE SET NULL |
| `created_at` | INT NOT NULL | |
```sql
KEY idx_rex_tenant (entity_type, entity_id, start_at)
KEY idx_rex_resource_range (resource_id, start_at, end_at)
```
`idx_rex_resource_range` کوئری داغ است: «استثناهای این منبع که با [from, to) تداخل دارند».
> نوع `blocked` عمداً هست: مسدود کردن دستیِ یک بازه توسط منشی («امروز عصر کسی را نگذار»)
> با مرخصی یکی نیست و گزارش بهره‌وری (تسک ۱۴) باید تفکیکشان کند.
## `national_holidays`
| ستون | نوع | توضیح |
|---|---|---|
| `id` | INT PK AI | |
| `date` | INT NOT NULL UNIQUE | نیمه‌شب روز به وقت `Asia/Tehran`، Unix |
| `jalali_date` | VARCHAR(10) NOT NULL | `1405-01-13` — برای import و نمایش |
| `title` | VARCHAR(150) NOT NULL | |
| `is_official` | TINYINT(1) NOT NULL DEFAULT 1 | مناسبت غیرتعطیل هم ثبت می‌شود |
| `created_at` | INT NOT NULL | |
```sql
UNIQUE KEY uniq_national_holiday_date (date)
KEY idx_national_holiday_jalali (jalali_date)
```
سراسری — در `GlobalTables::ENTITIES` با دلیل: «تقویم رسمی کشور، مال هیچ محیطی نیست».
## `tenant_holiday_overrides`
| ستون | نوع | توضیح |
|---|---|---|
| `id` | INT PK AI | |
| `uuid` | VARCHAR(36) UNIQUE | |
| `entity_type` / `entity_id` | VARCHAR(10) / INT NOT NULL | |
| `date` | INT NOT NULL | نیمه‌شب روز |
| `is_working` | TINYINT(1) NOT NULL | true = روز رسمیِ تعطیل، برای ما کاری است |
| `note` | VARCHAR(255) NULL | |
| `created_at` | INT NOT NULL | |
```sql
UNIQUE KEY uniq_tho_tenant_date (entity_type, entity_id, date)
KEY idx_tho_tenant (entity_type, entity_id, date)
```
`is_working=false` هم معنی دارد: روزی که رسمی نیست ولی این محیط تعطیل است (مثلاً
تعطیلی سالانهٔ کلینیک). پس این جدول هر دو جهت را می‌پوشاند و `Holiday` موجود فقط برای
سازگاری عقب‌رو در حالت `slot`/`service` می‌ماند.
## Migration
```bash
ddev exec php bin/console doctrine:migrations:diff --no-interaction
ddev exec php bin/console doctrine:migrations:migrate --no-interaction
ddev exec php bin/console app:holiday:import --year=1405 --file=var/holidays-1405.json
```
`app:resource:calendar:backfill` (اختیاری، در همین تسک): برای هر منبعِ `type=doctor` که از
`WeeklySchedule` ساخته شده، شیفت‌های همان برنامه را به `resource_calendars` کپی می‌کند تا
تقویم منبع از روز اول خالی نباشد. dry-run پیش‌فرض.
## طبقه‌بندی tenant
| جدول | وضعیت | دلیل |
|---|---|---|
| `resource_calendars` | `AGGREGATE_CHILDREN` | ریشه `ClinicResource`؛ uuid از request نمی‌گیرد |
| `resource_exceptions` | جفت tenant | uuid از request می‌آید (`PATCH /resource-exception/{uuid}`) |
| `national_holidays` | `ENTITIES` | تقویم کشوری |
| `tenant_holiday_overrides` | جفت tenant | |