# 機能設計書 119-トラフィック分析

## 概要

本ドキュメントは、Chatwootのトラフィック分析機能の設計を記述する。この機能は、会話トラフィックのヒートマップデータを生成し、時間帯別・日別の問い合わせ傾向を可視化するレポーティング機能である。

### 本機能の処理概要

トラフィック分析機能は、指定期間内の会話数を時間帯（Hour）と日付でグループ化し、ヒートマップ形式のデータを生成する機能である。これにより、どの曜日のどの時間帯に問い合わせが集中するかを視覚的に把握でき、シフト計画の最適化に活用できる。

**業務上の目的・背景**：カスタマーサポート業務では、問い合わせの時間帯別傾向を把握することが重要である。トラフィック分析により、ピーク時間帯の特定、曜日別の傾向分析、シーズン性の把握などが可能となり、適切な人員配置やシフトスケジュールの策定に活用できる。

**機能の利用シーン**：
- シフトスケジュールの最適化
- ピーク時間帯の特定とリソース事前配置
- 曜日別トラフィックパターンの分析
- CSV出力による詳細分析

**主要な処理内容**：
1. 指定されたタイムゾーンオフセットに基づいて日時を変換
2. 会話数を時間帯別・日別にグループ化（group_by_periodで1時間単位）
3. ヒートマップ形式のデータ構造に変換
4. CSV形式でレポートデータを出力

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

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | トラフィック分析API | 主機能 | 会話トラフィック統計のCSV取得 |

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| timezone_offset | Float | No | タイムゾーンオフセット（デフォルト: 0） | 数値 |
| days_before | Integer | No | 何日前からのデータを取得するか（デフォルト: 6日前） | 正の整数 |

### 入力データソース

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

## 出力仕様

### 出力データ

CSV形式で、以下の構造のヒートマップデータを出力。

| 行 | 内容 |
|-----|------|
| 1行目 | タイムゾーン情報 |
| 2行目 | ヘッダー行（'Start of the hour', 日付1, 日付2, ...） |
| 3行目以降 | 時間帯行（'00:00', 値1, 値2, ...）〜（'23:00', 値n, 値m, ...） |

**出力例**：
```
Timezone, UTC
Start of the hour, 2024-01-01, 2024-01-02, 2024-01-03
00:00, 5, 3, 8
01:00, 2, 1, 4
...
23:00, 10, 7, 12
```

### 出力先

- CSV形式：ダウンロード用ファイル（`conversation_traffic_reports.csv`）

## 処理フロー

### 処理シーケンス

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

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

3. ヒートマップデータ生成
   └─ HeatmapHelper#generate_conversations_heatmap_report を呼び出し

4. タイムゾーン調整
   └─ タイムゾーンオフセットに基づいて現在日時を調整

5. 会話データ取得
   └─ ReportBuilder でgroup_by='hour'で会話数を取得

6. データ変換
   └─ 生データをヒートマップ形式（日付×時間のマトリクス）に変換

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

### フローチャート

```mermaid
flowchart TD
    A[API呼び出し] --> B{認可チェック}
    B -->|権限あり| C[generate_conversations_heatmap_report]
    B -->|権限なし| Z[403 Forbidden]
    C --> D[generate_heatmap_data_for_timezone]
    D --> E[タイムゾーン調整]
    E --> F[ReportBuilder group_by: hour]
    F --> G[transform_data]
    G --> H[group_traffic_data]
    H --> I[マトリクス形式に変換]
    I --> J[CSV形式でレンダリング]
    J --> K[レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-119-01 | デフォルト期間 | days_beforeが指定されない場合は6日前から | days_before未指定時 |
| BR-119-02 | タイムゾーン対応 | 指定されたタイムゾーンオフセットで日時を変換 | 常時 |
| BR-119-03 | 1時間単位グループ化 | group_by='hour'で時間帯別に集計 | 常時 |
| BR-119-04 | マトリクス形式 | 日付を列、時間帯を行とするマトリクス形式で出力 | 常時 |

### 計算ロジック

**期間の計算**：
```ruby
since_timestamp = (timezone_today - days_before.days).to_i.to_s
until_timestamp = timezone_today.to_i.to_s
```

**時間帯別集計**：
```ruby
V2::ReportBuilder.new(account, {
  type: :account,
  group_by: 'hour',
  metric: 'conversations_count'
}).build
```

**ヒートマップ変換**：
- 日付（date）と時間（hour）でグループ化
- 各日付を列、各時間帯を行とするマトリクスに変換

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 会話数集計 | conversations | SELECT | 時間帯別・日別に会話数をカウント |

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

#### conversations

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 403 | Forbidden | 管理者権限がない場合 | 権限のあるユーザーでログイン |

### リトライ仕様

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

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

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

## パフォーマンス要件

- 1週間分のデータ（168時間分）でも迅速にレスポンスを返すこと
- group_by_periodライブラリによる効率的な集計が必要

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

- 管理者ロールのみがアクセス可能（ReportPolicyで制御）
- アカウント間のデータ分離はCurrent.accountスコープで担保

## 備考

- ヒートマップデータはフロントエンドで視覚化される想定
- タイムゾーンオフセットはクライアント側から送信される（ユーザーのローカルタイムゾーン）
- 24時間×日数分のマトリクスデータを生成

---

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

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

### 推奨読解順序

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

まず、出力されるヒートマップデータの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | conversation_traffic.erb | `app/views/api/v2/accounts/reports/conversation_traffic.erb` | CSV出力形式 |

**読解のコツ**: 出力は日付を列、時間帯を行とするマトリクス形式。各セルに該当時間帯の会話数が入る。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | reports_controller.rb | `app/controllers/api/v2/accounts/reports_controller.rb` | conversation_traffic（46-52行目） |

**主要処理フロー**:
1. **46-52行目**: `conversation_traffic`アクションでgenerate_conversations_heatmap_reportを呼び出し
2. **47行目**: @report_dataにヒートマップデータを格納
3. **48-49行目**: タイムゾーンを設定
4. **51行目**: CSVをレンダリング

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

ヒートマップデータ生成のヘルパーメソッドを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | heatmap_helper.rb | `app/helpers/api/v2/accounts/heatmap_helper.rb` | ヒートマップ生成ロジック |

**主要処理フロー**:
- **2-6行目**: generate_conversations_heatmap_reportでタイムゾーン用データ生成とグループ化
- **59-66行目**: generate_heatmap_data_for_timezoneでタイムゾーン調整と生データ取得
- **68-81行目**: generate_heatmap_dataでReportBuilderを使用して会話数を取得
- **83-94行目**: transform_dataで生データを{date, hour, value}形式に変換
- **10-57行目**: group_traffic_dataでマトリクス形式に変換

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

```
ReportsController#conversation_traffic
    │
    ├─ check_authorization
    │      └─ ReportPolicy#view?
    │
    ├─ HeatmapHelper#generate_conversations_heatmap_report
    │      │
    │      ├─ generate_heatmap_data_for_timezone
    │      │      │
    │      │      ├─ タイムゾーン計算
    │      │      │      └─ ActiveSupport::TimeZone[offset]
    │      │      │
    │      │      ├─ generate_heatmap_data
    │      │      │      │
    │      │      │      └─ V2::ReportBuilder.new(..., group_by: 'hour').build
    │      │      │
    │      │      └─ transform_data
    │      │             └─ { date, hour, value }
    │      │
    │      └─ group_traffic_data
    │             │
    │             ├─ 日付一覧を抽出・ソート
    │             │
    │             ├─ 時間帯でグループ化
    │             │
    │             └─ マトリクス形式に変換
    │                    [['Start of the hour', date1, date2, ...],
    │                     ['00:00', val1, val2, ...],
    │                     ...]
    │
    └─ generate_csv
           └─ render conversation_traffic.erb
```

### データフロー図

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

timezone_offset パラメータ ───▶ ActiveSupport::TimeZone ─────────┐
                                │                                 │
days_before パラメータ ────────▶ since_timestamp 計算 ────────────┤
                                                                  │
                              ┌───────────────────────────────────┘
                              ▼
                         V2::ReportBuilder
                              │
                              └─▶ .build (group_by: 'hour')
                                    │
                                    ▼
                              [{ timestamp: xxx, value: n }, ...]
                                    │
                                    ▼
                         transform_data
                              │
                              └─▶ [{ date: 'YYYY-MM-DD', hour: 0-23, value: n }, ...]
                                    │
                                    ▼
                         group_traffic_data
                              │
                              ├─▶ dates = [...].uniq.sort
                              │
                              └─▶ [['Start of the hour', ...dates],
                                   ['00:00', ...values_per_date],
                                   ['01:00', ...],
                                   ...]
                                    │
                                    ▼
                         CSV output (conversation_traffic_reports.csv)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| reports_controller.rb | `app/controllers/api/v2/accounts/reports_controller.rb` | コントローラー | APIエンドポイント |
| heatmap_helper.rb | `app/helpers/api/v2/accounts/heatmap_helper.rb` | ヘルパー | ヒートマップ生成ロジック |
| report_builder.rb | `app/builders/v2/report_builder.rb` | ビルダー | 会話数集計 |
| conversation_traffic.erb | `app/views/api/v2/accounts/reports/conversation_traffic.erb` | ビュー | CSV出力テンプレート |
| report_policy.rb | `app/policies/report_policy.rb` | ポリシー | 認可制御 |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（445行目） |
