# 機能設計書 95-バルクアクション

## 概要

本ドキュメントは、Chatwoot の Captain AI 機能におけるバルクアクション（一括処理）機能の設計を記載する。

### 本機能の処理概要

バルクアクション機能は、AIアシスタント関連のデータ（現時点ではAssistantResponse）に対して一括操作を行う機能である。複数のFAQレスポンスを一括で承認したり、一括削除したりすることができる。

**業務上の目的・背景**：ドキュメントからのFAQ自動生成により大量のレスポンスが作成されるが、これらを1件ずつ確認・承認するのは非効率である。バルクアクションにより、保留中のFAQを一括承認したり、不要なFAQを一括削除したりすることで、管理効率を大幅に向上させることができる。

**機能の利用シーン**：
- ドキュメントクロール後に生成された多数のFAQを一括承認する
- 不要または不正確なFAQを一括削除する
- 特定のドキュメントに関連するFAQをまとめて処理する

**主要な処理内容**：
1. 指定されたIDリストに基づくAssistantResponseの取得
2. ステータス更新による一括承認（pending → approved）
3. レコードの一括削除

**関連システム・外部連携**：特になし（内部データ操作のみ）

**権限による制御**：Captain::Assistant ポリシーに基づく認可。アシスタント管理権限を持つユーザーが操作可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 104 | FAQ一覧画面 | 主画面 | FAQの一括承認・削除 |
| 105 | 保留中FAQ一覧 | 主画面 | 保留中FAQの一括承認 |

## 機能種別

バルク操作 / データ一括更新

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| type | String | Yes | 対象モデル種別 | AssistantResponse のみ許可 |
| ids | Array[Integer] | Yes | 処理対象のIDリスト | 必須、配列 |
| fields | Object | Yes | 操作内容 | status: approve または delete |

### fieldsパラメータ詳細

| フィールド名 | 型 | 許可値 | 説明 |
|-------------|-----|--------|------|
| status | String | approve / delete | 一括承認または一括削除 |

### 入力データソース

画面入力（API経由）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| (配列) | Array[AssistantResponse] | 処理後のレスポンス一覧（承認時）|
| (空配列) | Array | 削除時は空配列 |

### 出力先

API レスポンス（JSON形式）

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ BulkActionsControllerがリクエストを受信
2. パラメータ検証
   ├─ type, ids, fieldsの存在確認
   └─ typeがMODEL_TYPEに含まれるか確認
3. 認可チェック
   └─ Captain::Assistantポリシーによる権限確認
4. バルク操作実行
   ├─ approve: pendingレコードをapprovedに更新
   └─ delete: レコードを一括削除
5. レスポンス返却
   └─ 処理結果のJSON返却
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B{パラメータ検証}
    B -->|type/ids/fields不足| C[422エラー]
    B -->|OK| D{type検証}
    D -->|無効なtype| E[422エラー]
    D -->|AssistantResponse| F{認可チェック}
    F -->|失敗| G[403エラー]
    F -->|成功| H{fields.status判定}
    H -->|approve| I[pendingレコード取得]
    H -->|delete| J[対象レコード取得]
    I --> K[ステータス更新: approved]
    J --> L[レコード一括削除]
    K --> M[更新後レスポンス返却]
    L --> N[空配列返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-95-01 | モデル種別制限 | typeはAssistantResponseのみ許可 | 全リクエスト |
| BR-95-02 | 必須パラメータ | type, ids, fieldsすべて必須 | 全リクエスト |
| BR-95-03 | 承認対象制限 | approveはpendingステータスのレコードのみ対象 | approve操作時 |
| BR-95-04 | アカウント制限 | Current.accountに属するレコードのみ操作可能 | 全操作 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| approve | captain_assistant_responses | UPDATE | status を approved に更新 |
| delete | captain_assistant_responses | DELETE | レコード一括削除 |

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

#### captain_assistant_responses

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | id IN params[:ids] AND account_id = current_account.id | 対象レコード取得 |
| UPDATE (approve) | status | 'approved' | pending レコードのみ |
| DELETE | - | id IN params[:ids] | 物理削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 403 | Forbidden | 権限不足 | 適切な権限を付与 |
| 422 | Unprocessable Entity | type, ids, fieldsが不足 | 必須パラメータを指定 |
| 422 | Unprocessable Entity | typeがAssistantResponse以外 | 正しいtypeを指定 |

### リトライ仕様

特になし。エラー時はクライアント側で再試行。

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

update_allおよびdestroy_allは単一SQLで実行されるため、暗黙のトランザクション内で処理される。

## パフォーマンス要件

- update_allによる単一SQLでの一括更新
- destroy_allによる単一SQLでの一括削除
- IDリストの件数に応じた線形時間

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

- Captain::Assistant ポリシーによるアクセス制御
- account_idによる所有権チェック
- 他アカウントのレコードは操作不可

## 備考

Enterprise Edition機能として提供される。現時点ではAssistantResponseのみ対応しているが、MODEL_TYPE配列を拡張することで他のモデルにも対応可能な設計となっている。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | assistant_response.rb | `enterprise/app/models/captain/assistant_response.rb` | AssistantResponseのスキーマ、statusのenum定義 |

**読解のコツ**:
- **45行目**: enum status: { pending: 0, approved: 1 }

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | bulk_actions_controller.rb | `enterprise/app/controllers/api/v1/accounts/captain/bulk_actions_controller.rb` | APIエンドポイントの実装 |

**主要処理フロー**:
1. **3行目**: before_action で Captain::Assistant ポリシーによる認可チェック
2. **4-5行目**: before_action でパラメータ検証
3. **7行目**: MODEL_TYPE定義（'AssistantResponse'のみ）
4. **9-11行目**: create アクション - process_bulk_action呼び出し
5. **15-19行目**: validate_params - 必須パラメータチェック
6. **21-25行目**: type_matches? - モデル種別チェック
7. **27-32行目**: process_bulk_action - typeに応じた処理分岐
8. **34-46行目**: handle_assistant_responses - 実際のバルク処理

#### Step 3: ビュー（JSON出力）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | create.json.jbuilder | `enterprise/app/views/api/v1/accounts/captain/bulk_actions/create.json.jbuilder` | JSON出力フォーマット |

**主要処理フロー**:
- **1-3行目**: @responsesをpartialでJSON配列として出力

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

```
Api::V1::Accounts::Captain::BulkActionsController
    │
    ├─ before_action :current_account
    │
    ├─ before_action -> { check_authorization(Captain::Assistant) }
    │
    ├─ before_action :validate_params
    │      └─ type, ids, fieldsの存在確認
    │
    ├─ before_action :type_matches?
    │      └─ MODEL_TYPE.include?(params[:type])
    │
    └─ create
           └─ process_bulk_action
                  │
                  └─ handle_assistant_responses
                         │
                         ├─ Current.account.captain_assistant_responses.where(id: params[:ids])
                         │
                         ├─ case params[:fields][:status]
                         │      │
                         │      ├─ 'approve'
                         │      │      └─ responses.pending.update(status: 'approved')
                         │      │
                         │      └─ 'delete'
                         │             └─ responses.destroy_all
                         │
                         └─ return responses / []
```

### データフロー図

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

type: 'AssistantResponse' ──┐
                            ├──▶ BulkActionsController#create
ids: [1, 2, 3, ...] ────────┤               │
                            │               ▼
fields: {status: 'approve'} ┘        validate_params
                                           │
                                           ▼
                                     type_matches?
                                           │
                                           ▼
                                   process_bulk_action
                                           │
                            ┌──────────────┼──────────────┐
                            ▼              ▼              ▼
                      'approve'        'delete'        (other)
                            │              │              │
                            ▼              ▼              ▼
                      responses        responses       nil
                       .pending        .destroy_all
                       .update
                            │              │
                            ▼              ▼
                      [AssistantResponse]   []
                         (JSON Array)    (Empty Array)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| bulk_actions_controller.rb | `enterprise/app/controllers/api/v1/accounts/captain/bulk_actions_controller.rb` | コントローラー | APIエンドポイント |
| assistant_response.rb | `enterprise/app/models/captain/assistant_response.rb` | モデル | データ定義 |
| create.json.jbuilder | `enterprise/app/views/api/v1/accounts/captain/bulk_actions/create.json.jbuilder` | ビュー | JSON出力 |
| _assistant_response.json.jbuilder | `enterprise/app/views/api/v1/models/captain/_assistant_response.json.jbuilder` | ビュー | AssistantResponse部分テンプレート |
