# 機能設計書 182-ボット割り当て

## 概要

本ドキュメントは、Chatwootにおける「ボット割り当て」機能の設計仕様を定義する。本機能は、特定のインボックスにエージェントボットを配置し、そのインボックスで発生する会話イベントをボットが自動処理できるようにするための管理機能である。

### 本機能の処理概要

本機能は、管理者がインボックスにエージェントボットを割り当て、または割り当てを解除することを可能にする。割り当てられたボットは、そのインボックスで発生する会話イベントを受信し、Webhook経由で外部システムと連携して自動応答を行う。

**業務上の目的・背景**：カスタマーサポート業務において、チャネルごとに異なるボットを配置したい場合がある。例えば、Webウィジェットには汎用的なFAQボットを、WhatsAppには商品注文専用ボットを配置するなど、チャネル特性に応じたボット運用が必要となる。本機能により、インボックス単位でのボット管理が可能となり、柔軟な自動応答体制を構築できる。

**機能の利用シーン**：新しいインボックスを作成した後、そのインボックスに適切なボットを割り当てる。既存のボット割り当てを変更したい場合、別のボットに切り替える。ボットによる自動応答を一時停止したい場合、割り当てを解除する。

**主要な処理内容**：
1. インボックスへのボット割り当て（新規作成または更新）
2. 既存のボット割り当ての解除（削除）
3. agent_bot_inboxレコードの管理

**関連システム・外部連携**：インボックス管理機能、ボット応答機能（No.181）との連携

**権限による制御**：インボックス設定の変更権限を持つ管理者のみが操作可能

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 50 | インボックス設定画面 | 主画面 | インボックスへのボット配置設定 |
| 74 | エージェントボット一覧画面 | 参照画面 | ボットの選択 |

## 機能種別

CRUD操作 / 設定管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | Integer | Yes | インボックスID | 存在するインボックスであること |
| agent_bot | Integer | No | エージェントボットID | 存在するボットであること、nullの場合は割り当て解除 |

### 入力データソース

- APIリクエスト: POST /api/v1/accounts/{account_id}/inboxes/{id}/set_agent_bot
- パラメータ: agent_bot（ボットIDまたはnull）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| HTTP Status | Integer | 200 OK（成功時） |

### 出力先

- HTTPレスポンス

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ set_agent_bot アクションが呼び出される

2. パラメータ検証
   └─ agent_botパラメータの存在チェック

3. 条件分岐
   ├─ agent_botが指定された場合
   │      └─ ボットの割り当て処理
   └─ agent_botがnull/未指定の場合
          └─ 既存の割り当て解除処理

4. ボット割り当て処理
   └─ 既存のagent_bot_inboxがあれば更新、なければ新規作成

5. 割り当て解除処理
   └─ 既存のagent_bot_inboxを削除

6. レスポンス返却
   └─ HTTP 200 OK
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B[インボックス取得]
    B --> C[ボット取得 fetch_agent_bot]
    C --> D{agent_botが指定されているか}

    D -->|Yes| E{既存のagent_bot_inboxがあるか}
    E -->|Yes| F[既存レコードを更新]
    E -->|No| G[新規agent_bot_inbox作成]

    D -->|No| H{既存のagent_bot_inboxがあるか}
    H -->|Yes| I[agent_bot_inbox削除]
    H -->|No| J[何もしない]

    F --> K[保存]
    G --> K

    K --> L[head :ok]
    I --> L
    J --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-182-01 | 単一ボット制約 | 1つのインボックスには1つのボットのみ割り当て可能 | 常時 |
| BR-182-02 | ボット更新 | 既存の割り当てがある場合は更新として処理 | agent_bot指定時 |
| BR-182-03 | 割り当て解除 | agent_botがnull/未指定の場合は既存割り当てを解除 | agent_bot未指定時 |
| BR-182-04 | アクセス可能ボット | アカウントに属するボット、またはシステムボットのみ割り当て可能 | 常時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ボット割り当て | agent_bot_inboxes | INSERT/UPDATE | 新規作成または更新 |
| 割り当て解除 | agent_bot_inboxes | DELETE | 既存レコードの削除 |
| インボックス取得 | inboxes | SELECT | 対象インボックスの取得 |
| ボット取得 | agent_bots | SELECT | 割り当てるボットの取得 |

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

#### agent_bot_inboxes

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | inbox_id | 指定されたインボックスID | |
| INSERT | agent_bot_id | 指定されたボットID | |
| INSERT | account_id | インボックスのaccount_id | ensure_account_idで自動設定 |
| INSERT | status | active（デフォルト） | |
| UPDATE | agent_bot_id | 新しいボットID | 既存レコードを更新 |
| DELETE | - | inbox_id で検索して削除 | |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 404 | Not Found | 指定されたインボックスが存在しない | エラーレスポンス返却 |
| 404 | Not Found | 指定されたボットが存在しない | エラーレスポンス返却 |
| 403 | Forbidden | 権限不足 | エラーレスポンス返却 |
| 422 | Unprocessable Entity | バリデーションエラー | エラーレスポンス返却 |

### リトライ仕様

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

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

暗黙的なトランザクションが適用される。agent_bot_inbox.save! または destroy! の失敗時はロールバックされる。

## パフォーマンス要件

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

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

- インボックス設定変更権限の確認（check_authorization）
- アカウント境界の厳守（Current.accountによるスコープ制限）

## 備考

- 割り当てられたボットのステータスはデフォルトでactive
- ステータスの変更（active/inactive）は別途管理

---

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

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

### 推奨読解順序

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

まず、ボットとインボックスの関連付けを管理するモデルを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | agent_bot_inbox.rb | `app/models/agent_bot_inbox.rb` | ボット-インボックス関連付けの構造 |
| 1-2 | agent_bot.rb | `app/models/agent_bot.rb` | ボットモデルのリレーション |

**読解のコツ**:
- **14-22行目**（agent_bot_inbox.rb）: バリデーションとリレーション定義
- **24-28行目**: ensure_account_idコールバック - account_idの自動設定ロジック

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

ボット割り当てAPIの実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | inboxes_controller.rb | `app/controllers/api/v1/accounts/inboxes_controller.rb` | set_agent_botアクションの実装 |

**主要処理フロー**:
- **4行目**: before_action :fetch_agent_bot - ボット取得のコールバック設定
- **53-55行目**: agent_botアクション - 現在の割り当てボット取得
- **57-66行目**: set_agent_botアクション - ボット割り当て/解除の実装
- **97-99行目**: fetch_agent_botメソッド - パラメータからボットを取得

#### Step 3: 認可処理を理解する

権限チェックの仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | inboxes_controller.rb | `app/controllers/api/v1/accounts/inboxes_controller.rb` | check_authorizationの呼び出し |

**主要処理フロー**:
- **7行目**: before_action :check_authorization - 権限チェック

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

```
POST /api/v1/accounts/:account_id/inboxes/:id/set_agent_bot
    │
    ├─ before_action :fetch_inbox
    │      └─ Current.account.inboxes.find(params[:id])
    │
    ├─ before_action :fetch_agent_bot
    │      └─ AgentBot.find(params[:agent_bot]) if params[:agent_bot]
    │
    ├─ before_action :check_authorization
    │
    └─ set_agent_bot アクション
           │
           ├─ @agent_bot が存在する場合
           │      ├─ @inbox.agent_bot_inbox || AgentBotInbox.new
           │      ├─ agent_bot_inbox.agent_bot = @agent_bot
           │      └─ agent_bot_inbox.save!
           │
           └─ @agent_bot が存在しない場合
                  └─ @inbox.agent_bot_inbox.destroy! (存在する場合)
```

### データフロー図

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

APIリクエスト ─────────▶ InboxesController ──────────────▶ HTTP 200 OK
(agent_bot ID)               │
                             ▼
                     fetch_agent_bot
                     (AgentBot取得)
                             │
                             ▼
                     set_agent_bot
                             │
                    ┌────────┴────────┐
                    ▼                 ▼
            ボット割り当て      割り当て解除
            (save!)            (destroy!)
                    │                 │
                    ▼                 ▼
              agent_bot_inboxes テーブル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| inboxes_controller.rb | `app/controllers/api/v1/accounts/inboxes_controller.rb` | コントローラー | set_agent_bot、agent_botアクション |
| agent_bot_inbox.rb | `app/models/agent_bot_inbox.rb` | モデル | ボット-インボックス関連付け |
| agent_bot.rb | `app/models/agent_bot.rb` | モデル | ボットモデル |
| inbox.rb | `app/models/inbox.rb` | モデル | インボックスモデル（agent_bot_inboxリレーション） |
