# 画面設計書 82-エージェント割り当て作成

## 概要

本ドキュメントは、Chatwootのエージェント割り当てポリシー作成画面の設計を記述したものです。この画面では、新しいエージェント割り当てポリシーを作成します。

### 本画面の処理概要

**業務上の目的・背景**：顧客サポート業務において、会話をエージェントに自動的に割り当てるためのルールを定義します。ポリシーでは割り当て順序（ラウンドロビン/バランス）、会話の優先度、公平分配の設定などを指定できます。これにより、チームの業務負荷を均等化し、対応品質を向上させることができます。

**画面へのアクセス方法**：エージェント割り当て一覧画面から「ポリシーを作成」ボタンをクリックしてアクセスします。URLパスは `/app/accounts/:accountId/settings/assignment-policy/assignment/create` です。

**主要な操作・処理内容**：
1. ポリシー名の入力（必須）
2. ポリシー説明の入力（任意）
3. ポリシーの有効/無効状態の設定
4. 割り当て順序の選択（ラウンドロビン/バランス）
5. 会話優先度の選択（作成順/待機時間順）
6. 公平分配制限値の設定
7. 公平分配ウィンドウ時間の設定
8. フォーム送信によるポリシー作成

**画面遷移**：
- 遷移元：エージェント割り当て一覧画面
- 遷移先：作成成功時はエージェント割り当て編集画面に自動遷移（インボックス設定のため）

**権限による表示制御**：管理者（administrator）ロールのユーザーのみがアクセス可能です。ASSIGNMENT_V2フィーチャーフラグが有効な場合にのみ表示されます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 24 | 割り当てポリシー | 主機能 | 新しい割り当てルールの作成 |

## 画面種別

登録

## URL/ルーティング

- **パス**: `/app/accounts/:accountId/settings/assignment-policy/assignment/create`
- **ルート名**: `agent_assignment_policy_create`

## 入出力項目

### 入力項目

| 項目名 | データ型 | 必須 | 初期値 | バリデーション | 説明 |
|--------|----------|------|--------|----------------|------|
| name | String | 必須 | 空文字 | 空でないこと | ポリシー名 |
| description | String | 任意 | 空文字 | なし | ポリシーの説明 |
| enabled | Boolean | 必須 | false | なし | 有効/無効状態 |
| assignmentOrder | String | 必須 | round_robin | round_robin/balanced | 割り当て順序 |
| conversationPriority | String | 必須 | earliest_created | earliest_created/longest_waiting | 会話優先度 |
| fairDistributionLimit | Number | 必須 | 100 | 正の整数 | 公平分配制限値 |
| fairDistributionWindow | Number | 必須 | 3600 | 正の整数（秒） | 公平分配ウィンドウ |

## 表示項目

### 基本情報セクション（BaseInfo）

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| ポリシー名入力 | テキストフィールド | 必須入力、プレースホルダー付き |
| 説明入力 | テキストエリア | 任意入力、プレースホルダー付き |
| ステータス | トグルスイッチ | 有効/無効の切り替え |

### 割り当て順序セクション

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| ラウンドロビン | ラジオカード | 順番に割り当て |
| バランス | ラジオカード | 負荷均等に割り当て（Enterprise版のみ） |

### 会話優先度セクション

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| 作成順 | ラジオカード | 作成日時が早い順 |
| 待機時間順 | ラジオカード | 待機時間が長い順 |

### 公平分配セクション（FairDistribution）

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| 制限値 | 数値入力 | 上限件数 |
| ウィンドウ | 数値入力 | 時間範囲（秒） |

## イベント仕様

### 1-フォーム送信

フォームのsubmitイベント時、以下の処理を実行します：
1. バリデーション確認（nameが空でないか）
2. Vuex Action `assignmentPolicies/create` を実行
3. 成功時：成功メッセージを表示し、作成されたポリシーの編集画面に遷移
4. 失敗時：エラーメッセージを表示

### 2-パンくずリストクリック

パンくずリストの「エージェント割り当て」クリック時、エージェント割り当て一覧画面（`agent_assignment_policy_index`）に遷移します。

### 3-割り当て順序選択

ラジオカードの選択時、state.assignmentOrderを更新します。

### 4-会話優先度選択

ラジオカードの選択時、state.conversationPriorityを更新します。

### 5-バリデーション状態変更

BaseInfoコンポーネントからのvalidationChangeイベント時、送信ボタンの有効/無効状態を更新します。

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| フォーム送信 | assignment_policies | INSERT | 新規ポリシーの作成 |

### テーブル別更新項目詳細

#### assignment_policies

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name | フォーム入力値 | 必須 |
| INSERT | description | フォーム入力値 | 任意 |
| INSERT | enabled | フォーム入力値（boolean） | デフォルトfalse |
| INSERT | assignment_order | フォーム入力値 | round_robin or balanced |
| INSERT | conversation_priority | フォーム入力値 | earliest_created or longest_waiting |
| INSERT | fair_distribution_limit | フォーム入力値 | デフォルト100 |
| INSERT | fair_distribution_window | フォーム入力値 | デフォルト3600 |
| INSERT | account_id | 現在のアカウントID | 自動設定 |

## メッセージ仕様

| メッセージID | 種別 | 表示条件 | メッセージ内容 |
|-------------|------|----------|--------------|
| CREATE.API.SUCCESS_MESSAGE | 成功 | ポリシー作成成功時 | ポリシーが正常に作成されました |
| CREATE.API.ERROR_MESSAGE | エラー | ポリシー作成失敗時 | ポリシーの作成に失敗しました |

## 例外処理

| 例外条件 | 処理内容 |
|----------|----------|
| 名前が空 | 送信ボタンを無効化、バリデーションエラー表示 |
| API呼び出し失敗 | エラーメッセージをアラート表示 |
| 権限不足 | 画面アクセス不可（ルートガードで制御） |
| フィーチャーフラグ無効 | 画面アクセス不可（ルートガードで制御） |

## 備考

- 「バランス」割り当て順序はEnterprise版でのみ利用可能です
- 作成成功後は自動的に編集画面に遷移し、インボックスの紐づけが可能になります
- 公平分配の設定により、特定の時間内での割り当て上限を制御できます

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | constants.js | `app/javascript/dashboard/routes/dashboard/settings/assignmentPolicy/constants.js` | ROUND_ROBIN, BALANCED, EARLIEST_CREATED等の定数とデフォルト値 |
| 1-2 | assignmentPolicies.js | `app/javascript/dashboard/store/modules/assignmentPolicies.js` | createアクションの実装（行64-78） |

**読解のコツ**: フォームの初期値は定数ファイルで定義されており、constants.jsを先に読むと理解しやすい

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AgentAssignmentCreatePage.vue | `app/javascript/dashboard/routes/dashboard/settings/assignmentPolicy/pages/AgentAssignmentCreatePage.vue` | handleSubmit関数、formRefの使用方法 |

**主要処理フロー**:
1. **行16-17**: formRefとuiFlagsの取得
2. **行35-54**: handleSubmit関数でcreateアクションをディスパッチ
3. **行43-48**: 成功時に編集画面へルーター遷移

#### Step 3: フォームコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AgentAssignmentPolicyForm.vue | `app/javascript/dashboard/routes/dashboard/settings/assignmentPolicy/pages/components/AgentAssignmentPolicyForm.vue` | フォームのstate構造、バリデーション、各セクションの実装 |
| 3-2 | BaseInfo.vue | `app/javascript/dashboard/components-next/AssignmentPolicy/components/BaseInfo.vue` | 名前・説明・ステータスの入力コンポーネント |
| 3-3 | RadioCard.vue | `app/javascript/dashboard/components-next/AssignmentPolicy/components/RadioCard.vue` | ラジオボタン形式のカード選択UI |
| 3-4 | FairDistribution.vue | `app/javascript/dashboard/components-next/AssignmentPolicy/components/FairDistribution.vue` | 公平分配設定のUI |

**主要処理フロー（AgentAssignmentPolicyForm.vue）**:
- **行72-80**: stateのリアクティブ定義
- **行86-106**: 割り当て順序と優先度のオプション生成
- **行142-144**: handleSubmitでemit('submit', state)

#### Step 4: API層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | assignmentPolicies.js（API） | `app/javascript/dashboard/api/assignmentPolicies.js` | ApiClientの継承とエンドポイント |
| 4-2 | assignment_policies_controller.rb | `app/controllers/api/v1/accounts/assignment_policies_controller.rb` | createアクションのpermitted_params |

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

```
AgentAssignmentCreatePage.vue (エントリーポイント)
    │
    └─ AgentAssignmentPolicyForm.vue
           │
           ├─ BaseInfo.vue
           │      └─ @validation-change → validationState更新
           │
           ├─ RadioCard.vue (割り当て順序)
           │      └─ @select → state.assignmentOrder更新
           │
           ├─ RadioCard.vue (会話優先度)
           │      └─ @select → state.conversationPriority更新
           │
           ├─ FairDistribution.vue
           │      └─ v-model → state.fairDistribution*更新
           │
           └─ @submit → handleSubmit
                  └─ store.dispatch('assignmentPolicies/create')
                          │
                          ├─ AssignmentPoliciesAPI.create()
                          │      └─ POST /api/v1/accounts/:id/assignment_policies
                          │
                          └─ 成功時: router.push → agent_assignment_policy_edit
```

### データフロー図

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

フォーム入力 ─────────▶ state（reactive） ─────────────▶
                              │
                              ▼
                      @submit イベント
                              │
                              ▼
                      handleSubmit
                              │
                              ▼
                      assignmentPolicies/create
                              │
                              ▼
                      POST /assignment_policies ──────▶ 新規ポリシーレコード
                              │
                              ▼
                      Vuex State更新
                              │
                              ▼
                      router.push（編集画面へ遷移）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AgentAssignmentCreatePage.vue | `app/javascript/dashboard/routes/dashboard/settings/assignmentPolicy/pages/AgentAssignmentCreatePage.vue` | ソース | 作成ページコンポーネント |
| AgentAssignmentPolicyForm.vue | `app/javascript/dashboard/routes/dashboard/settings/assignmentPolicy/pages/components/AgentAssignmentPolicyForm.vue` | ソース | フォームコンポーネント |
| BaseInfo.vue | `app/javascript/dashboard/components-next/AssignmentPolicy/components/BaseInfo.vue` | ソース | 基本情報入力 |
| RadioCard.vue | `app/javascript/dashboard/components-next/AssignmentPolicy/components/RadioCard.vue` | ソース | ラジオカード選択 |
| FairDistribution.vue | `app/javascript/dashboard/components-next/AssignmentPolicy/components/FairDistribution.vue` | ソース | 公平分配設定 |
| assignmentPolicies.js | `app/javascript/dashboard/store/modules/assignmentPolicies.js` | ソース | Vuexストア |
| assignmentPolicies.js | `app/javascript/dashboard/api/assignmentPolicies.js` | ソース | APIクライアント |
| constants.js | `app/javascript/dashboard/routes/dashboard/settings/assignmentPolicy/constants.js` | ソース | 定数定義 |
| assignment_policies_controller.rb | `app/controllers/api/v1/accounts/assignment_policies_controller.rb` | ソース | バックエンドコントローラー |
| SettingsLayout.vue | `app/javascript/dashboard/routes/dashboard/settings/SettingsLayout.vue` | ソース | 設定画面共通レイアウト |
