# 帳票設計書 7-CSATレポート（CSV）

## 概要

本ドキュメントは、Chatwootシステムにおける顧客満足度調査（CSAT: Customer Satisfaction）の回答レポート（CSV形式）の設計仕様を定義する。

### 本帳票の処理概要

CSATレポートは、指定期間内における顧客満足度調査の回答データを一覧形式で出力し、顧客フィードバック分析のための詳細データをCSV形式で出力する帳票である。

**業務上の目的・背景**：カスタマーサポートの品質向上には、顧客からの直接的なフィードバックが不可欠である。CSATレポートにより、各エージェントの対応に対する評価、顧客の具体的なフィードバックコメント、改善が必要なエリアを特定できる。本帳票は、サポート品質改善のPDCAサイクルにおける重要なデータソースとして活用される。

**帳票の利用シーン**：エージェントのパフォーマンス評価、顧客満足度トレンド分析、低評価案件の詳細調査、サポート品質改善会議の資料作成時に利用される。

**主要な出力内容**：
1. エージェント名（対応したエージェントの名前とメールアドレス）
2. 評価（1-5の満足度スコア）
3. フィードバック（顧客からのコメント）
4. 連絡先名（回答した顧客の名前）
5. 連絡先メールアドレス
6. 連絡先電話番号
7. 会話リンク（該当会話へのURL）
8. 記録日時（回答が記録された日時）
9. レビューノート（Enterprise版のみ：管理者によるレビューコメント）

**帳票の出力タイミング**：管理者がCSATレポート画面から任意のタイミングでダウンロードボタンをクリックした際にオンデマンドで生成・出力される。

**帳票の利用者**：アカウント管理者、品質管理担当者、チームリーダー

## 帳票種別

一覧表

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | CSATレポート画面 | `/app/accounts/:account_id/reports/csat` | 「Download」ボタンクリック |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | CSV |
| 用紙サイズ | N/A |
| 向き | N/A |
| ファイル名 | `csat_report.csv` |
| 出力方法 | ダウンロード |
| 文字コード | UTF-8 |

### CSV固有設定

| 項目 | 内容 |
|-----|------|
| 区切り文字 | カンマ（,） |
| 囲み文字 | ダブルクォート（"） |
| ヘッダー行 | あり（1行目：カラムヘッダー、最終行：期間情報） |
| BOM | なし |

## 帳票レイアウト

### レイアウト概要

CSVファイルは以下の構成で出力される。1行目にカラムヘッダー、2行目以降にCSAT回答データ、最終行にレポート対象期間が出力される。

```
┌─────────────────────────────────────┐
│        カラムヘッダー（1行目）         │
├─────────────────────────────────────┤
│          CSAT回答データ              │
│          （2行目以降）                │
│         各回答1行ずつ                │
├─────────────────────────────────────┤
│        期間情報（最終行）             │
└─────────────────────────────────────┘
```

### ヘッダー部（1行目）

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | Agent Name | エージェント名 | I18n翻訳キー | 文字列 |
| 2 | Rating | 評価 | I18n翻訳キー | 文字列 |
| 3 | Feedback Comment | フィードバック | I18n翻訳キー | 文字列 |
| 4 | Contact Name | 連絡先名 | I18n翻訳キー | 文字列 |
| 5 | Contact Email Address | 連絡先メールアドレス | I18n翻訳キー | 文字列 |
| 6 | Contact Phone Number | 連絡先電話番号 | I18n翻訳キー | 文字列 |
| 7 | Link to the conversation | 会話リンク | I18n翻訳キー | 文字列 |
| 8 | Recorded date | 記録日時 | I18n翻訳キー | 文字列 |
| 9 | Review Notes | レビューノート（Enterprise版のみ） | I18n翻訳キー | 文字列 |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | Agent Name | エージェント名とメールアドレス | `users.name`, `users.email` | "{名前} ({メール})" | - |
| 2 | Rating | 満足度評価 | `csat_survey_responses.rating` | 整数（1-5） | - |
| 3 | Feedback Comment | フィードバックメッセージ | `csat_survey_responses.feedback_message` | 文字列 | - |
| 4 | Contact Name | 連絡先の名前 | `contacts.name` | 文字列 | - |
| 5 | Contact Email Address | 連絡先のメールアドレス | `contacts.email` | 文字列 | - |
| 6 | Contact Phone Number | 連絡先の電話番号 | `contacts.phone_number` | 文字列 | - |
| 7 | Link to the conversation | 会話へのリンク | `app_account_conversation_url` | URL文字列 | - |
| 8 | Recorded date | 記録日時 | `csat_survey_responses.created_at` | 日時 | - |
| 9 | Review Notes | レビューノート（Enterprise版のみ） | `csat_survey_responses.csat_review_notes` | 文字列 | - |

### フッター部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | レポート期間 | 集計対象期間 | `params[:since]`, `params[:until]` | "Reporting period YYYY-MM-DD to YYYY-MM-DD" |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| since | 集計開始日（UNIXタイムスタンプ） | Yes |
| until | 集計終了日（UNIXタイムスタンプ） | Yes |
| user_ids | フィルタ対象のエージェントID | No |
| inbox_id | フィルタ対象の受信トレイID | No |
| team_id | フィルタ対象のチームID | No |
| rating | フィルタ対象の評価値 | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | created_at | 降順（デフォルト） |

### 改ページ条件

N/A（CSV形式のため改ページなし）

## データベース参照仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| csat_survey_responses | CSAT回答データの取得 | `csat_survey_responses.account_id = Current.account.id` |
| users | エージェント情報の取得 | `users.id = csat_survey_responses.assigned_agent_id` |
| contacts | 連絡先情報の取得 | `contacts.id = csat_survey_responses.contact_id` |
| conversations | 会話情報の取得 | `conversations.id = csat_survey_responses.conversation_id` |

### テーブル別参照項目詳細

#### csat_survey_responses

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| rating | Rating | - | 1-5の整数 |
| feedback_message | Feedback Comment | - | 任意 |
| created_at | Recorded date | - | - |
| csat_review_notes | Review Notes | Enterprise版のみ | - |

#### users

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| name | Agent Name | - | - |
| email | Agent Name | - | 名前の後に括弧で追加 |

#### contacts

| 参照項目（カラム名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| name | Contact Name | - | - |
| email | Contact Email Address | - | - |
| phone_number | Contact Phone Number | - | - |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| Link to the conversation | `app_account_conversation_url(account_id, conversation.display_id)` | N/A | URLヘルパーで生成 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[ダウンロード要求] --> B[check_authorization]
    B --> C[set_csat_survey_responses]
    C --> D[フィルタ条件適用]
    D --> E[download アクション]
    E --> F[ERBテンプレートでCSV出力]
    F --> G[ファイルダウンロード]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| 認可エラー | レポート閲覧権限がない場合 | HTTP 403 | 管理者権限を持つユーザーでログイン |
| パラメータ不足 | since/untilパラメータが不正な場合 | パラメータによる | 正しい期間パラメータを指定 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数百〜数千件 |
| 目標出力時間 | 数秒以内 |
| 同時出力数上限 | 特に制限なし |

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

- レポート閲覧は認可チェックを実施
- 顧客の個人情報（名前、メールアドレス、電話番号）が含まれるため、アクセス制御に注意
- Enterprise版のレビューノートには内部コメントが含まれる可能性があるため、外部共有時は注意

## 備考

- Enterprise版では「Review Notes」カラムが追加される（ChatwootApp.enterprise? で判定）
- エージェントが未割り当ての場合、Agent Name は空（nil）になる
- フィードバックメッセージが空の場合、Feedback Comment カラムは空白
- 会話が削除されている場合、Link to the conversation は空になる

---

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

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

### 推奨読解順序

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

まず、帳票出力に使用されるデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | en.yml | `config/locales/en.yml` | reports.csat.headersセクション（行195-205）でCSVヘッダーの翻訳キーを確認 |
| 1-2 | csat_survey_responses テーブル定義 | `db/schema.rb` | csat_survey_responsesテーブルのカラム定義 |

**読解のコツ**: csat_survey_responsesテーブルはassigned_agent_id、contact_id、conversation_idで関連テーブルと紐づく。

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

処理の起点となるコントローラーを特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | csat_survey_responses_controller.rb | `app/controllers/api/v1/accounts/csat_survey_responses_controller.rb` | downloadアクション（行22-26）がエントリーポイント |

**主要処理フロー**:
1. **行7**: `check_authorization` で権限チェック
2. **行8**: `set_csat_survey_responses` でデータ取得
3. **行22-26**: `download` アクションでCSVレスポンスを生成
4. **行54**: Enterprise版の拡張（`prepend_mod_with`）

#### Step 3: フィルタ処理を理解する

データ取得時のフィルタ処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | csat_survey_responses_controller.rb | `app/controllers/api/v1/accounts/csat_survey_responses_controller.rb` | `set_csat_survey_responses` メソッド（行36-43） |

**主要処理フロー**:
- **行37**: 基本クエリでincludes（conversation, assigned_agent, contact）
- **行38-43**: 各フィルタを連鎖適用（created_at, assigned_agent_id, inbox_id, team_id, rating）

#### Step 4: CSVテンプレートを理解する

最終的なCSV出力のテンプレートを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | download.csv.erb | `app/views/api/v1/accounts/csat_survey_responses/download.csv.erb` | CSVの行構造と出力形式（全43行） |

**主要処理フロー**:
- **行1-13**: ヘッダー行の定義（Enterprise版で9カラム目追加）
- **行14**: ヘッダー行をCSV出力
- **行15-33**: 各CSAT回答をループして行を生成
- **行21-29**: 行データの構築（エージェント名、評価、フィードバック等）
- **行30**: Enterprise版でreview_notesを追加
- **行34-42**: 最終行にレポート期間を出力

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

```
Api::V1::Accounts::CsatSurveyResponsesController#download
    │
    ├─ check_authorization (before_action)
    │
    ├─ set_csat_survey_responses (before_action)
    │      │
    │      ├─ csat_survey_responses.includes([:conversation, :assigned_agent, :contact])
    │      │
    │      └─ チェーン: filtrate -> filter_by_created_at -> filter_by_assigned_agent_id
    │                   -> filter_by_inbox_id -> filter_by_team_id -> filter_by_rating
    │
    └─ render template: 'download'
           └─ download.csv.erb
                  │
                  ├─ 各csat_responseをループ
                  │      ├─ assigned_agent から Agent Name を取得
                  │      ├─ contact から連絡先情報を取得
                  │      └─ conversation から会話リンクを生成
                  │
                  └─ Enterprise版: csat_review_notes を追加
```

### データフロー図

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

params[:since]    ─────┐
params[:until]    ─────┼──▶  set_csat_survey_responses     ──▶   @csat_survey_responses
params[:user_ids] ─────┤           │
params[:inbox_id] ─────┤           ├─▶ filter_by_created_at
params[:team_id]  ─────┤           ├─▶ filter_by_assigned_agent_id
params[:rating]   ─────┘           ├─▶ filter_by_inbox_id
                                   ├─▶ filter_by_team_id
                                   └─▶ filter_by_rating
                                              │
                                              ▼
                                    download.csv.erb
                                              │
                              ┌───────────────┼───────────────┐
                              │               │               │
                      assigned_agent      contact        conversation
                              │               │               │
                              ▼               ▼               ▼
                        Agent Name      Contact Info    Conversation URL
                                              │
                                              ▼
                                       csat_report.csv
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| csat_survey_responses_controller.rb | `app/controllers/api/v1/accounts/csat_survey_responses_controller.rb` | コントローラー | エントリーポイント、フィルタ処理 |
| download.csv.erb | `app/views/api/v1/accounts/csat_survey_responses/download.csv.erb` | テンプレート | CSV出力フォーマット定義 |
| csat_survey_response.rb | `app/models/csat_survey_response.rb` | モデル | CSAT回答データモデル |
| en.yml | `config/locales/en.yml` | 設定 | CSVヘッダーの翻訳定義 |
