# 画面設計書 67-Webhook設定画面

## 概要

本ドキュメントは、ChatwootのWebhook設定画面の設計仕様を記述したものです。

### 本画面の処理概要

本画面は、外部システムとの連携のためのWebhookを設定・管理する画面です。Webhookを使用することで、Chatwoot内で発生したイベント（会話の作成、メッセージの送信など）を外部のHTTPエンドポイントに通知できます。

**業務上の目的・背景**：カスタマーサポートシステムと社内の他システム（CRM、チケット管理、通知システムなど）を連携させる場合、Webhookによるリアルタイムなイベント通知が不可欠です。本画面では、Webhookエンドポイントの登録、イベント種別の選択、Webhookの管理を行います。

**画面へのアクセス方法**：連携アプリ一覧画面から「Webhook」を選択、または直接 `/app/accounts/:accountId/settings/integrations/webhook` にアクセスします。

**主要な操作・処理内容**：
1. Webhook一覧の表示（エンドポイントURL、購読イベント）
2. 新規Webhookの作成
3. 既存Webhookの編集
4. Webhookの削除

**画面遷移**：
- 遷移元：連携アプリ一覧画面
- 遷移先：なし（モーダル内で操作完結）

**権限による表示制御**：管理者（administrator）権限を持つユーザーのみがアクセス可能です。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 141 | Webhooks | 主機能 | Webhookの設定 |
| 142 | Webhookイベント | 補助機能 | Webhookイベントの設定 |

## 画面種別

一覧・登録・編集

## URL/ルーティング

| 項目 | 値 |
|------|-----|
| パス | `/app/accounts/:accountId/settings/integrations/webhook` |
| ルート名 | `settings_integrations_webhook` |
| コンポーネント | `app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/Index.vue` |
| 権限 | `administrator` |
| フィーチャーフラグ | `INTEGRATIONS` |

## 入出力項目

### 入力項目（作成/編集モーダル）

| 項目名 | 項目ID | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| Webhook名 | name | string | 任意 | Webhookの名称 |
| エンドポイントURL | url | string | 必須 | Webhook送信先URL（http/https） |
| 購読イベント | subscriptions | array | 必須 | 通知を受け取るイベントの種類 |
| インボックスID | inbox_id | number | 任意 | 特定インボックスに限定する場合 |

### 購読可能イベント一覧

| イベント名 | 説明 |
|-----------|------|
| conversation_status_changed | 会話ステータス変更時 |
| conversation_updated | 会話更新時 |
| conversation_created | 会話作成時 |
| contact_created | 連絡先作成時 |
| contact_updated | 連絡先更新時 |
| message_created | メッセージ作成時 |
| message_updated | メッセージ更新時 |
| webwidget_triggered | ウィジェットトリガー時 |
| inbox_created | インボックス作成時 |
| inbox_updated | インボックス更新時 |
| conversation_typing_on | 入力開始時 |
| conversation_typing_off | 入力終了時 |

## 表示項目

### 一覧テーブル

| 項目名 | 項目ID | 型 | 説明 |
|--------|--------|-----|------|
| エンドポイントURL | url | string | Webhook送信先URL |
| アクション | - | - | 編集・削除ボタン |

### アクションボタン

| ボタン名 | 説明 |
|---------|------|
| 編集 | Webhookを編集 |
| 削除 | Webhookを削除 |

## イベント仕様

### 1-Webhook追加ボタン押下

ヘッダー部の「+ Add Webhook」ボタンをクリックすると、作成用のモーダルダイアログが表示されます。

**処理フロー**：
1. `openAddPopup()` が呼び出される
2. `showAddPopup` が `true` に設定される
3. `NewWebhook` コンポーネントがモーダル内に表示される

### 2-Webhook編集ボタン押下

一覧の各行にある編集ボタンをクリックすると、編集用のモーダルダイアログが表示されます。

**処理フロー**：
1. `openEditPopup(webhook)` が呼び出される
2. `selectedWebHook` に選択したWebhookが格納される
3. `showEditPopup` が `true` に設定される
4. `EditWebhook` コンポーネントがモーダル内に表示される

### 3-Webhook削除ボタン押下

一覧の各行にある削除ボタンをクリックすると、確認ダイアログが表示されます。

**処理フロー**：
1. `openDeletePopup(webhook)` が呼び出される
2. `selectedWebHook` に選択したWebhookが格納される
3. `showDeleteConfirmationPopup` が `true` に設定される
4. 確認後、`confirmDeletion()` が呼び出される
5. `deleteWebhook(id)` が呼び出される
6. `this.$store.dispatch('webhooks/delete', id)` でAPIを呼び出し
7. 成功時：成功メッセージを表示
8. 失敗時：エラーメッセージを表示

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| Webhook一覧取得 | webhooks | SELECT | アカウントに紐づく全Webhookを取得 |
| Webhook作成 | webhooks | INSERT | 新しいWebhookを作成 |
| Webhook更新 | webhooks | UPDATE | 既存Webhookを更新 |
| Webhook削除 | webhooks | DELETE | 指定されたWebhookを削除 |

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

#### webhooks

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | id | シーケンス自動採番 | 主キー |
| INSERT | name | フォーム入力値 | Webhook名 |
| INSERT | url | フォーム入力値 | エンドポイントURL |
| INSERT | subscriptions | JSON配列 | 購読イベント |
| INSERT | webhook_type | 0 (account_type) | デフォルト値 |
| INSERT | account_id | Current.account.id | アカウントID |
| INSERT | inbox_id | フォーム入力値（任意） | 特定インボックス |
| INSERT | created_at | 現在日時 | 作成日時 |
| INSERT | updated_at | 現在日時 | 更新日時 |
| UPDATE | name, url, subscriptions, inbox_id | フォーム入力値 | 編集時 |
| UPDATE | updated_at | 現在日時 | 更新日時 |
| DELETE | - | WHERE id = :id | 指定IDのレコードを削除 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示タイミング |
|-------------|------|---------------|---------------|
| INTEGRATION_SETTINGS.WEBHOOK.DELETE.API.SUCCESS_MESSAGE | 成功 | Webhook削除成功 | 削除成功時 |
| INTEGRATION_SETTINGS.WEBHOOK.DELETE.API.ERROR_MESSAGE | エラー | Webhook削除失敗 | 削除失敗時 |
| INTEGRATION_SETTINGS.WEBHOOK.DELETE.CONFIRM.TITLE | 確認 | 削除確認タイトル | 削除ボタン押下時 |
| INTEGRATION_SETTINGS.WEBHOOK.DELETE.CONFIRM.MESSAGE | 確認 | 削除確認メッセージ | 削除ボタン押下時 |
| INTEGRATION_SETTINGS.WEBHOOK.LIST.404 | 情報 | Webhookがありません | Webhookが0件の場合 |
| INTEGRATION_SETTINGS.WEBHOOK.LOADING | 情報 | 読み込み中 | データ取得中 |

## 例外処理

| 例外状況 | 処理内容 |
|---------|---------|
| データ取得失敗 | エラーを無視し、空のリストを表示 |
| 作成/更新失敗 | エラーメッセージをアラート表示 |
| 削除失敗 | エラーメッセージをアラート表示 |
| URLバリデーションエラー | http/https以外のURLはリジェクト |
| 購読イベントバリデーションエラー | 許可されていないイベントはリジェクト |

## 備考

- `subscriptions` は許可されたイベント名の配列（`ALLOWED_WEBHOOK_EVENTS` で定義）
- `webhook_type` は `account_type`（0）と `inbox_type`（1）の2種類
- URLは `http://` または `https://` で始まる必要がある
- 同一アカウント内で同じURLは登録不可（unique制約）
- Enterprise版では監査ログ機能が追加される（`Webhook.include_mod_with('Audit::Webhook')`）

---

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

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

### 推奨読解順序

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

Webhookのデータ構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | webhook.rb | `app/models/webhook.rb` | モデル定義、ALLOWED_WEBHOOK_EVENTS、バリデーションを確認 |

**読解のコツ**: `ALLOWED_WEBHOOK_EVENTS` で許可されるイベント一覧を確認できます。`validate_webhook_subscriptions` メソッドでsubscriptionsのバリデーションを行います。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Index.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/Index.vue` | 画面の構成、CRUD操作を確認 |

**主要処理フロー**:
1. **51-53行目**: `mounted` で `store.dispatch('webhooks/get')` を呼び出し
2. **55-57行目**: `openAddPopup()` で追加モーダル表示
3. **68-71行目**: `openEditPopup()` で編集モーダル表示
4. **80-91行目**: `deleteWebhook()` で削除処理

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | webhooks.js | `app/javascript/dashboard/store/modules/webhooks.js` | CRUD操作のアクションを確認 |

**主要処理フロー**:
- **25-34行目**: `get` アクションで一覧取得
- **36-49行目**: `create` アクションで作成
- **51-61行目**: `update` アクションで更新
- **63-74行目**: `delete` アクションで削除

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | webhooks_controller.rb | `app/controllers/api/v1/accounts/webhooks_controller.rb` | コントローラのアクション、許可パラメータを確認 |

**主要処理フロー**:
- **5-7行目**: `index` アクションで全Webhook取得
- **9-12行目**: `create` アクションで作成
- **14-16行目**: `update` アクションで更新
- **25-27行目**: `webhook_params` で許可パラメータ定義

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

```
Index.vue (エントリーポイント)
    │
    ├─ mounted()
    │      └─ store.dispatch('webhooks/get')
    │             └─ webHookAPI.get()
    │                    └─ GET /api/v1/accounts/:account_id/webhooks
    │
    ├─ NewWebhook.vue (作成)
    │      └─ store.dispatch('webhooks/create')
    │             └─ webHookAPI.create()
    │
    ├─ EditWebhook.vue (編集)
    │      └─ store.dispatch('webhooks/update')
    │             └─ webHookAPI.update()
    │
    └─ deleteWebhook()
           └─ store.dispatch('webhooks/delete')
                  └─ webHookAPI.delete()
```

### データフロー図

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

ユーザー操作 ────────▶ Index.vue ─────────────▶ 画面表示更新
                           │
                           ▼
                      Vuex Store
                      (webhooks)
                           │
                           ▼
                    webHookAPI
                           │
                           ▼
                  Rails Controller
              (webhooks_controller.rb)
                           │
                           ▼
                       Webhook
                       (Model)
                           │
                           ▼
                    PostgreSQL
                     (webhooks)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Index.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/Index.vue` | ソース | メイン画面コンポーネント |
| NewWebHook.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/NewWebHook.vue` | ソース | 新規作成モーダル |
| EditWebHook.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/EditWebHook.vue` | ソース | 編集モーダル |
| WebhookRow.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/Webhooks/WebhookRow.vue` | ソース | 一覧行コンポーネント |
| webhooks.js | `app/javascript/dashboard/store/modules/webhooks.js` | ソース | Vuexストアモジュール |
| webhooks.js | `app/javascript/dashboard/api/webhooks.js` | ソース | APIクライアント |
| webhooks_controller.rb | `app/controllers/api/v1/accounts/webhooks_controller.rb` | ソース | Railsコントローラ |
| webhook.rb | `app/models/webhook.rb` | ソース | モデル定義 |
