# 画面設計書 63-マクロ新規作成画面

## 概要

本ドキュメントは、Chatwootのマクロ新規作成画面の設計仕様を記述したものです。

### 本画面の処理概要

本画面は、新しいマクロを作成するための画面です。マクロは複数のアクションをまとめて定義し、会話に対して一括で実行できるショートカット機能です。視覚的なノードエディタを使用して、アクションの追加・編集・削除を行います。

**業務上の目的・背景**：エージェントが日常的に行う一連の操作（チーム割り当て、ラベル付け、メッセージ送信など）をマクロとして保存することで、作業の効率化と標準化を実現します。本画面では、マクロ名、公開範囲、実行するアクションのリストを定義し、再利用可能なマクロを作成します。

**画面へのアクセス方法**：マクロ一覧画面から「+ Add Macro」ボタンをクリックしてアクセスします。URLパスは `/app/accounts/:accountId/settings/macros/new` です。

**主要な操作・処理内容**：
1. マクロ名の入力
2. 公開範囲の選択（個人/グローバル）
3. アクションノードの追加
4. アクションタイプの選択とパラメータ設定
5. アクションノードの削除・リセット
6. マクロの保存

**画面遷移**：
- 遷移元：マクロ一覧画面
- 遷移先：マクロ一覧画面（保存成功時）

**権限による表示制御**：全ロール（管理者・エージェント）がアクセス可能です。ただし、エージェントは公開範囲を「個人」のみ選択可能です。管理者は「グローバル」も選択できます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 75 | マクロ（ショートカット） | 主機能 | 新しいマクロの作成 |
| 77 | マクロのグローバル化 | 補助機能 | マクロの共有設定 |

## 画面種別

登録

## URL/ルーティング

| 項目 | 値 |
|------|-----|
| パス | `/app/accounts/:accountId/settings/macros/new` |
| ルート名 | `macros_new` |
| コンポーネント | `app/javascript/dashboard/routes/dashboard/settings/macros/MacroEditor.vue` |
| 権限 | `ROLES`, `CONVERSATION_PERMISSIONS` |
| フィーチャーフラグ | `MACROS` |

## 入出力項目

### 入力項目

| 項目名 | 項目ID | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| マクロ名 | name | string | 必須 | マクロの名称 |
| 公開範囲 | visibility | enum | 必須 | `personal`（個人）または `global`（全体公開） |
| アクション配列 | actions | array | 必須 | 実行するアクションのリスト |

### アクション項目

| アクション名 | キー | 入力タイプ | 説明 |
|-------------|------|-----------|------|
| チーム割り当て | assign_team | search_select | チームを選択 |
| エージェント割り当て | assign_agent | search_select | エージェントを選択 |
| ラベル追加 | add_label | multi_select | 追加するラベルを選択 |
| ラベル削除 | remove_label | multi_select | 削除するラベルを選択 |
| チーム割り当て解除 | remove_assigned_team | null | パラメータ不要 |
| メール送信 | send_email_transcript | email | 送信先メールアドレス |
| 会話ミュート | mute_conversation | null | パラメータ不要 |
| 会話スヌーズ | snooze_conversation | null | パラメータ不要 |
| 会話解決 | resolve_conversation | null | パラメータ不要 |
| 添付ファイル送信 | send_attachment | attachment | ファイルをアップロード |
| メッセージ送信 | send_message | textarea | 送信するメッセージ |
| プライベートノート追加 | add_private_note | textarea | ノートの内容 |
| 優先度変更 | change_priority | search_select | 優先度を選択 |
| Webhookイベント送信 | send_webhook_event | url | WebhookのURL |

## 表示項目

### 左側：アクションノードエディタ

| 項目名 | 説明 |
|--------|------|
| アクションノード | 各アクションを視覚的なノードとして表示 |
| アクションタイプ | ドロップダウンでアクションを選択 |
| アクションパラメータ | アクションに応じた入力フィールド |
| 追加ボタン | 新しいアクションノードを追加 |
| 削除ボタン | アクションノードを削除 |

### 右側：プロパティパネル

| 項目名 | 説明 |
|--------|------|
| マクロ名入力 | マクロの名称を入力 |
| 公開範囲選択 | 個人/グローバルを選択 |
| 保存ボタン | マクロを保存 |

## イベント仕様

### 1-アクションノード追加

「+」ボタンをクリックすると、新しいアクションノードが追加されます。

**処理フロー**：
1. `appendNode()` が呼び出される
2. `macro.actions` 配列に新しいアクション `{ action_name: 'assign_team', action_params: [] }` が追加される

### 2-アクションノード削除

各ノードの削除ボタンをクリックすると、そのノードが削除されます。

**処理フロー**：
1. `deleteNode(index)` が呼び出される
2. `errors` から該当インデックスのエラーを削除
3. `macro.actions.splice(index, 1)` でアクションを削除

### 3-アクションリセット

各ノードのリセットボタンをクリックすると、そのノードのパラメータがリセットされます。

**処理フロー**：
1. `resetNode(index)` が呼び出される
2. `errors` から該当インデックスのエラーを削除
3. `macro.actions[index].action_params = []` でパラメータをクリア

### 4-マクロ保存

プロパティパネルの保存ボタンをクリックすると、マクロが保存されます。

**処理フロー**：
1. `MacroForm.submit()` が呼び出される
2. `validateActions(macro.actions)` でアクションのバリデーション
3. エラーがあれば処理中断
4. `v$.$touch()` でフォームバリデーション
5. バリデーション失敗なら処理中断
6. `$emit('submit', macro)` でマクロデータを親に渡す
7. `MacroEditor.saveMacro(macroData)` が呼び出される
8. `actionQueryGenerator(serializedMacro.actions)` でアクションをシリアライズ
9. `store.dispatch('macros/create', serializedMacro)` でAPIを呼び出し
10. 成功時：成功メッセージを表示し、マクロ一覧画面に遷移
11. 失敗時：エラーメッセージを表示

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| マクロ作成 | macros | INSERT | 新しいマクロを作成 |
| ファイル添付 | active_storage_attachments | INSERT | 添付ファイルがある場合 |

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

#### macros

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | id | シーケンス自動採番 | 主キー |
| INSERT | name | フォーム入力値 | マクロ名 |
| INSERT | visibility | フォーム入力値（0 or 1） | 公開範囲 |
| INSERT | actions | JSON形式のフォーム入力値 | アクション配列 |
| INSERT | account_id | Current.account.id | アカウントID |
| INSERT | created_by_id | current_user.id | 作成者ID |
| INSERT | updated_by_id | current_user.id | 更新者ID |
| INSERT | created_at | 現在日時 | 作成日時 |
| INSERT | updated_at | 現在日時 | 更新日時 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示タイミング |
|-------------|------|---------------|---------------|
| MACROS.ADD.API.SUCCESS_MESSAGE | 成功 | マクロ作成成功 | 作成成功時 |
| MACROS.ERROR | エラー | マクロ保存エラー | 作成失敗時 |
| MACROS.EDITOR.LOADING | 情報 | 読み込み中 | データ取得中 |

## 例外処理

| 例外状況 | 処理内容 |
|---------|---------|
| バリデーションエラー | エラー表示し、保存処理を中断 |
| API呼び出し失敗 | エラーメッセージをアラート表示 |
| アクションパラメータ不足 | アクションごとにエラーを表示 |

## 備考

- 新規作成時、初期アクションとして `assign_team` が1つ追加された状態で開始
- 初期公開範囲は `global`（ただしエージェントの場合は強制的に `personal` に設定）
- エージェントロールのユーザーは個人マクロのみ作成可能（`set_visibility` メソッドで制御）
- アクションのシリアライズは `actionQueryGenerator` ヘルパーで行う
- ファイル添付時は `AttachmentConcern` を使用してBlobを処理

---

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

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

### 推奨読解順序

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

マクロとアクションタイプの構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | macro.rb | `app/models/macro.rb` | モデル定義、ACTIONS_ATTRS定数を確認 |
| 1-2 | constants.js | `app/javascript/dashboard/routes/dashboard/settings/macros/constants.js` | MACRO_ACTION_TYPESの定義を確認 |

**読解のコツ**: `MACRO_ACTION_TYPES` で各アクションの `key`、`label`、`inputType` を把握することが重要です。`inputType` によって入力UIが決まります。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | MacroEditor.vue | `app/javascript/dashboard/routes/dashboard/settings/macros/MacroEditor.vue` | 画面の構成、モード判定、データ初期化を確認 |

**主要処理フロー**:
1. **99-110行目**: `watch` でルートを監視し、新規/編集を判定
2. **85-97行目**: `initNewMacro()` で初期データを設定
3. **112-127行目**: `saveMacro()` で保存処理

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | MacroForm.vue | `app/javascript/dashboard/routes/dashboard/settings/macros/MacroForm.vue` | フォームの構成、バリデーション、アクション操作を確認 |

**主要処理フロー**:
- **75-80行目**: `appendNode()` でアクション追加
- **81-86行目**: `deleteNode()` でアクション削除
- **87-95行目**: `submit()` でバリデーションと送信

#### Step 4: Vuex Store層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | macros.js | `app/javascript/dashboard/store/modules/macros.js` | create アクションを確認 |

**主要処理フロー**:
- **53-62行目**: `create` アクションでAPI呼び出し

#### Step 5: バックエンド層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | macros_controller.rb | `app/controllers/api/v1/accounts/macros_controller.rb` | create アクション、set_visibility を確認 |

**主要処理フロー**:
- **15-27行目**: `create` アクションで添付ファイル対応の作成処理
- **20行目**: `set_visibility` でロールに応じた公開範囲設定

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

```
MacroEditor.vue (エントリーポイント)
    │
    ├─ watch(route)
    │      └─ initNewMacro()
    │             └─ 初期データ設定
    │
    └─ MacroForm.vue
           │
           ├─ MacroNodes.vue
           │      ├─ appendNode()
           │      ├─ deleteNode()
           │      └─ resetNode()
           │
           ├─ MacroProperties.vue
           │      └─ submit()
           │
           └─ saveMacro()
                  │
                  ├─ actionQueryGenerator()
                  │
                  └─ store.dispatch('macros/create')
                         └─ MacrosAPI.create()
                                └─ POST /api/v1/accounts/:account_id/macros
                                       └─ macros_controller#create
```

### データフロー図

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

マクロ名 ─────────────▶ MacroProperties ─────────▶ macro.name
公開範囲 ─────────────▶ MacroProperties ─────────▶ macro.visibility
アクション追加 ────────▶ MacroNodes ──────────────▶ macro.actions[]
                           │
                           ▼
                      MacroForm
                           │
                           ▼
                      MacroEditor
                           │
                           ▼
                    actionQueryGenerator
                           │
                           ▼
                      Vuex Store
                           │
                           ▼
                  Rails Controller
                           │
                           ▼
                    PostgreSQL
                      (macros)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| MacroEditor.vue | `app/javascript/dashboard/routes/dashboard/settings/macros/MacroEditor.vue` | ソース | エディタコンテナ |
| MacroForm.vue | `app/javascript/dashboard/routes/dashboard/settings/macros/MacroForm.vue` | ソース | フォームコンポーネント |
| MacroNodes.vue | `app/javascript/dashboard/routes/dashboard/settings/macros/MacroNodes.vue` | ソース | ノードエディタ |
| MacroProperties.vue | `app/javascript/dashboard/routes/dashboard/settings/macros/MacroProperties.vue` | ソース | プロパティパネル |
| constants.js | `app/javascript/dashboard/routes/dashboard/settings/macros/constants.js` | ソース | アクションタイプ定義 |
| macroHelper.js | `app/javascript/dashboard/routes/dashboard/settings/macros/macroHelper.js` | ソース | ヘルパー関数 |
| actionQueryGenerator.js | `app/javascript/dashboard/helper/actionQueryGenerator.js` | ソース | アクションシリアライザ |
| macros.js | `app/javascript/dashboard/store/modules/macros.js` | ソース | Vuexストアモジュール |
| macros.js | `app/javascript/dashboard/api/macros.js` | ソース | APIクライアント |
| macros_controller.rb | `app/controllers/api/v1/accounts/macros_controller.rb` | ソース | Railsコントローラ |
| macro.rb | `app/models/macro.rb` | ソース | モデル定義 |
