- 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.
4.6 KiB
دیتابیس — تسک ۰۵
segment_templates
| ستون | نوع | توضیح |
|---|---|---|
id |
INT PK AI | |
uuid |
VARCHAR(36) UNIQUE | از request میآید |
entity_type / entity_id |
VARCHAR(10) / INT NOT NULL | |
owner_type |
VARCHAR(10) NOT NULL | service | option |
service_item_id |
INT NULL | FK → service_items.id ON DELETE CASCADE |
service_option_id |
INT NULL | FK → service_options.id ON DELETE CASCADE |
name |
VARCHAR(150) NOT NULL | |
segment_type |
VARCHAR(40) NOT NULL | کلید ادغام |
sequence |
SMALLINT NOT NULL | |
fixed_minutes |
SMALLINT NULL | |
duration_share |
SMALLINT NULL | درصد ۰..۱۰۰ |
patient_present |
TINYINT(1) NOT NULL DEFAULT 1 | |
mergeable |
TINYINT(1) NOT NULL DEFAULT 0 | |
active |
TINYINT(1) NOT NULL DEFAULT 1 | |
created_at/updated_at |
INT NOT NULL |
KEY idx_seg_tpl_tenant (entity_type, entity_id, active)
KEY idx_seg_tpl_service (service_item_id, sequence)
KEY idx_seg_tpl_option (service_option_id, sequence)
قیدهای اپلیکیشنی (در سازنده/سرویس، نه CHECK):
- دقیقاً یکی از
service_item_id/service_option_idغیر-NULL و باowner_typeسازگار - دقیقاً یکی از
fixed_minutes/duration_shareغیر-NULL - جمع
duration_shareبخشهای یک سرویس = ۱۰۰ (اگر حداقل یکی سهمی باشد)
segment_requirements
| ستون | نوع | توضیح |
|---|---|---|
id |
INT PK AI | |
uuid |
VARCHAR(36) UNIQUE | |
segment_template_id |
INT NOT NULL | FK ON DELETE CASCADE |
resource_type_id |
INT NOT NULL | FK → resource_types.id ON DELETE RESTRICT |
count |
SMALLINT NOT NULL DEFAULT 1 | |
resource_pool_id |
INT NULL | FK → resource_pools.id ON DELETE SET NULL |
specific_resource_id |
INT NULL | FK → clinic_resources.id ON DELETE SET NULL |
required_skills |
JSON NULL | آرایهٔ skill_id |
constraints |
JSON NULL | فهرست بسته — جدول architecture |
occupancy |
VARCHAR(10) NOT NULL DEFAULT 'exclusive' | exclusive|shared|passive |
sort_order |
SMALLINT NOT NULL DEFAULT 0 |
KEY idx_seg_req_segment (segment_template_id, sort_order)
KEY idx_seg_req_pool (resource_pool_id)
فرزند aggregate با ریشهٔ SegmentTemplate — uuid از request فقط در
PUT /segment-template/{uuid}/requirements میآید که خودش از ریشه لنگر میخورد،
پس ستون tenant لازم ندارد.
required_skillsعمداً JSON است نه جدول واسط: همیشه کامل خوانده و کامل جایگزین میشود، و هیچ کوئریای از سمت مهارت به نیازمندی نمیرود. جدول واسط اینجا فقط سه JOIN اضافه به مسیر داغ تسک ۰۶ میآورد.
هیچ جدول جدیدی برای «برنامهٔ ساختهشده» نیست
AppointmentPlan یک DTO درونحافظهای است، نه entity. ذخیرهاش وقتی معنی پیدا میکند که
نوبت ثبت شود — که کار تسک ۰۷ است (appointment_segments).
دلیل: برنامه یک تابع خالص از (سرویس، آیتمها، بیمار، شعبه، قوانین فعال) است. ذخیرهکردنش پیش از ثبت یعنی نگهداشتن حالت موقتی که باید منقضی شود — همان مسئلهای که رزرو موقت تسک ۰۷ حل میکند و دو مکانیزم موازی لازم نیست.
Migration
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:segment:seed-templates --preset=beauty --tenant=clinic:12 --force
app:segment:seed-templates سه پریست دارد (مستند بند ۱۷: «الگوی آماده برای هر نوع کلینیک»):
| پریست | بخشها |
|---|---|
beauty |
آمادهسازی ۵ · انتظار ۳۰ (فقط اتاق) · درمان (سهمی ۱۰۰) · مراقبت ۵ |
dental |
آمادهسازی ۵ · درمان (سهمی ۱۰۰) · تمیزکاری یونیت ۱۰ (بدون حضور بیمار) |
physio |
درمان (سهمی ۱۰۰) |
dry-run پیشفرض. پریستها روی سرویسهای موجود اعمال نمیشوند مگر با --service=<uuid>.
طبقهبندی tenant
| جدول | وضعیت |
|---|---|
segment_templates |
جفت tenant |
segment_requirements |
AGGREGATE_CHILDREN → ریشه SegmentTemplate |