# 機能設計書 149-Dyte統合

## 概要

本ドキュメントは、ChatwootとDyte（ビデオ会議プラットフォーム）を連携する統合機能の設計書である。Dyte統合により、Chatwootの会話内で直接ビデオ会議を開始し、顧客とエージェントがリアルタイムで音声・ビデオコミュニケーションを行えるようになる。

### 本機能の処理概要

**業務上の目的・背景**：テキストベースのカスタマーサポートでは解決が難しい複雑な問題（製品の設定方法、技術的なトラブルシューティング等）が発生することがある。Dyte統合により、必要に応じてテキストチャットからビデオ会議へシームレスに移行でき、より効果的なサポートを提供できる。これにより、顧客満足度の向上と問題解決時間の短縮が期待できる。

**機能の利用シーン**：
- 複雑な技術サポートでの画面共有による問題解決
- 製品のデモンストレーション
- 顧客との対面コミュニケーションが必要な場合
- 契約や重要事項の説明

**主要な処理内容**：
1. Dyte統合の設定（Organization ID、API Key）
2. 会議の作成
3. 参加者の追加
4. 会議リンクを含むメッセージの作成

**関連システム・外部連携**：
- Dyte API v2（会議作成、参加者追加）

**権限による制御**：
- 会話へのアクセス権限（show?ポリシー）が必要

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 65 | 連携アプリ一覧画面 | 参照画面 | Dyte統合の有効化状態表示 |
| 11 | 会話詳細画面 | 主画面 | ビデオ会議の開始 |

## 機能種別

データ連携 / ビデオ会議

## 入力仕様

### 入力パラメータ（統合設定）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| organization_id | String | Yes | Dyte組織ID | 空でないこと |
| api_key | String | Yes | Dyte APIキー | 空でないこと |

### 入力パラメータ（会議作成）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| conversation_id | Integer | Yes | 会話表示ID | 存在する会話 |

### 入力パラメータ（参加者追加）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| conversation_id | Integer | Yes | 会話表示ID | 存在する会話 |
| message_id | Integer | Yes | メッセージID | content_type = 'integrations' |

### 入力データソース

- 管理画面のDyte統合設定フォーム
- 会話詳細画面のビデオ会議開始ボタン

## 出力仕様

### 出力データ（会議作成時）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | String | 会議ID |
| data.meeting_id | String | Dyte会議ID |
| (message) | Message | 会議情報を含むメッセージ |

### 出力データ（参加者追加時）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | String | 参加者ID |
| token | String | 参加者トークン |

### 出力先

- messagesテーブル（会議メッセージ）
- Dyte（会議・参加者）

## 処理フロー

### 処理シーケンス（会議作成）

```
1. エージェントが会議作成を開始
   └─ DyteController#create_a_meeting

2. 会話取得
   └─ fetch_conversation

3. 認可チェック
   └─ authorize_request
   └─ authorize @conversation, :show?

4. Dyte会議作成
   └─ dyte_processor_service.create_a_meeting(Current.user)

5. Dyte API呼び出し
   └─ Dyte.new.create_a_meeting(title)

6. 統合メッセージ作成
   └─ create_a_dyte_integration_message
   └─ content_type: 'integrations'
   └─ content_attributes: { type: 'dyte', data: { meeting_id: ... } }

7. レスポンス返却
   └─ message.push_event_data
```

### 処理シーケンス（参加者追加）

```
1. ユーザーが会議に参加
   └─ DyteController#add_participant_to_meeting

2. メッセージ取得
   └─ fetch_message

3. メッセージタイプ検証
   └─ content_type == 'integrations'

4. 参加者追加
   └─ dyte_processor_service.add_participant_to_meeting
   └─ Dyte.new.add_participant_to_meeting(meeting_id, user_id, name, avatar)

5. レスポンス返却
   └─ { id, token, ... }
```

### フローチャート

```mermaid
flowchart TD
    A[エージェントが会議作成を開始] --> B[会話取得]
    B --> C{認可チェック}
    C -->|失敗| D[403 Forbidden]
    C -->|成功| E[Dyte会議作成API呼び出し]
    E --> F{成功?}
    F -->|No| G[エラーレスポンス]
    F -->|Yes| H[統合メッセージ作成]
    H --> I[content_type: integrations]
    I --> J[push_event_data]
    J --> K[レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-149-01 | 会話アクセス権限 | 会議作成にはshow?ポリシーが必要 | 会議作成時 |
| BR-149-02 | メッセージタイプ検証 | 参加者追加はcontent_type='integrations'のメッセージのみ | 参加者追加時 |
| BR-149-03 | 会議タイトル | 会議タイトルは「{エージェント名}との通話」形式 | 会議作成時 |
| BR-149-04 | プリセット | 参加者追加時はgroup_call_hostプリセットを使用 | 参加者追加時 |
| BR-149-05 | アバターフォールバック | ユーザーアバターがない場合はデフォルト画像を使用 | 参加者追加時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 設定 | integrations_hooks | INSERT/UPDATE | Dyte Hook作成・更新 |
| 会議作成 | messages | INSERT | 統合メッセージ作成 |
| 会話取得 | conversations | SELECT | 会話情報取得 |
| メッセージ取得 | messages | SELECT | メッセージ情報取得 |

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

#### integrations_hooks

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | app_id = 'dyte' AND account_id = ? | Hook取得 |
| INSERT | app_id | 'dyte' | 固定値 |
| INSERT | settings | { organization_id, api_key } | 認証情報 |

#### messages

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | message_type | 'outgoing' | エージェント発信 |
| INSERT | content_type | 'integrations' | 統合メッセージ |
| INSERT | content | 会議タイトル | - |
| INSERT | content_attributes | { type: 'dyte', data: { meeting_id } } | 会議情報 |
| INSERT | sender | Current.user | エージェント |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 403 | Forbidden | 会話へのアクセス権限がない | 権限を確認 |
| 422 | Unprocessable Entity | メッセージタイプが不正 | 正しいメッセージを選択 |
| 422 | Unprocessable Entity | Dyte API エラー | API設定を確認 |
| 422 | Unprocessable Entity | 認証情報が不足 | organization_id, api_keyを設定 |

### リトライ仕様

Dyte API呼び出し自体にはリトライ仕様は存在しない

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

- 会議作成とメッセージ作成は同一トランザクション内

## パフォーマンス要件

- 会議作成: 5秒以内
- 参加者追加: 3秒以内

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

- API Keyはsettings内に暗号化して保存
- 認証情報はBase64エンコードしてDyte APIに送信
- 会話アクセス権限による制御

## 備考

- Dyte API v2を使用
- 会議プリセット: group_call_host
- content_type='integrations'のメッセージはWidget/公開APIでも表示可能

---

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

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

### 推奨読解順序

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

Dyte統合の設定を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | apps.yml | `config/integration/apps.yml` | Dyteアプリ設定（169-202行目） |

**読解のコツ**:
- **apps.yml 169-202行目**: Dyteのsettings_json_schema（organization_id, api_key必須）を確認
- **settings_form_schema**: フロントエンドのフォーム構造を確認

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

Dyte統合コントローラーを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | dyte_controller.rb | `app/controllers/api/v1/accounts/integrations/dyte_controller.rb` | 各種API操作 |

**主要処理フロー**:
1. **2-4行目**: before_actionで会話/メッセージ取得、認可チェック
2. **6-8行目**: `create_a_meeting`で会議作成
3. **10-20行目**: `add_participant_to_meeting`で参加者追加
4. **24-26行目**: `authorize_request`で認可チェック

#### Step 3: サービス処理を理解する

ProcessorServiceの処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | processor_service.rb | `lib/integrations/dyte/processor_service.rb` | Dyte API呼び出し |

**主要処理フロー**:
- **4-13行目**: `create_a_meeting`で会議作成とメッセージ生成
- **15-16行目**: `add_participant_to_meeting`で参加者追加
- **20-38行目**: `create_a_dyte_integration_message`で統合メッセージ作成

#### Step 4: Dyteクライアントを理解する

Dyteクライアントを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | dyte.rb | `lib/dyte.rb` | Dyte APIクライアント |

**主要処理フロー**:
- **6-10行目**: コンストラクタでBase64認証情報生成
- **12-20行目**: `create_a_meeting`でPOSTリクエスト
- **22-34行目**: `add_participant_to_meeting`で参加者追加

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

```
DyteController
    │
    ├─ before_action :fetch_conversation
    │      └─ conversations.find_by!(display_id: ...)
    │
    ├─ before_action :authorize_request
    │      └─ authorize @conversation, :show?
    │
    ├─ #create_a_meeting
    │      └─ dyte_processor_service.create_a_meeting(Current.user)
    │             ├─ Dyte.new.create_a_meeting(title)
    │             │      └─ POST /meetings
    │             ├─ create_a_dyte_integration_message
    │             │      └─ conversation.messages.create!(...)
    │             └─ message.push_event_data
    │
    └─ #add_participant_to_meeting
           ├─ content_type == 'integrations' 検証
           └─ dyte_processor_service.add_participant_to_meeting
                  └─ Dyte.new.add_participant_to_meeting
                         └─ POST /meetings/{id}/participants
```

### データフロー図

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

conversation_id        ───▶ DyteController             ───▶ Dyte API
                               │                              (会議作成)
                               ▼
                       ProcessorService               ───▶ messages
                               │                              (統合メッセージ)
                               ▼
                       Dyte.create_a_meeting
                               │
                               ▼
                       create_integration_message
                               │
                               ▼
                       push_event_data
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dyte_controller.rb | `app/controllers/api/v1/accounts/integrations/dyte_controller.rb` | コントローラー | Dyte統合API |
| processor_service.rb | `lib/integrations/dyte/processor_service.rb` | サービス | Dyte API呼び出し |
| dyte.rb | `lib/dyte.rb` | クライアント | Dyte APIクライアント |
| apps.yml | `config/integration/apps.yml` | 設定 | Dyteアプリ設定 |
| dyte_controller.rb | `app/controllers/api/v1/widget/integrations/dyte_controller.rb` | コントローラー | Widget用Dyte API |
