# پایگاه داده — تسک ۱۱: پنل اشتراکی (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 | |

## ایندکس‌ها

```sql
-- جستجوی سریع اشتراک فعال
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 اولیه)

```sql
-- سه پنل پایه — باید در 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`
