# 機能設計書 186-ポリシーインボックス制限

## 概要

本ドキュメントは、Chatwootにおける「ポリシーインボックス制限」機能の設計仕様を定義する。本機能は、エージェント容量ポリシーに対してインボックスごとの会話制限数を設定するためのエンタープライズ専用機能である。

### 本機能の処理概要

本機能は、管理者が特定の容量ポリシーに対してインボックスごとの会話制限を設定することを可能にする。これにより、インボックスの特性（複雑な案件が多い、簡単な問い合わせが多いなど）に応じた細かな容量制御が可能になる。

**業務上の目的・背景**：インボックスによって会話の複雑さや対応時間が異なる場合がある。例えば、技術サポートのインボックスは1件あたりの対応時間が長いため少ない会話数を、FAQインボックスは短い対応時間で多くの会話を処理できる。インボックスごとの制限により、エージェントの実質的な作業負荷を均等化できる。

**機能の利用シーン**：新しいインボックスを追加した際に、そのインボックス固有の容量制限を設定する。既存の制限値を業務量に応じて調整する。不要になった制限を削除する。

**主要な処理内容**：
1. インボックス制限の作成
2. インボックス制限の更新
3. インボックス制限の削除

**関連システム・外部連携**：容量ポリシー機能（No.184）、自動割り当て機能

**権限による制御**：エンタープライズアカウントの管理者のみがアクセス可能

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 86 | エージェント容量編集 | 主画面 | インボックス制限の設定 |

## 機能種別

CRUD操作 / 設定管理 / Enterprise機能

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| agent_capacity_policy_id | Integer | Yes | ポリシーID | URLパスパラメータ |
| inbox_id | Integer | Yes（create時） | インボックスID | アカウント内のインボックス |
| conversation_limit | Integer | Yes | 会話制限数 | 正の整数（1以上） |
| id | Integer | Yes（update/destroy時） | 制限ID | URLパスパラメータ |

### 入力データソース

- APIリクエスト（JSON形式）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | Integer | 制限ID |
| inbox_id | Integer | インボックスID |
| conversation_limit | Integer | 会話制限数 |
| agent_capacity_policy_id | Integer | ポリシーID |

### 出力先

- HTTPレスポンス（JSON形式）

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ アクション種別を判定

2. ポリシー取得
   └─ agent_capacity_policy_idでポリシーを取得

3. 認可チェック
   └─ AgentCapacityPolicyに対する権限を確認

4. アクション実行
   ├─ create: インボックス制限の新規作成
   │      └─ 重複チェック
   ├─ update: 制限値の更新
   └─ destroy: 制限の削除

5. レスポンス返却
   └─ JSON形式またはhead :no_content
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B[fetch_policy]
    B --> C[check_authorization]
    C --> D{アクション}

    D -->|create| E[fetch_inbox]
    D -->|update| F[fetch_inbox_limit]
    D -->|destroy| F

    E --> G[validate_no_duplicate]
    G --> H{重複あり?}
    H -->|Yes| I[エラーレスポンス]
    H -->|No| J[inbox_capacity_limits.create!]

    F --> K{アクション}
    K -->|update| L[conversation_limit更新]
    K -->|destroy| M[制限削除]

    J --> N[レスポンス返却]
    L --> N
    M --> O[head :no_content]

    I --> P[終了]
    N --> P
    O --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-186-01 | エンタープライズ専用 | 本機能はエンタープライズエディションでのみ利用可能 | 常時 |
| BR-186-02 | 重複禁止 | 同一ポリシー内で同一インボックスに対する制限は1つのみ | 作成時 |
| BR-186-03 | 正の整数 | conversation_limitは1以上の正の整数 | 作成・更新時 |
| BR-186-04 | アカウント境界 | 同一アカウント内のインボックスのみ設定可能 | 常時 |

### 計算ロジック

特になし

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 新規作成 | inbox_capacity_limits | INSERT | インボックス制限の作成 |
| 更新 | inbox_capacity_limits | UPDATE | 制限値の更新 |
| 削除 | inbox_capacity_limits | DELETE | 制限の削除 |

### テーブル別操作詳細

#### inbox_capacity_limits

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | agent_capacity_policy_id = @agent_capacity_policy.id | 重複チェック |
| INSERT | inbox_id | リクエストパラメータ | |
| INSERT | conversation_limit | リクエストパラメータ | |
| INSERT | agent_capacity_policy_id | @agent_capacity_policy.id | |
| UPDATE | conversation_limit | リクエストパラメータ | |
| DELETE | - | id = params[:id] | |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 403 | Forbidden | 非エンタープライズアカウント | エラーレスポンス返却 |
| 403 | Forbidden | 権限不足 | エラーレスポンス返却 |
| 404 | Not Found | ポリシーが存在しない | エラーレスポンス返却 |
| 404 | Not Found | インボックスが存在しない | エラーレスポンス返却 |
| 422 | Unprocessable Entity | 重複したインボックス制限 | I18nメッセージ付きエラー |
| 422 | Unprocessable Entity | バリデーションエラー | エラーメッセージ返却 |

### リトライ仕様

同期処理のため、リトライ仕様は適用されない。

## トランザクション仕様

create! / update! / destroy! による暗黙的なトランザクション制御。

## パフォーマンス要件

- 単純なCRUD操作のため、特別なパフォーマンス要件なし
- 応答時間: 通常100ms以内

## セキュリティ考慮事項

- エンタープライズエディション専用機能
- AgentCapacityPolicyに対する権限チェック
- アカウント境界の厳守（インボックス取得時にCurrent.accountでスコープ）

## 備考

- ユニーク制約: (agent_capacity_policy_id, inbox_id)の組み合わせ
- 削除時は204 No Contentを返却

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、インボックス制限のデータモデルを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | inbox_capacity_limit.rb | `enterprise/app/models/inbox_capacity_limit.rb` | 制限モデルの構造 |

**読解のコツ**:
- **18-20行目**: belongs_toリレーション定義
- **22行目**: conversation_limitのバリデーション（presence, numericality）
- **23行目**: ユニーク制約（inbox_id, scope: agent_capacity_policy_id）
- **14行目（スキーマコメント）**: ユニークインデックスの定義

#### Step 2: コントローラーアクションを理解する

インボックス制限APIの実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | inbox_limits_controller.rb | `enterprise/app/controllers/api/v1/accounts/agent_capacity_policies/inbox_limits_controller.rb` | CRUD実装 |

**主要処理フロー**:
- **2行目**: check_authorization(AgentCapacityPolicy) - ポリシーに対する権限チェック
- **6行目**: validate_no_duplicate - 重複チェックのコールバック
- **8-13行目**: createアクション - 制限の新規作成
- **15-17行目**: updateアクション - 制限値の更新
- **19-22行目**: destroyアクション - 制限の削除
- **38-42行目**: validate_no_duplicateメソッド - 重複時のエラーレスポンス

#### Step 3: バリデーションロジックを理解する

重複チェックの仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | inbox_limits_controller.rb | `enterprise/app/controllers/api/v1/accounts/agent_capacity_policies/inbox_limits_controller.rb` | validate_no_duplicate |

**主要処理フロー**:
- **38-42行目**: 既存レコードのexists?チェック
- **41行目**: render_could_not_create_error - I18nエラーメッセージ

### プログラム呼び出し階層図

```
APIリクエスト
    │
    ├─ EnterpriseAccountsController (継承)
    │
    └─ AgentCapacityPolicies::InboxLimitsController
           │
           ├─ before_action :check_authorization(AgentCapacityPolicy)
           ├─ before_action :fetch_policy
           ├─ before_action :fetch_inbox (create)
           ├─ before_action :fetch_inbox_limit (update, destroy)
           ├─ before_action :validate_no_duplicate (create)
           │
           ├─ create
           │      └─ @agent_capacity_policy.inbox_capacity_limits.create!(
           │             inbox: @inbox,
           │             conversation_limit: permitted_params[:conversation_limit]
           │         )
           │
           ├─ update
           │      └─ @inbox_limit.update!(conversation_limit: permitted_params[:conversation_limit])
           │
           └─ destroy
                  └─ @inbox_limit.destroy!
```

### データフロー図

```
[入力]                          [処理]                              [出力]

APIリクエスト ─────────▶ InboxLimitsController ───────────▶ JSON Response
(inbox_id,                    │
conversation_limit)           ▼
                     fetch_policy
                     (ポリシー取得)
                             │
                             ▼
                     fetch_inbox / fetch_inbox_limit
                             │
                             ▼
                     validate_no_duplicate (create時)
                             │
                             ▼
                     inbox_capacity_limits テーブル
                     (create!/update!/destroy!)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| inbox_limits_controller.rb | `enterprise/app/controllers/api/v1/accounts/agent_capacity_policies/inbox_limits_controller.rb` | コントローラー | インボックス制限API |
| inbox_capacity_limit.rb | `enterprise/app/models/inbox_capacity_limit.rb` | モデル | インボックス制限モデル |
| agent_capacity_policy.rb | `enterprise/app/models/agent_capacity_policy.rb` | モデル | ポリシーモデル |
| inbox.rb | `app/models/inbox.rb` | モデル | インボックスモデル |
