# 機能設計書 106-サーベイテンプレート

## 概要

本ドキュメントは、Chatwootにおける CSAT サーベイテンプレート管理機能について記述する。WhatsApp チャネル用の CSAT（顧客満足度調査）テンプレートの作成・管理を行う機能である。

### 本機能の処理概要

**業務上の目的・背景**：WhatsAppでは、事前承認されたメッセージテンプレートを使用してプロアクティブなメッセージ送信を行う必要がある。CSATサーベイを WhatsApp 経由で送信するためには、専用のテンプレートを作成し、Meta（Facebook）または Twilio の承認を得る必要がある。本機能は、そのテンプレート管理を自動化する。

**機能の利用シーン**：
- インボックス設定画面でCSATテンプレートの状態を確認
- 新しいCSATテンプレートを作成（メッセージ、ボタンテキスト、言語を指定）
- 既存テンプレートのステータス（承認待ち、承認済み、却下）を確認

**主要な処理内容**：
1. CSATテンプレートのステータス取得（show アクション）
2. 新しいCSATテンプレートの作成（create アクション）
3. 既存テンプレートがある場合は削除してから新規作成
4. WhatsApp Cloud API または Twilio API との連携

**関連システム・外部連携**：
- WhatsApp Cloud API: Meta のテンプレート管理API
- Twilio Content API: Twilio のテンプレート管理API

**権限による制御**：インボックスの show 権限が必要。authorize @inbox, :show? でアクセス制御される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 50 | インボックス設定画面 | 参照画面 | CSATテンプレートの設定（WhatsApp インボックス） |

## 機能種別

CRUD操作（参照・作成） / 外部連携

## 入力仕様

### 入力パラメータ

#### テンプレートステータス取得（show）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| inbox_id | Integer | Yes | インボックスID | 存在確認 |

#### テンプレート作成（create）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| inbox_id | Integer | Yes | インボックスID | 存在確認 |
| template.message | String | Yes | テンプレートメッセージ | 必須 |
| template.button_text | String | No | ボタンテキスト（デフォルト: "Please rate us"） | - |
| template.language | String | No | 言語コード（デフォルト: "en"） | - |

### 入力データソース

- 画面入力: インボックス設定画面
- DBテーブル: inboxes テーブルから csat_config を取得

## 出力仕様

### 出力データ

#### テンプレートステータス（show）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| template_exists | Boolean | テンプレートが存在するか |
| template_name | String | テンプレート名（WhatsApp Cloud） |
| friendly_name | String | フレンドリー名（Twilio） |
| content_sid | String | コンテンツSID（Twilio） |
| status | String | テンプレートステータス（PENDING, APPROVED, REJECTED） |
| template_id | String | テンプレートID（WhatsApp Cloud） |
| language | String | 言語コード |

#### テンプレート作成（create）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| template.name / friendly_name | String | 作成されたテンプレート名 |
| template.template_id / content_sid | String | テンプレートID |
| template.status | String | 初期ステータス（PENDING） |
| template.language | String | 言語コード |

### 出力先

- 画面表示: JSON形式でAPIレスポンス
- 外部API: WhatsApp Cloud API / Twilio Content API

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ APIエンドポイント: /api/v1/accounts/:account_id/inboxes/:inbox_id/csat_templates

2. 前処理
   ├─ fetch_inbox: インボックス取得
   └─ validate_whatsapp_channel: WhatsApp チャネルか確認

3. show アクション
   ├─ CsatTemplateManagementService.new(inbox).template_status
   ├─ csat_config からテンプレート情報取得
   └─ WhatsApp/Twilio API でステータス確認

4. create アクション
   ├─ テンプレートパラメータ抽出
   ├─ CsatTemplateManagementService.new(inbox).create_template
   │      ├─ 既存テンプレート削除
   │      ├─ WhatsApp/Twilio API でテンプレート作成
   │      └─ inbox.csat_config 更新
   └─ レスポンス返却
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B[インボックス取得]
    B --> C{WhatsApp?}
    C -->|No| D[400 Bad Request]
    C -->|Yes| E{アクション種別}
    E -->|show| F[テンプレートステータス取得]
    E -->|create| G[パラメータ検証]
    F --> H{テンプレート存在?}
    H -->|Yes| I[API でステータス確認]
    H -->|No| J[template_exists: false]
    I --> K[JSON レスポンス]
    J --> K
    G --> L{message あり?}
    L -->|No| M[422 Unprocessable Entity]
    L -->|Yes| N[既存テンプレート削除]
    N --> O[新規テンプレート作成]
    O --> P{成功?}
    P -->|Yes| Q[csat_config 更新]
    P -->|No| R[エラーレスポンス]
    Q --> S[201 Created]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-106-01 | WhatsApp限定 | CSATテンプレート機能は WhatsApp チャネルのみ利用可能 | 常時 |
| BR-106-02 | メッセージ必須 | テンプレート作成時は message パラメータ必須 | create アクション |
| BR-106-03 | 既存削除 | 新規テンプレート作成時は既存を先に削除 | create アクション |
| BR-106-04 | デフォルト言語 | 言語未指定時は 'en' を使用 | create アクション |
| BR-106-05 | デフォルトボタン | ボタンテキスト未指定時は 'Please rate us' を使用 | create アクション |

### 計算ロジック

テンプレート名の生成:
```ruby
CsatTemplateNameService.csat_template_name(@inbox.id)
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| show | inboxes | SELECT | csat_config 取得 |
| create | inboxes | SELECT | csat_config 取得 |
| create | inboxes | UPDATE | csat_config 更新 |

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

#### inboxes

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | csat_config | id = inbox_id | JSONB 型 |
| UPDATE | csat_config | テンプレート情報マージ | 既存設定は保持 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 400 | Bad Request | WhatsApp 以外のチャネル | エラーメッセージ表示 |
| 403 | Forbidden | インボックス閲覧権限なし | エラーメッセージ表示 |
| 422 | UnprocessableEntity | message パラメータなし | エラーメッセージ表示 |
| 500 | InternalServerError | 外部API エラー | service_error 返却 |

### リトライ仕様

- 外部APIエラー時は即時エラー返却（リトライなし）
- ユーザーが再度操作する必要あり

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

- csat_config 更新は Railsデフォルトトランザクション内
- 外部API呼び出しはトランザクション外

## パフォーマンス要件

- レスポンス時間: 外部API応答に依存（5-10秒程度）
- 外部API呼び出しは同期処理

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

- 認証必須: Devise TokenAuthによる認証
- 認可: Punditによるインボックス閲覧権限チェック
- 外部API認証: WhatsApp Cloud API / Twilio API の認証情報を安全に管理

## 備考

- WhatsApp Cloud API と Twilio WhatsApp で異なるレスポンス形式に対応
- テンプレートの承認には Meta/Twilio 側での審査が必要（数時間〜数日）
- csat_config は JSONB 型で柔軟にテンプレート情報を保存

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | inbox.rb | `app/models/inbox.rb` | csat_config カラム（JSONB型） |

**読解のコツ**: inboxes テーブルの csat_config カラムに、テンプレート情報が JSON 形式で保存される。

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

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

**主要処理フロー**:
- **5-13行目**: `show` - テンプレートステータス取得
- **15-25行目**: `create` - テンプレート作成
- **29-32行目**: `fetch_inbox` - インボックス取得と認可
- **34-38行目**: `validate_whatsapp_channel` - WhatsApp チャネル検証

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | csat_template_management_service.rb | `app/services/csat_template_management_service.rb` | テンプレート管理ロジック |

**主要処理フロー**:
- **2-3行目**: デフォルト値定数
- **9-21行目**: `template_status` - ステータス取得
- **23-35行目**: `create_template` - テンプレート作成
- **43-49行目**: `create_template_via_provider` - プロバイダ別作成
- **72-77行目**: `update_inbox_csat_config` - csat_config 更新
- **149-161行目**: `delete_existing_template_if_needed` - 既存テンプレート削除

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

```
InboxCsatTemplatesController
    │
    ├─ before_action
    │      ├─ fetch_inbox
    │      │      └─ authorize @inbox, :show?
    │      └─ validate_whatsapp_channel
    │
    ├─ show
    │      └─ CsatTemplateManagementService.template_status
    │             ├─ get_twilio_template_status (Twilio の場合)
    │             │      └─ Twilio::CsatTemplateService.get_template_status
    │             └─ get_whatsapp_template_status (WhatsApp Cloud の場合)
    │                    └─ Whatsapp::CsatTemplateService.get_template_status
    │
    └─ create
           └─ CsatTemplateManagementService.create_template
                  ├─ validate_template_params!
                  ├─ delete_existing_template_if_needed
                  │      ├─ delete_existing_twilio_template
                  │      └─ delete_existing_whatsapp_template
                  ├─ create_template_via_provider
                  │      ├─ create_twilio_template
                  │      │      └─ Twilio::CsatTemplateService.create_template
                  │      └─ create_whatsapp_template
                  │             └─ Whatsapp::CsatTemplateService.create_template
                  └─ update_inbox_csat_config
```

### データフロー図

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

API リクエスト ─────▶ InboxCsatTemplatesController ─────▶ JSON Response
(inbox_id,                  │
 template params)           │
                           ▼
              CsatTemplateManagementService
                           │
                ┌──────────┴──────────┐
                ▼                     ▼
    Twilio::CsatTemplateService    Whatsapp::CsatTemplateService
                │                     │
                ▼                     ▼
        Twilio Content API      WhatsApp Cloud API
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| inbox_csat_templates_controller.rb | `app/controllers/api/v1/accounts/inbox_csat_templates_controller.rb` | コントローラー | API エンドポイント |
| csat_template_management_service.rb | `app/services/csat_template_management_service.rb` | サービス | テンプレート管理ロジック |
| csat_template_service.rb | `app/services/twilio/csat_template_service.rb` | サービス | Twilio テンプレートサービス |
| csat_template_service.rb | `app/services/whatsapp/csat_template_service.rb` | サービス | WhatsApp テンプレートサービス |
| csat_template_name_service.rb | `app/services/csat_template_name_service.rb` | サービス | テンプレート名生成 |
| inbox.rb | `app/models/inbox.rb` | モデル | インボックスモデル（csat_config） |
