# 機能設計書 109-レポートV2

## 概要

本ドキュメントは、Chatwootにおける包括的なレポーティングAPI（V2）について記述する。会話統計、エージェントパフォーマンス、インボックス統計、ラベル統計、チーム統計など、多角的な分析データを提供するAPIである。

### 本機能の処理概要

**業務上の目的・背景**：カスタマーサポートの品質管理と改善には、定量的なデータ分析が不可欠である。本機能は、会話数、応答時間、解決時間、解決数などの主要KPIを時系列データやサマリー形式で提供し、サービス品質のモニタリングと改善施策の立案を支援する。

**機能の利用シーン**：
- レポート画面で会話統計の時系列グラフを表示
- サマリーレポートで主要KPIを確認
- エージェント別、インボックス別、チーム別のパフォーマンス比較
- ボット（AI）のパフォーマンス分析
- 会話トラフィックのヒートマップ表示

**主要な処理内容**：
1. 時系列レポートの生成（index アクション）
2. サマリーレポートの生成（summary アクション）
3. エージェント/インボックス/ラベル/チーム別レポート（CSV出力）
4. ボットメトリクスの集計
5. 会話トラフィックの時間帯別集計

**関連システム・外部連携**：特になし（内部集計処理）

**権限による制御**：レポート閲覧には report:view 権限が必要。check_authorization によりアクセス制御される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 28 | レポート概要画面 | 参照画面 | ライブレポートの表示 |
| 29 | 会話レポート画面 | 主画面 | 会話に関するレポート表示 |

## 機能種別

集計処理 / 帳票出力

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| type | String | Yes | レポートタイプ（account, agent, inbox, label, team） | enum値のみ許可 |
| metric | String | No | メトリクスタイプ | conversations_count, avg_first_response_time 等 |
| since | Integer (Unix timestamp) | No | 期間開始（秒） | - |
| until | Integer (Unix timestamp) | No | 期間終了（秒） | - |
| id | Integer | No | 対象ID（エージェント、インボックス等） | - |
| group_by | String | No | グループ化単位（day, week, month, year） | - |
| business_hours | Boolean | No | 営業時間ベースで計算するか | - |
| timezone_offset | Float | No | タイムゾーンオフセット | - |

### 入力データソース

- 画面入力: レポート画面のフィルタ条件
- DBテーブル: conversations, reporting_events, messages 等

## 出力仕様

### 出力データ

#### 時系列レポート（index）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| data | Array | 時系列データ配列 [{timestamp, value}, ...] |

#### サマリーレポート（summary）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| conversations_count | Integer | 会話数 |
| incoming_messages_count | Integer | 受信メッセージ数 |
| outgoing_messages_count | Integer | 送信メッセージ数 |
| avg_first_response_time | Float | 平均初回応答時間（秒） |
| avg_resolution_time | Float | 平均解決時間（秒） |
| resolutions_count | Integer | 解決数 |
| reply_time | Float | 平均返信時間（秒） |
| previous | Object | 前期間のサマリー（比較用） |

#### ボットサマリー（bot_summary）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| bot_resolutions_count | Integer | ボットによる解決数 |
| bot_handoffs_count | Integer | ボットからのハンドオフ数 |

### 出力先

- 画面表示: JSON形式でAPIレスポンス
- ファイル: CSV形式でダウンロード（agents, inboxes, labels, teams）

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ APIエンドポイント: /api/v2/accounts/:account_id/reports

2. 認可チェック
   └─ authorize :report, :view?

3. パラメータ解析
   ├─ common_params: type, id, group_by, business_hours
   ├─ report_params: metric, since, until, timezone_offset
   └─ range: current期間, previous期間の計算

4. アクション別処理
   ├─ index: V2::Reports::Conversations::ReportBuilder.timeseries
   ├─ summary: V2::Reports::Conversations::MetricBuilder.summary
   ├─ bot_summary: V2::Reports::Conversations::MetricBuilder.bot_summary
   ├─ agents/inboxes/labels/teams: SummaryBuilder + CSV出力
   ├─ conversation_traffic: HeatmapHelper.heatmap
   └─ bot_metrics: V2::Reports::BotMetricsBuilder.metrics
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B[認可チェック]
    B --> C{アクション種別}
    C -->|index| D[ReportBuilder.timeseries]
    C -->|summary| E[MetricBuilder.summary]
    C -->|bot_summary| F[MetricBuilder.bot_summary]
    C -->|agents等| G[SummaryBuilder.build]
    C -->|conversation_traffic| H[HeatmapHelper]
    C -->|bot_metrics| I[BotMetricsBuilder]
    D --> J[JSON レスポンス]
    E --> K[current + previous サマリー]
    K --> J
    F --> J
    G --> L[CSV レスポンス]
    H --> L
    I --> J
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-109-01 | 営業時間計算 | business_hours=true の場合、営業時間ベースで時間を計算 | パラメータ指定時 |
| BR-109-02 | 期間比較 | summary では current 期間と previous 期間（同じ長さの直前期間）を比較 | summary アクション |
| BR-109-03 | グループ化 | day, week, month, year 単位でグループ化可能 | group_by パラメータ |

### 計算ロジック

前期間の計算:
```ruby
previous_since = params[:since].to_i - (params[:until].to_i - params[:since].to_i)
previous_until = params[:since]
```

営業時間ベース計算:
```ruby
average_value_key = business_hours ? :value_in_business_hours : :value
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| index | conversations | SELECT + COUNT | 会話数集計 |
| index | reporting_events | SELECT + AVG | 応答時間等の平均値 |
| summary | conversations | SELECT + COUNT | 各種カウント |
| summary | reporting_events | SELECT + AVG | 平均値計算 |
| agents/inboxes等 | reporting_events | SELECT + GROUP BY | グループ別集計 |

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

#### reporting_events

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT + AVG | value / value_in_business_hours | name = 'first_response' / 'reply_time' / 'conversation_resolved' | 平均時間計算 |
| SELECT + COUNT | * | name = 'conversation_resolved' | 解決数 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | Unauthorized | 未認証状態でアクセス | ログインページへリダイレクト |
| 403 | Forbidden | レポート閲覧権限なし | エラーメッセージ表示 |
| 422 | UnprocessableEntity | type パラメータなし | エラーレスポンス |

### リトライ仕様

特になし。同期処理のため即時エラー返却。

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

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

## パフォーマンス要件

- レスポンス時間: 1秒以内（通常データ量）
- インデックス: reporting_events.created_at, conversations.created_at

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

- 認証必須: Devise TokenAuthによる認証
- 認可: Punditによるレポート閲覧権限チェック
- アカウントスコープ: Current.account で他アカウントのデータにアクセス不可

## 備考

- ReportBuilder は metric パラメータに応じて適切なビルダークラスを選択
- MetricBuilder は複数のメトリクスを一括で計算
- SummaryBuilder は各種エンティティ（エージェント、インボックス等）の統計を生成

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | reporting_event.rb | `app/models/reporting_event.rb` | レポーティングイベントの構造 |

**読解のコツ**: `name` カラムで first_response, reply_time, conversation_resolved 等のイベントタイプを識別。`value` と `value_in_business_hours` で通常時間と営業時間ベースの値を保持。

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

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

**主要処理フロー**:
- **7-10行目**: `index` - 時系列レポート
- **13-15行目**: `summary` - サマリーレポート
- **17-19行目**: `bot_summary` - ボットサマリー
- **21-23行目**: `agents` - エージェントレポート
- **54-58行目**: `conversations` - 会話メトリクス
- **60-63行目**: `bot_metrics` - ボットメトリクス

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | report_builder.rb | `app/builders/v2/reports/conversations/report_builder.rb` | 時系列レポートビルダー |
| 3-2 | metric_builder.rb | `app/builders/v2/reports/conversations/metric_builder.rb` | メトリクスビルダー |
| 3-3 | base_summary_builder.rb | `app/builders/v2/reports/base_summary_builder.rb` | サマリービルダー基底クラス |

**主要処理フロー**:
- `ReportBuilder.timeseries` - 時系列データ生成
- `MetricBuilder.summary` - 7種類のメトリクスを一括計算
- `MetricBuilder.bot_summary` - ボット関連メトリクス

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | reports_helper.rb | `app/helpers/api/v2/accounts/reports_helper.rb` | レポートヘルパー |

**主要処理フロー**:
- **2-12行目**: `generate_agents_report` - エージェントレポート生成
- **14-24行目**: `generate_inboxes_report` - インボックスレポート生成
- **26-36行目**: `generate_teams_report` - チームレポート生成

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

```
Api::V2::Accounts::ReportsController
    │
    ├─ index
    │      └─ V2::Reports::Conversations::ReportBuilder.new.timeseries
    │             └─ builder_class(metric).new.timeseries
    │
    ├─ summary
    │      └─ build_summary(:summary)
    │             ├─ V2::Reports::Conversations::MetricBuilder.new.summary (current)
    │             └─ V2::Reports::Conversations::MetricBuilder.new.summary (previous)
    │
    ├─ bot_summary
    │      └─ build_summary(:bot_summary)
    │
    ├─ agents
    │      └─ generate_agents_report (ReportsHelper)
    │             └─ V2::Reports::AgentSummaryBuilder.new.build
    │
    ├─ inboxes
    │      └─ generate_inboxes_report (ReportsHelper)
    │             └─ V2::Reports::InboxSummaryBuilder.new.build
    │
    └─ bot_metrics
           └─ V2::Reports::BotMetricsBuilder.new.metrics
```

### データフロー図

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

パラメータ ─────────▶ ReportsController ─────────▶ JSON/CSV
(type, metric,              │
 since, until,              │
 group_by)                  ▼
                    ┌───────┴───────┐
                    │               │
              ReportBuilder    SummaryBuilder
                    │               │
                    ▼               ▼
              reporting_events  conversations
              (SELECT, AVG,     account_users
               GROUP BY)        inboxes, teams
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| reports_controller.rb | `app/controllers/api/v2/accounts/reports_controller.rb` | コントローラー | API エンドポイント |
| report_builder.rb | `app/builders/v2/reports/conversations/report_builder.rb` | ビルダー | 時系列レポート |
| metric_builder.rb | `app/builders/v2/reports/conversations/metric_builder.rb` | ビルダー | メトリクス集計 |
| base_summary_builder.rb | `app/builders/v2/reports/base_summary_builder.rb` | ビルダー | サマリー基底クラス |
| agent_summary_builder.rb | `app/builders/v2/reports/agent_summary_builder.rb` | ビルダー | エージェントサマリー |
| inbox_summary_builder.rb | `app/builders/v2/reports/inbox_summary_builder.rb` | ビルダー | インボックスサマリー |
| reports_helper.rb | `app/helpers/api/v2/accounts/reports_helper.rb` | ヘルパー | レポート生成ヘルパー |
| reporting_event.rb | `app/models/reporting_event.rb` | モデル | レポーティングイベント |
