# پایگاه داده — تسک ۱۴: پنل پیامکی

## جدول: sms_wallets

| ستون | نوع | توضیح |
|------|-----|-------|
| id | INT UNSIGNED AUTO_INCREMENT PK | |
| entity_type | VARCHAR(10) NOT NULL | `'doctor'` \| `'clinic'` |
| entity_id | INT NOT NULL | |
| balance_rials | INT NOT NULL DEFAULT 0 | موجودی فعلی |
| created_at | INT NOT NULL | |
| updated_at | INT NOT NULL | |
| UNIQUE | (entity_type, entity_id) | یک wallet به ازای هر entity |

## جدول: sms_wallet_transactions

| ستون | نوع | توضیح |
|------|-----|-------|
| id | INT UNSIGNED AUTO_INCREMENT PK | |
| uuid | CHAR(36) UNIQUE NOT NULL | |
| sms_wallet_id | INT NOT NULL FK→sms_wallets.id ON DELETE CASCADE | |
| type | VARCHAR(10) NOT NULL | `'credit'` \| `'debit'` |
| amount_rials | INT NOT NULL | مبلغ (همیشه مثبت) |
| description | VARCHAR(255) NULL | توضیح |
| payment_id | INT NULL FK→payments.id ON DELETE SET NULL | برای شارژ |
| created_at | INT NOT NULL | |

ایندکس:
```sql
INDEX idx_sms_wallet_tx ON sms_wallet_transactions(sms_wallet_id, created_at)
```

## جدول: sms_settings

| ستون | نوع | توضیح |
|------|-----|-------|
| id | INT UNSIGNED AUTO_INCREMENT PK | |
| entity_type | VARCHAR(10) NOT NULL | |
| entity_id | INT NOT NULL | |
| reminder_enabled | TINYINT(1) NOT NULL DEFAULT 0 | |
| reminder_hours_before | TINYINT NOT NULL DEFAULT 2 | چند ساعت قبل از نوبت |
| post_visit_enabled | TINYINT(1) NOT NULL DEFAULT 0 | |
| post_visit_text | TEXT NULL | متن پیامک بعد از ویزیت |
| updated_at | INT NOT NULL | |
| UNIQUE | (entity_type, entity_id) | |

## SiteConfig key جدید

| کلید | نوع | مقدار پیش‌فرض | توضیح |
|------|-----|--------------|-------|
| `sms_price_rials` | string | `'250'` | قیمت هر پیامک — ادمین تنظیم می‌کند |

## Migration نمونه

```sql
CREATE TABLE sms_wallets (
    id           INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    entity_type  VARCHAR(10) NOT NULL,
    entity_id    INT NOT NULL,
    balance_rials INT NOT NULL DEFAULT 0,
    created_at   INT NOT NULL,
    updated_at   INT NOT NULL,
    UNIQUE KEY uniq_sms_wallet_entity (entity_type, entity_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE sms_wallet_transactions (
    id            INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    uuid          CHAR(36) NOT NULL UNIQUE,
    sms_wallet_id INT NOT NULL,
    type          VARCHAR(10) NOT NULL,
    amount_rials  INT NOT NULL,
    description   VARCHAR(255) NULL,
    payment_id    INT NULL,
    created_at    INT NOT NULL,
    FOREIGN KEY (sms_wallet_id) REFERENCES sms_wallets(id) ON DELETE CASCADE,
    FOREIGN KEY (payment_id)    REFERENCES payments(id) ON DELETE SET NULL,
    INDEX idx_sms_wallet_tx (sms_wallet_id, created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE sms_settings (
    id                    INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    entity_type           VARCHAR(10) NOT NULL,
    entity_id             INT NOT NULL,
    reminder_enabled      TINYINT(1) NOT NULL DEFAULT 0,
    reminder_hours_before TINYINT NOT NULL DEFAULT 2,
    post_visit_enabled    TINYINT(1) NOT NULL DEFAULT 0,
    post_visit_text       TEXT NULL,
    updated_at            INT NOT NULL,
    UNIQUE KEY uniq_sms_settings_entity (entity_type, entity_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```

## نکات مهم

- `balance_rials` هرگز منفی نمی‌شود — در `SmsWalletService::deduct()` چک می‌شود
- `sms_wallet_transactions` لاگ کامل تمام تراکنش‌ها است — حذف نمی‌شود
- `sms_settings` با UPSERT ذخیره می‌شود (اگر وجود نداشت INSERT، وگرنه UPDATE)
