Files
clinicpro/docs/phase2_taskes/task-11-subscription/database.md
T

4.6 KiB
Raw Blame History

پایگاه داده — تسک ۱۱: پنل اشتراکی (Subscription Tiers)

جدول: subscription_plans

ستون نوع توضیح
id INT UNSIGNED AUTO_INCREMENT PK
uuid CHAR(36) UNIQUE NOT NULL
name VARCHAR(30) NOT NULL 'free' | 'basic' | 'professional'
level TINYINT NOT NULL 0, 1, یا 2
max_secretaries TINYINT NOT NULL 1, 2، یا 5
features JSON NOT NULL {"patient_records": bool, "services": bool, "sms_panel": bool}
active TINYINT(1) NOT NULL DEFAULT 1
created_at INT NOT NULL Unix timestamp
updated_at INT NOT NULL Unix timestamp

جدول: subscription_periods

ستون نوع توضیح
id INT UNSIGNED AUTO_INCREMENT PK
uuid CHAR(36) UNIQUE NOT NULL
plan_id INT NOT NULL FK→subscription_plans.id ON DELETE CASCADE
label VARCHAR(50) NOT NULL مثال: '۶ ماهه', 'تریال ۱ ماهه'
duration_months TINYINT NOT NULL مدت به ماه
price_rials INT NOT NULL 0 برای تریال
is_trial TINYINT(1) NOT NULL DEFAULT 0
active TINYINT(1) NOT NULL DEFAULT 1
sort_order TINYINT NOT NULL DEFAULT 0 ترتیب نمایش
created_at INT NOT NULL
updated_at INT NOT NULL

جدول: clinic_subscriptions

ستون نوع توضیح
id INT UNSIGNED AUTO_INCREMENT PK
uuid CHAR(36) UNIQUE NOT NULL
entity_type VARCHAR(10) NOT NULL 'doctor' | 'clinic'
entity_id INT NOT NULL id دکتر یا کلینیک
plan_id INT NOT NULL FK→subscription_plans.id
period_id INT NOT NULL FK→subscription_periods.id
payment_id INT NULL FK→payments.id ON DELETE SET NULL NULL برای تریال
is_trial TINYINT(1) NOT NULL DEFAULT 0
starts_at INT NOT NULL Unix timestamp
expires_at INT NULL NULL = بی‌نهایت (Free)
created_at INT NOT NULL

ایندکس‌ها

-- جستجوی سریع اشتراک فعال
CREATE INDEX idx_clinic_subscriptions_entity
  ON clinic_subscriptions(entity_type, entity_id, expires_at);

-- جلوگیری از استفاده مکرر از تریال
-- توجه: این constraint روی is_trial=1 کار می‌کند چون is_trial=0 می‌تواند تکراری باشد
-- بنابراین در application check می‌کنیم نه UNIQUE index
CREATE INDEX idx_clinic_subscriptions_trial
  ON clinic_subscriptions(entity_type, entity_id, is_trial);

Seed Data (Migration اولیه)

-- سه پنل پایه — باید در migration ایجاد شوند
INSERT INTO subscription_plans (uuid, name, level, max_secretaries, features, active, created_at, updated_at) VALUES
  (UUID(), 'free',         0, 1, '{"patient_records":false,"services":false,"sms_panel":false}', 1, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
  (UUID(), 'basic',        1, 2, '{"patient_records":true,"services":true,"sms_panel":false}',  1, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
  (UUID(), 'professional', 2, 5, '{"patient_records":true,"services":true,"sms_panel":true}',  1, UNIX_TIMESTAMP(), UNIX_TIMESTAMP());

-- دوره‌های نمونه برای basic (ادمین بعداً قیمت‌ها را ویرایش می‌کند)
-- plan_id=2 = basic
INSERT INTO subscription_periods (uuid, plan_id, label, duration_months, price_rials, is_trial, active, sort_order, created_at, updated_at) VALUES
  (UUID(), 2, 'تریال ۱ ماهه', 1, 0,       1, 1, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
  (UUID(), 2, '۱ ماهه',       1, 250000,  0, 1, 1, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
  (UUID(), 2, '۳ ماهه',       3, 690000,  0, 1, 2, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
  (UUID(), 2, '۶ ماهه',       6, 1200000, 0, 1, 3, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()),
  (UUID(), 2, '۱۲ ماهه',     12, 2000000, 0, 1, 4, UNIX_TIMESTAMP(), UNIX_TIMESTAMP());

SiteConfig key های جدید

کلید نوع مقدار پیش‌فرض توضیح
trial_enabled string '1'|'0' '1' ادمین می‌تواند تریال را غیرفعال کند

نکات مهم

  • expires_at = NULL فقط برای رکوردهای Free plan است — این‌ها بی‌نهایت معتبرند
  • query اشتراک فعال: WHERE entity_type=? AND entity_id=? AND (expires_at IS NULL OR expires_at > UNIX_TIMESTAMP()) ORDER BY id DESC LIMIT 1
  • تریال check در application: SELECT COUNT(*) FROM clinic_subscriptions WHERE entity_type=? AND entity_id=? AND is_trial=1