# 画面設計書 43-CSATレポート画面

## 概要

本ドキュメントは、ChatwootのCSAT（Customer Satisfaction）レポート画面の設計仕様を定義するものである。

### 本画面の処理概要

顧客満足度調査（CSAT）の結果を分析・可視化する画面。CSATスコアの分布、回答率、各評価ごとの件数などのメトリクスを表示し、個別の回答内容をテーブル形式で確認できる。

**業務上の目的・背景**：顧客満足度調査は、サポート品質を顧客視点から測定する重要な指標である。会話終了後に送信されるCSATアンケートへの回答を集計・分析することで、エージェントごと、インボックスごと、チームごとの顧客満足度を把握できる。これにより、優秀なエージェントの特定や改善が必要な領域の発見に活用される。

**画面へのアクセス方法**：サイドメニューの「レポート」から「CSAT」を選択することでアクセスする。管理者またはレポート管理権限を持つユーザーのみがアクセス可能。

**主要な操作・処理内容**：
1. 期間フィルタによるレポート期間の選択
2. エージェント、インボックス、チーム、評価レベルによるフィルタリング
3. CSATメトリクス（平均スコア、回答率、評価分布）の確認
4. CSAT回答一覧のページング閲覧
5. CSVレポートのダウンロード

**画面遷移**：
- 遷移元：レポートメニュー
- 遷移先：各会話詳細画面（テーブルの会話リンクから）

**権限による表示制御**：管理者（administrator）およびレポート管理権限（report_manage）を持つユーザーのみがアクセス可能。チームフィルタはTEAM_MANAGEMENT機能が有効な場合のみ表示される。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 105 | CSATサーベイ | 主機能 | 顧客満足度調査レポートの表示 |
| 107 | サーベイメトリクス | 補助機能 | CSAT集計結果の表示 |
| 108 | サーベイダウンロード | 補助機能 | CSAT結果のエクスポート |

## 画面種別

一覧

## URL/ルーティング

```
/app/accounts/:accountId/reports/csat
```

- ルート名: `csat_reports`
- パラメータ:
  - `accountId`: アカウントID

## 入出力項目

### フィルタ入力項目

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| 期間（from/to） | Date | ○ | レポート対象期間 |
| エージェント | MultiSelect | - | 担当エージェントでフィルタ（複数選択可） |
| インボックス | Select | - | インボックスでフィルタ |
| チーム | Select | - | チームでフィルタ（TEAM_MANAGEMENT有効時のみ） |
| 評価 | Select | - | 評価レベル（1-5）でフィルタ |

## 表示項目

### レポートヘッダー

| 項目名 | 型 | 説明 |
|--------|-----|------|
| レポートタイトル | String | 「CSATレポート」 |
| ダウンロードボタン | Button | CSVレポートをダウンロード |

### CSATメトリクス

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 総回答数 | Number | 対象期間のCSAT回答総数 |
| 満足度スコア | Percentage | 平均満足度スコア（%） |
| 回答率 | Percentage | 送信されたCSATに対する回答率 |
| 評価分布 | Chart | 各評価（1-5）の件数分布 |

### CSAT回答テーブル

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 連絡先名 | String | 回答者の連絡先名 |
| 担当エージェント | String | 対応したエージェント名 |
| 評価 | Number/Emoji | 1-5の評価（絵文字表示） |
| フィードバック | String | 顧客からのコメント |
| 会話リンク | Link | 対象会話への遷移リンク |
| 回答日時 | DateTime | CSAT回答日時 |

### ページネーション

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 現在のページ | Number | 現在表示中のページ番号 |
| ページ切り替え | Pagination | ページ遷移UI |

## イベント仕様

### 1-フィルタ変更イベント

**トリガー**: 任意のフィルタ条件変更時

**処理フロー**:
1. ユーザーがフィルタ条件を変更
2. `onFilterChange`メソッドが呼び出される
3. from, to, userIds, inbox, team, rating状態が更新される
4. `getAllData`メソッドが呼び出される
5. `csat/getMetrics`と`csat/get`がディスパッチされる
6. APIからデータ取得後、画面が更新される

### 2-ページ変更イベント

**トリガー**: ページネーションのページ変更時

**処理フロー**:
1. ユーザーがページを切り替え
2. `onPageNumberChange`メソッドが呼び出される
3. `pageIndex`が更新される
4. `getResponses`メソッドで新しいページのデータを取得

### 3-レポートダウンロード

**トリガー**: ダウンロードボタンクリック

**処理フロー**:
1. `downloadReports`メソッドが呼び出される
2. `csat/downloadCSATReports`アクションがディスパッチされる
3. APIエンドポイント`/api/v1/accounts/:accountId/csat_survey_responses/download`にリクエスト
4. レスポンスをCSVファイルとしてダウンロード

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| フィルタ変更 | csat_survey_responses | SELECT | CSAT回答データの取得 |
| メトリクス取得 | csat_survey_responses | SELECT | CSATメトリクスの集計 |
| メトリクス取得 | messages | SELECT | 送信CSAT数のカウント |

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

#### csat_survey_responses

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | account_id | 現在のアカウントID | フィルタ条件 |
| SELECT | created_at | since〜until期間 | 期間フィルタ |
| SELECT | assigned_agent_id | 指定エージェントID配列 | エージェントフィルタ |
| SELECT | inbox_id | 指定インボックスID | インボックスフィルタ |
| SELECT | team_id | 指定チームID | チームフィルタ |
| SELECT | rating | 指定評価値 | 評価フィルタ |

## メッセージ仕様

| 種別 | メッセージキー | メッセージ内容 |
|------|---------------|---------------|
| エラー | REPORT.CSAT_REPORTS.DOWNLOAD_FAILED | ダウンロードに失敗しました |
| エラー | REPORT.DATA_FETCHING_FAILED | データの取得に失敗しました |

## 例外処理

| 例外状態 | 処理内容 |
|----------|---------|
| API通信エラー | エラートースト表示 |
| 権限不足 | 403エラー、アクセス拒否画面表示 |
| データなし | 空のテーブルとゼロ値のメトリクス表示 |
| ダウンロードエラー | エラーメッセージ表示 |

## 備考

- CSATは会話のクローズ後に顧客に送信される
- 評価は1-5のスケールで、絵文字で表現される場合がある
- チームフィルタはTEAM_MANAGEMENT機能フラグが有効な場合のみ表示
- 1ページあたり25件表示（RESULTS_PER_PAGE = 25）

---

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

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

### 推奨読解順序

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

まず、CSATデータの構造とVuexストアの状態管理を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | csat.js | `app/javascript/dashboard/store/modules/csat.js` | state構造とactions |

**読解のコツ**:
- メトリクス取得とレスポンス取得が分離されている
- ページネーションは`pageIndex`で0ベースで管理

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

処理の起点となるVueコンポーネントを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | CsatResponses.vue | `app/javascript/dashboard/routes/dashboard/settings/reports/CsatResponses.vue` | メインコンポーネント |

**主要処理フロー**:
1. **L22-31**: data定義 - pageIndex、フィルタ条件の初期状態
2. **L34-53**: computed - requestPayload構築、isTeamsEnabled判定
3. **L55-109**: methods - データ取得、フィルタ変更、ダウンロード処理

#### Step 3: 子コンポーネントを理解する

メトリクスとテーブルを担当するコンポーネント。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | CsatMetrics.vue | `app/javascript/dashboard/routes/dashboard/settings/reports/components/CsatMetrics.vue` | メトリクス表示 |
| 3-2 | CsatTable.vue | `app/javascript/dashboard/routes/dashboard/settings/reports/components/CsatTable.vue` | テーブル表示 |
| 3-3 | CsatFilters.vue | `app/javascript/dashboard/routes/dashboard/settings/reports/components/Csat/CsatFilters.vue` | フィルタUI |

#### Step 4: API層を理解する

バックエンドとの通信を担当するAPI層。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | csatReports.js | `app/javascript/dashboard/api/csatReports.js` | API定義 |

**主要処理フロー**:
- **L9-22**: get - CSAT回答リストの取得（ページング対応）
- **L24-36**: download - CSVダウンロード
- **L38-43**: getMetrics - メトリクス取得

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

Rails側のコントローラ。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | csat_survey_responses_controller.rb | `app/controllers/api/v1/accounts/csat_survey_responses_controller.rb` | コントローラ |

**主要処理フロー**:
- **L15**: index - CSAT回答リスト
- **L17-20**: metrics - メトリクス集計
- **L22-25**: download - CSVダウンロード

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

```
CsatResponses.vue
    │
    ├─ CsatFilters (子コンポーネント)
    │      └─ @filter-change → onFilterChange()
    │             ├─ 状態更新 (from, to, userIds, inbox, team, rating)
    │             └─ getAllData()
    │                    ├─ csat/getMetrics dispatch
    │                    │      └─ CSATReportsAPI.getMetrics()
    │                    │             └─ GET /api/v1/.../csat_survey_responses/metrics
    │                    │
    │                    └─ getResponses()
    │                           └─ csat/get dispatch
    │                                  └─ CSATReportsAPI.get()
    │                                         └─ GET /api/v1/.../csat_survey_responses
    │
    ├─ CsatMetrics (子コンポーネント)
    │      └─ props: filters
    │
    ├─ CsatTable (子コンポーネント)
    │      └─ @page-change → onPageNumberChange()
    │             └─ getResponses()
    │
    └─ downloadReports()
           └─ csat/downloadCSATReports dispatch
                  └─ CSATReportsAPI.download()
                         └─ GET /api/v1/.../csat_survey_responses/download
```

### データフロー図

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

期間フィルタ   ───▶  CSATReportsAPI.get()    ───▶  CSAT回答テーブル
                            │
フィルタ条件   ───▶  CSATReportsAPI.getMetrics ───▶  CSATメトリクス
(agent,inbox等)             │                        (満足度、回答率)
                            │
ページ番号     ───▶  getResponses()           ───▶  ページング更新
                            │
ダウンロード   ───▶  CSATReportsAPI.download  ───▶  CSVファイル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CsatResponses.vue | `app/javascript/dashboard/routes/dashboard/settings/reports/CsatResponses.vue` | ソース | メイン画面コンポーネント |
| CsatMetrics.vue | `app/javascript/dashboard/routes/dashboard/settings/reports/components/CsatMetrics.vue` | ソース | メトリクス表示コンポーネント |
| CsatTable.vue | `app/javascript/dashboard/routes/dashboard/settings/reports/components/CsatTable.vue` | ソース | テーブル表示コンポーネント |
| CsatFilters.vue | `app/javascript/dashboard/routes/dashboard/settings/reports/components/Csat/CsatFilters.vue` | ソース | フィルタコンポーネント |
| ReportHeader.vue | `app/javascript/dashboard/routes/dashboard/settings/reports/components/ReportHeader.vue` | ソース | ヘッダーコンポーネント |
| reports.routes.js | `app/javascript/dashboard/routes/dashboard/settings/reports/reports.routes.js` | 設定 | ルーティング定義 |
| csat.js (store) | `app/javascript/dashboard/store/modules/csat.js` | ソース | Vuexストアモジュール |
| csatReports.js (api) | `app/javascript/dashboard/api/csatReports.js` | ソース | APIクライアント |
| csat_survey_responses_controller.rb | `app/controllers/api/v1/accounts/csat_survey_responses_controller.rb` | ソース | Railsコントローラ |
| csat_survey_response.rb | `app/models/csat_survey_response.rb` | ソース | モデル定義 |
