Files
clinicpro/docs/new_feture/taskes/task-05-appointment-plan/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

4.6 KiB
Raw Blame History

دیتابیس — تسک ۰۵

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