# 機能設計書 111-インボックス別レポート

## 概要

本ドキュメントは、Chatwootのインボックス別レポート機能の設計を記述する。この機能は、各インボックスのパフォーマンスメトリクスを集計・分析し、チャネル運用の効率化を支援するレポーティング機能である。

### 本機能の処理概要

インボックス別レポート機能は、アカウント内の各インボックス（チャネル）に対して、会話数、解決数、平均応答時間、平均解決時間などの主要指標を集計し、管理者が各チャネルのパフォーマンスを比較・分析できるようにする機能である。

**業務上の目的・背景**：カスタマーサポート業務において、複数のチャネル（メール、チャット、SNSなど）を運用している場合、各チャネルの対応品質やリソース配分を適切に管理する必要がある。インボックス別レポートにより、どのチャネルが最も負荷が高いか、どのチャネルの応答時間が遅いかなどを把握し、サポートリソースの最適化やSLA遵守のための施策立案に活用できる。

**機能の利用シーン**：
- 週次・月次のチャネル別パフォーマンスレビュー
- チャネル間の負荷バランス確認とエージェント配置の最適化
- 新規チャネル導入後の効果測定
- 特定期間のチャネル別KPI分析（CSV出力による詳細分析）

**主要な処理内容**：
1. 指定された期間内の各インボックスの会話数を集計
2. ReportingEventテーブルから解決数・平均応答時間・平均解決時間を算出
3. 営業時間ベースの計算オプションに対応
4. JSON形式またはCSV形式でレポートデータを出力

**関連システム・外部連携**：特になし（内部データの集計機能）

**権限による制御**：管理者（Administrator）ロールを持つユーザーのみがレポートを閲覧可能（ReportPolicy#view?で制御）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 33 | インボックスレポート画面 | 主機能 | インボックス別統計の表示 |
| 34 | インボックスレポート概要 | 主機能 | インボックスレポート概要一覧 |
| 35 | インボックスレポート詳細 | 主機能 | 特定インボックスの詳細レポート |

## 機能種別

データ集計・レポート出力

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| since | String | Yes | 集計開始日時（UNIXタイムスタンプ文字列） | 数値変換可能な文字列 |
| until | String | Yes | 集計終了日時（UNIXタイムスタンプ文字列） | 数値変換可能な文字列 |
| business_hours | Boolean | No | 営業時間ベースで計算するか | true/false |
| timezone_offset | Float | No | タイムゾーンオフセット | 数値 |

### 入力データソース

- HTTPリクエストパラメータ（API呼び出し時）
- Current.account（認証済みユーザーのアカウント情報）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | Integer | インボックスID |
| conversations_count | Integer | 期間内の会話数 |
| resolved_conversations_count | Integer | 期間内の解決会話数 |
| avg_first_response_time | Float | 平均初回応答時間（秒） |
| avg_resolution_time | Float | 平均解決時間（秒） |
| avg_reply_time | Float | 平均返信時間（秒） |

### 出力先

- JSON形式：API V2エンドポイント（`/api/v2/accounts/:account_id/reports/inboxes`）
- CSV形式：ダウンロード用ファイル（`inboxes_report.csv`）

## 処理フロー

### 処理シーケンス

```
1. API呼び出し（GET /api/v2/accounts/:account_id/reports/inboxes）
   └─ ReportsController#inboxes アクションが起動

2. 認可チェック
   └─ ReportPolicy#view? で管理者権限を確認

3. レポートデータ生成
   └─ ReportsHelper#generate_inboxes_report を呼び出し
       └─ InboxSummaryBuilder でデータを集計

4. 会話数の集計
   └─ Conversationテーブルから期間内・インボックス別に件数をグループ化

5. ReportingEventデータの集計
   └─ 解決数、平均応答時間、平均解決時間、平均返信時間を算出

6. インボックス一覧との結合
   └─ 各インボックスのIDと統計値をマッピング

7. CSV出力
   └─ レポートデータをCSV形式でレンダリング
```

### フローチャート

```mermaid
flowchart TD
    A[API呼び出し] --> B{認可チェック}
    B -->|権限あり| C[InboxSummaryBuilder初期化]
    B -->|権限なし| Z[403 Forbidden]
    C --> D[会話数を集計]
    D --> E[ReportingEventデータを集計]
    E --> F[インボックス別に統計を構築]
    F --> G[CSV形式でレンダリング]
    G --> H[レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-111-01 | 期間指定必須 | since/untilパラメータは必須 | 常時 |
| BR-111-02 | 営業時間計算 | business_hours=trueの場合、value_in_business_hoursカラムを使用 | business_hoursパラメータがtrue |
| BR-111-03 | 全インボックス対象 | アカウント内の全インボックスを対象に集計 | 常時 |

### 計算ロジック

**平均時間の計算**：
- 通常モード：`AVG(reporting_events.value)`
- 営業時間モード：`AVG(reporting_events.value_in_business_hours)`

**対象イベント種別**：
- 解決数：`name = 'conversation_resolved'`
- 初回応答時間：`name = 'first_response'`
- 返信時間：`name = 'reply_time'`

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 会話数集計 | conversations | SELECT | 期間内の会話をインボックス別にカウント |
| イベント集計 | reporting_events | SELECT | 各種イベントの平均値・件数を算出 |
| インボックス取得 | inboxes | SELECT | アカウント内の全インボックスを取得 |

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

#### conversations

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | COUNT(*) | created_at BETWEEN since AND until, GROUP BY inbox_id | 期間内会話数 |

#### reporting_events

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | AVG(value), COUNT(*) | created_at BETWEEN since AND until, GROUP BY inbox_id | イベント種別ごとに集計 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 403 | Forbidden | 管理者権限がない場合 | 権限のあるユーザーでログイン |
| 422 | Unprocessable Entity | パラメータ不正 | パラメータを確認して再リクエスト |

### リトライ仕様

該当なし（同期処理のため）

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

読み取り専用処理のため、トランザクション制御は不要。

## パフォーマンス要件

- インボックス数が多い場合（100以上）でも3秒以内にレスポンスを返すこと
- reporting_eventsテーブルには適切なインデックス（account_id, name, created_at）が設定されている

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

- 管理者ロールのみがアクセス可能（ReportPolicyで制御）
- アカウント間のデータ分離はCurrent.accountスコープで担保
- CSVダウンロード時もサーバーサイドで認証・認可チェックを実施

## 備考

- レポートデータはリアルタイムで集計されるため、大量データの場合はレスポンスに時間がかかる可能性がある
- CSV出力時は、時間値が人間可読形式（HH:MM:SS）に変換される（TimeFormatPresenter使用）

---

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

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

### 推奨読解順序

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

まず、レポートで使用されるデータモデルを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | reporting_event.rb | `app/models/reporting_event.rb` | レポートイベントのスキーマ（value, value_in_business_hours等） |

**読解のコツ**: ReportingEventモデルの`value`と`value_in_business_hours`の違いを理解することが重要。営業時間計算オプションによって使用するカラムが変わる。

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

APIコントローラーからの処理フローを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | reports_controller.rb | `app/controllers/api/v2/accounts/reports_controller.rb` | inboxesアクション（26-29行目） |

**主要処理フロー**:
1. **26-29行目**: `inboxes`アクションでgenerate_inboxes_reportを呼び出し、CSVレンダリング
2. **67-71行目**: `generate_csv`メソッドでCSVヘッダー設定とテンプレートレンダリング
3. **73-75行目**: `check_authorization`で権限チェック

#### Step 3: ヘルパー層を理解する

レポート生成のヘルパーメソッドを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | reports_helper.rb | `app/helpers/api/v2/accounts/reports_helper.rb` | generate_inboxes_report（14-24行目） |

**主要処理フロー**:
- **14-17行目**: InboxSummaryBuilderを初期化してbuildを呼び出し
- **19-23行目**: 各インボックスのデータを整形

#### Step 4: ビルダー層を理解する

実際のデータ集計ロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | base_summary_builder.rb | `app/builders/v2/reports/base_summary_builder.rb` | 共通の集計ロジック |
| 4-2 | inbox_summary_builder.rb | `app/builders/v2/reports/inbox_summary_builder.rb` | インボックス固有の集計ロジック |

**主要処理フロー**:
- **base_summary_builder.rb 11-14行目**: load_dataで会話数とイベントデータを読み込み
- **base_summary_builder.rb 16-34行目**: load_reporting_events_dataで各種メトリクスを一括集計
- **inbox_summary_builder.rb 19-21行目**: インボックスIDでグループ化して会話数を取得
- **inbox_summary_builder.rb 29-38行目**: インボックスごとの統計情報を構築

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

CSV出力形式を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | inboxes.csv.erb | `app/views/api/v2/accounts/reports/inboxes.csv.erb` | CSV出力テンプレート |

**主要処理フロー**:
- **1行目**: 期間情報をヘッダー行として出力
- **3-10行目**: カラムヘッダーを定義（i18n対応）
- **12-14行目**: レポートデータを行ごとに出力

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

```
ReportsController#inboxes
    │
    ├─ check_authorization
    │      └─ ReportPolicy#view?
    │
    ├─ ReportsHelper#generate_inboxes_report
    │      │
    │      ├─ InboxSummaryBuilder#new
    │      │
    │      └─ InboxSummaryBuilder#build
    │             │
    │             ├─ load_data
    │             │      ├─ fetch_conversations_count
    │             │      └─ load_reporting_events_data
    │             │
    │             └─ prepare_report
    │                    └─ build_inbox_stats
    │
    └─ generate_csv
           └─ render inboxes.csv.erb
```

### データフロー図

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

since/until パラメータ ───▶ DateRangeHelper#range ───────────┐
                                                              │
business_hours パラメータ ─▶ average_value_key 判定 ─────────┤
                                                              │
                              ┌──────────────────────────────┘
                              ▼
Current.account ────────────▶ InboxSummaryBuilder
                              │
                              ├─▶ conversations.group(:inbox_id).count ──┐
                              │                                          │
                              └─▶ reporting_events.group(inbox_id)       │
                                   .select(AVG, COUNT) ──────────────────┤
                                                                         │
                              ┌──────────────────────────────────────────┘
                              ▼
                         prepare_report
                              │
                              ▼
                         CSVSafe.generate_line ───▶ inboxes_report.csv
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| reports_controller.rb | `app/controllers/api/v2/accounts/reports_controller.rb` | コントローラー | APIエンドポイント |
| reports_helper.rb | `app/helpers/api/v2/accounts/reports_helper.rb` | ヘルパー | レポート生成ヘルパー |
| inbox_summary_builder.rb | `app/builders/v2/reports/inbox_summary_builder.rb` | ビルダー | インボックス集計ロジック |
| base_summary_builder.rb | `app/builders/v2/reports/base_summary_builder.rb` | ビルダー | 共通集計ロジック |
| date_range_helper.rb | `app/helpers/date_range_helper.rb` | ヘルパー | 日付範囲処理 |
| reporting_event.rb | `app/models/reporting_event.rb` | モデル | レポートイベントデータ |
| report_policy.rb | `app/policies/report_policy.rb` | ポリシー | 認可制御 |
| inboxes.csv.erb | `app/views/api/v2/accounts/reports/inboxes.csv.erb` | ビュー | CSV出力テンプレート |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（440行目） |
