# 画面設計書 29-会話レポート画面

## 概要

本ドキュメントは、Chatwootの会話レポート画面の設計仕様を記述したものである。

### 本画面の処理概要

会話レポート画面は、会話に関する各種統計レポートを表示し、期間やグルーピング条件を指定してデータを分析する機能を提供する画面である。

**業務上の目的・背景**：カスタマーサポートのパフォーマンス分析において、会話の量と質を定量的に把握することは重要である。本画面により、マネージャーは会話数、メッセージ数、初回応答時間、解決時間などの主要指標を期間別・グループ別に分析し、チームの改善ポイントを特定することができる。

**画面へのアクセス方法**：ダッシュボードのサイドバーから「レポート」メニューを選択し、「会話」サブメニューをクリックすることでアクセスする。URLは `/app/accounts/:accountId/reports/conversation` の形式となる。

**主要な操作・処理内容**：
1. 会話統計のサマリー表示
2. 各指標のチャート表示
3. 日付範囲フィルタの設定
4. グループ化期間（日/週/月/年）の選択
5. 営業時間ベースの計算切り替え
6. レポートのCSVダウンロード

**画面遷移**：レポート概要画面、他のレポート画面から遷移可能。

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 109 | レポートV2 | 主機能 | 会話に関するレポート表示 |
| 115 | 会話分析 | 補助機能 | 会話の詳細分析 |
| 116 | サマリーレポート | 補助機能 | 要約統計の表示 |

## 画面種別

レポート

## URL/ルーティング

| パス | ルート名 | 説明 |
|------|----------|------|
| `/app/accounts/:accountId/reports/conversation` | reports_conversation | 会話レポート画面 |

## 入出力項目

### 入力項目（フィルタ）

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| from | 日付 | 必須 | 集計開始日（UNIXタイムスタンプ） |
| to | 日付 | 必須 | 集計終了日（UNIXタイムスタンプ） |
| groupBy | 文字列 | 必須 | グループ化期間（day, week, month, year） |
| businessHours | 真偽値 | 任意 | 営業時間ベースで計算するか |

### 出力項目

| 項目名 | 型 | 説明 |
|--------|-----|------|
| summary | Object | サマリー統計データ |
| chartData | Object | 各指標のチャートデータ |

## 表示項目

### ヘッダー

| 項目名 | 説明 |
|--------|------|
| タイトル | 「会話レポート」（i18nキー: REPORT.HEADER） |
| ダウンロードボタン | CSVダウンロード |

### フィルタセクション

| 項目名 | 説明 |
|--------|------|
| 日付範囲ピッカー | 開始日と終了日を選択 |
| グループ化セレクタ | 日/週/月/年を選択 |
| 営業時間トグル | 営業時間ベースの計算を切り替え |

### レポート指標

| 指標名 | 説明 | キー |
|--------|------|------|
| 会話数 | 期間内の会話総数 | conversations_count |
| 受信メッセージ数 | 顧客からのメッセージ数 | incoming_messages_count |
| 送信メッセージ数 | エージェントからのメッセージ数 | outgoing_messages_count |
| 平均初回応答時間 | 最初のメッセージへの応答時間 | avg_first_response_time |
| 平均解決時間 | 会話開始から解決までの時間 | avg_resolution_time |
| 解決数 | 解決された会話数 | resolutions_count |
| 返信時間 | メッセージへの返信時間 | reply_time |

## イベント仕様

### 1-画面初期表示

画面表示後、フィルタ変更イベントが発火してデータを取得する。

**処理フロー**:
1. `ReportFilterSelector`がデフォルト日付範囲で初期化
2. `onFilterChange`イベントが発火
3. `fetchAllData`を実行

### 2-フィルタ変更

日付範囲、グループ化、営業時間設定を変更する。

**処理フロー**:
1. `onFilterChange`を実行
2. `from`, `to`, `groupBy`, `businessHours`を更新
3. `fetchAllData`で全データを再取得
4. トラッキングイベント送信

### 3-サマリー取得

会話統計のサマリーを取得する。

**処理フロー**:
1. `fetchAccountSummary`を実行
2. `getRequestPayload`でパラメータ構築
3. Vuexアクション`fetchAccountSummary`をディスパッチ

### 4-チャートデータ取得

各指標のチャートデータを取得する。

**処理フロー**:
1. `fetchChartData`を実行
2. 7つの指標それぞれに対して`fetchAccountReport`をディスパッチ
3. 各指標のチャートデータをストアに保存

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

CSVレポートをダウンロードする。

**処理フロー**:
1. `downloadConversationReports`を実行
2. `generateFileName`でファイル名生成
3. Vuexアクション`downloadConversationsSummaryReports`をディスパッチ

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| サマリー取得 | conversations, messages | SELECT | 集計クエリ実行 |
| チャートデータ取得 | conversations, messages | SELECT | 時系列集計クエリ実行 |

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

本画面は参照のみで更新処理なし。

#### conversations

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | created_at, resolved_at, first_reply_created_at | 期間条件、アカウント条件 | 統計集計用 |

#### messages

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | created_at, message_type | 期間条件、会話条件 | メッセージ数集計用 |

## メッセージ仕様

| 種別 | コード | メッセージ | 表示条件 |
|------|--------|-----------|----------|
| エラー | REPORT.SUMMARY_FETCHING_FAILED | サマリーの取得に失敗しました | サマリー取得エラー時 |
| エラー | REPORT.DATA_FETCHING_FAILED | データの取得に失敗しました | チャートデータ取得エラー時 |
| ボタン | REPORT.DOWNLOAD_CONVERSATION_REPORTS | 会話レポートをダウンロード | ダウンロードボタンラベル |

## 例外処理

| 例外条件 | 処理内容 |
|----------|---------|
| サマリー取得失敗 | アラートメッセージを表示 |
| チャートデータ取得失敗 | アラートメッセージを表示 |
| 権限不足 | 画面へのアクセスがブロック |

## 備考

- グループ化オプションは日付範囲によって動的に変更される（短期間では日単位、長期間では週/月/年）
- 営業時間ベースの計算はアカウントの営業時間設定に基づく
- タイムゾーンオフセットが自動的に計算されてAPIに送信される
- ダウンロードファイル名には日付とbusinessHours設定が含まれる

---

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

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

### 推奨読解順序

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

まず、レポートのデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | reports.js (api) | `app/javascript/dashboard/api/reports.js` | getReports, getSummaryメソッド |

**読解のコツ**: APIメソッドのパラメータを見ることで、どのようなフィルタ条件が使えるか把握できる。

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

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

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

**主要処理フロー**:
1. **行11-19**: REPORTS_KEYSで7つの指標を定義
2. **行29-35**: dataで状態管理（from, to, groupBy, businessHours）
3. **行37-41**: `fetchAllData`でサマリーとチャートを取得
4. **行42-47**: `fetchAccountSummary`でサマリー取得
5. **行49-68**: `fetchChartData`で各指標のチャートデータ取得
6. **行79-92**: `downloadConversationReports`でダウンロード処理
7. **行93-104**: `onFilterChange`でフィルタ変更処理

#### Step 3: フィルタコンポーネントを理解する

フィルタUIの実装を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FilterSelector.vue | `app/javascript/dashboard/routes/dashboard/settings/reports/components/FilterSelector.vue` | フィルタUIの実装 |

#### Step 4: レポートコンテナを理解する

チャート表示の実装を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ReportContainer.vue | `app/javascript/dashboard/routes/dashboard/settings/reports/ReportContainer.vue` | チャート表示コンテナ |

#### Step 5: APIレイヤーを理解する

バックエンドとの通信処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | reports.js | `app/javascript/dashboard/api/reports.js` | getReports, getSummary, getConversationsSummaryReportsメソッド |

**主要処理フロー**:
- **行11-32**: `getReports`でチャートデータ取得
- **行35-47**: `getSummary`でサマリー取得
- **行64-68**: `getConversationsSummaryReports`でCSVダウンロード

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

```
Index.vue (View層)
    │
    ├─ ReportHeader
    │      └─ ダウンロードボタン
    │             └─ downloadConversationReports
    │                    └─ store.dispatch('downloadConversationsSummaryReports')
    │
    ├─ ReportFilterSelector
    │      └─ @filter-change="onFilterChange"
    │             └─ fetchAllData
    │                    ├─ fetchAccountSummary
    │                    │      └─ store.dispatch('fetchAccountSummary')
    │                    │             └─ ReportsAPI.getSummary()
    │                    │
    │                    └─ fetchChartData (7指標)
    │                           └─ store.dispatch('fetchAccountReport')
    │                                  └─ ReportsAPI.getReports()
    │
    └─ ReportContainer
           └─ チャート表示
```

### データフロー図

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

日付範囲 ─────────────────▶ onFilterChange
グループ化                       │
営業時間                         ▼
                          fetchAllData
                                │
                                ├─ fetchAccountSummary ───▶ サマリーカード
                                │      └─ ReportsAPI.getSummary()
                                │
                                └─ fetchChartData ───▶ 各指標チャート
                                       └─ ReportsAPI.getReports() x7
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Index.vue | `app/javascript/dashboard/routes/dashboard/settings/reports/Index.vue` | ソース | メイン画面コンポーネント |
| ReportHeader.vue | `app/javascript/dashboard/routes/dashboard/settings/reports/components/ReportHeader.vue` | ソース | レポートヘッダー |
| FilterSelector.vue | `app/javascript/dashboard/routes/dashboard/settings/reports/components/FilterSelector.vue` | ソース | フィルタセレクタ |
| ReportContainer.vue | `app/javascript/dashboard/routes/dashboard/settings/reports/ReportContainer.vue` | ソース | レポートコンテナ |
| reports.js (api) | `app/javascript/dashboard/api/reports.js` | ソース | レポートAPI |
| constants.js | `app/javascript/dashboard/routes/dashboard/settings/reports/constants.js` | ソース | 定数定義（GROUP_BY_FILTER等） |
| downloadHelper.js | `app/javascript/dashboard/helper/downloadHelper.js` | ソース | ダウンロードヘルパー |
| events.js | `app/javascript/dashboard/helper/AnalyticsHelper/events.js` | ソース | トラッキングイベント定義 |
