# 画面設計書 12-キャンペーン詳細画面

## 概要

Fat Free CRM における特定のキャンペーンの詳細情報を表示し、関連するリード・商談・タスクを管理するための画面設計書である。

### 本画面の処理概要

本画面は、選択されたキャンペーンの詳細情報を表示し、そのキャンペーンに紐付くリード・商談・タスク・コメントを一元的に管理する画面である。

**業務上の目的・背景**：
マーケティング担当者がキャンペーンの詳細を確認し、そのキャンペーンから獲得したリードや発生した商談の状況を把握する必要がある。また、キャンペーンの目標（リード数、収益など）に対する実績を比較することで、キャンペーンの効果を測定し、今後のマーケティング戦略の改善に活用する。本画面を通じて、キャンペーンに関連するすべての活動を追跡し、チーム間でのコミュニケーション（コメント）も行える。

**画面へのアクセス方法**：
1. キャンペーン一覧画面でキャンペーン名をクリック
2. ダッシュボードやリード詳細画面などからキャンペーンリンクをクリック
3. URL直接入力: `/campaigns/:id`

**主要な操作・処理内容**：
1. キャンペーン基本情報の表示（名前、ステータス、期間、予算など）
2. 目標値と実績値の比較表示
3. 関連リードの一覧表示・管理
4. 関連商談の一覧表示・管理
5. 関連タスクの一覧表示・管理
6. タイムライン（コメント・メール）の表示
7. コメントの追加
8. キャンペーン情報の編集
9. キャンペーンの削除
10. CSV/XLS/RSS/ATOMでのエクスポート（リード情報）
11. 購読/購読解除（変更通知）
12. バージョン履歴の表示

**画面遷移**：
- 遷移元: キャンペーン一覧画面、ダッシュボード、リード詳細画面
- 遷移先: キャンペーン編集フォーム、リード詳細画面、リード新規作成、商談詳細画面、商談新規作成

**権限による表示制御**：
- 認証済みユーザーのみアクセス可能
- キャンペーンのアクセス権限（Public/Private/Shared）に基づいて表示・操作可否が決定
- 編集・削除は作成者または共有されたユーザーのみ可能

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 11 | キャンペーン詳細表示 | 主機能 | キャンペーン詳細、関連リード・商談、タイムライン表示 |
| 42 | コメント一覧表示 | 補助機能 | キャンペーンに紐付くコメント表示 |
| 43 | コメント作成 | 補助機能 | キャンペーンへのコメント追加 |
| 86 | 購読/購読解除 | 補助機能 | キャンペーンの変更通知購読/解除 |
| 14 | キャンペーン削除 | 遷移先機能 | 詳細画面からのキャンペーン削除 |
| 85 | バージョン履歴 | 補助機能 | キャンペーンの変更履歴追跡 |
| 22 | リード作成 | 遷移先機能 | キャンペーン画面からのリード作成 |
| 30 | 商談作成 | 遷移先機能 | キャンペーン画面からの商談作成 |

## 画面種別

詳細

## URL/ルーティング

| HTTPメソッド | URL | アクション | 説明 |
|-------------|-----|----------|------|
| GET | /campaigns/:id | show | 詳細表示 |
| GET | /campaigns/:id.csv | show | CSV形式でリードエクスポート |
| GET | /campaigns/:id.xls | show | XLS形式でリードエクスポート |
| GET | /campaigns/:id.rss | show | RSS形式でリードエクスポート |
| GET | /campaigns/:id.atom | show | ATOM形式でリードエクスポート |
| DELETE | /campaigns/:id | destroy | 削除 |
| POST | /campaigns/:id/subscribe | subscribe | 購読 |
| POST | /campaigns/:id/unsubscribe | unsubscribe | 購読解除 |
| PUT | /campaigns/:id/attach | attach | 関連エンティティの追加 |
| POST | /campaigns/:id/discard | discard | 関連エンティティの削除 |

## 入出力項目

### コメント入力

| 項目名 | 入力形式 | 必須 | 説明 |
|--------|---------|------|------|
| コメント本文 | テキストエリア | ○ | キャンペーンへのコメント |

## 表示項目

### キャンペーン基本情報（サイドバー）

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| 開始日 | date | キャンペーン開始日 |
| 終了日 | date | キャンペーン終了日 |
| ステータス | string | planned/started/on_hold/completed/called_off |
| 予算 | decimal | キャンペーン予算 |
| 背景情報 | text | キャンペーンの背景情報 |
| タグ | string | 付与されたタグ |

### 目標値（Targets）

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| 目標リード数 | integer | 獲得目標リード数 |
| 目標コンバージョン率 | float | 目標コンバージョン率（%） |
| 目標商談数 | integer | 計算値（リード数 * コンバージョン率） |
| 目標収益 | decimal | 目標収益額 |

### 実績値（Actual Performance）

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| 実績リード数 | integer | leads_count |
| 実績コンバージョン率 | float | 計算値（商談数/リード数*100） |
| 実績商談数 | integer | opportunities_count |
| 実績収益 | decimal | revenue |

### 関連リード一覧

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| リード名 | string | 氏名（リンク） |
| 会社名 | string | 所属会社 |
| ステータス | string | リードステータス |
| ソース | string | リード獲得元 |

### 関連商談一覧

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| 商談名 | string | 商談名（リンク） |
| ステージ | string | 商談ステージ |
| 金額 | decimal | 商談金額 |
| 確度 | integer | 受注確度 |
| クローズ予定日 | date | クローズ予定日 |

### タイムライン

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| コメント | text | コメント内容 |
| 作成者 | string | コメント作成者名 |
| 作成日時 | datetime | コメント作成日時 |
| メール | text | 関連メール（存在する場合） |

## イベント仕様

### 01-編集ボタン押下

「Edit」ボタンをクリックすると、Ajax通信でキャンペーン編集フォーム（_edit.html.haml）が展開される。

### 02-削除ボタン押下

「Delete」ボタンをクリックすると確認ダイアログが表示され、確認後にキャンペーンが論理削除され、一覧画面にリダイレクトする。

### 03-コメント投稿

コメントフォームに入力して送信すると、Ajax通信でコメントが保存され、タイムラインに追加される。

### 04-購読ボタン押下

「Subscribe」ボタンをクリックすると、現在のユーザーがsubscribed_usersに追加され、変更通知を受け取るようになる。

### 05-購読解除ボタン押下

「Unsubscribe」ボタンをクリックすると、現在のユーザーがsubscribed_usersから削除され、変更通知を受け取らなくなる。

### 06-リード追加

関連リードセクションで「Add Lead」をクリックすると、リード選択ポップアップが表示され、選択したリードがキャンペーンに紐付けられる。

### 07-商談追加

関連商談セクションで「Add Opportunity」をクリックすると、商談選択ポップアップが表示され、選択した商談がキャンペーンに紐付けられる。

### 08-リード詳細遷移

リード名リンクをクリックすると、該当リードの詳細画面に遷移する。

### 09-商談詳細遷移

商談名リンクをクリックすると、該当商談の詳細画面に遷移する。

### 10-エクスポート

各エクスポートリンク（CSV/XLS/RSS/ATOM）をクリックすると、キャンペーンに紐付くリード情報がエクスポートされる。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 詳細表示 | campaigns | SELECT | キャンペーン情報取得 |
| 詳細表示 | leads | SELECT | 関連リード取得 |
| 詳細表示 | opportunities | SELECT | 関連商談取得 |
| 詳細表示 | comments | SELECT | コメント取得 |
| 詳細表示 | versions | INSERT | 閲覧履歴記録 |
| コメント投稿 | comments | INSERT | コメント追加 |
| 削除 | campaigns | UPDATE | deleted_at への論理削除 |
| 購読 | campaigns | UPDATE | subscribed_users 配列更新 |
| 購読解除 | campaigns | UPDATE | subscribed_users 配列更新 |
| リード追加 | leads | UPDATE | campaign_id 更新 |
| 商談追加 | opportunities | UPDATE | campaign_id 更新 |

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

#### campaigns

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | id = :id | 詳細情報取得 |
| UPDATE (削除時) | deleted_at | 現在日時 | 論理削除 |
| UPDATE (購読時) | subscribed_users | 配列に current_user.id 追加 | serialized array |
| UPDATE (購読解除時) | subscribed_users | 配列から current_user.id 削除 | serialized array |

#### comments

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | commentable_type='Campaign', commentable_id=:id | ポリモーフィック |
| INSERT | commentable_type | 'Campaign' | |
| INSERT | commentable_id | キャンペーンID | |
| INSERT | comment | コメント本文 | |
| INSERT | user_id | current_user.id | |

#### versions

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT (閲覧時) | item_type | 'Campaign' | |
| INSERT (閲覧時) | item_id | キャンペーンID | |
| INSERT (閲覧時) | event | 'view' | |
| INSERT (閲覧時) | whodunnit | current_user.id | |

## メッセージ仕様

| メッセージ種別 | メッセージコード | 表示内容 | 表示条件 |
|--------------|----------------|---------|---------|
| 成功 | msg_asset_deleted | "#{name} has been deleted." | 削除成功時 |
| 成功 | - | コメント追加後のタイムライン更新 | コメント投稿成功時 |

## 例外処理

| 例外ケース | 処理内容 | 表示 |
|-----------|---------|------|
| 認証エラー | ログイン画面にリダイレクト | Deviseのデフォルトメッセージ |
| 権限エラー | 403エラー | アクセス権限がありません |
| データ未存在 | 404エラー | 該当するキャンペーンが見つかりません |

## 備考

- 目標商談数は target_leads * target_conversion / 100 で計算
- 実績コンバージョン率は opportunities_count / leads_count * 100 で計算
- タイムラインはコメントとメールを作成日時の降順でマージして表示
- paper_trail により詳細画面アクセス時にviewイベントが記録される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | campaign.rb | `app/models/entities/campaign.rb` | キャンペーンの関連定義（has_many :leads, has_many :opportunities）を確認 |
| 1-2 | campaign.rb | `app/models/entities/campaign.rb` | attach!, discard! メソッドの実装（78-99行目） |

**読解のコツ**: `belongs_to :user` でオーナー、`has_many :leads` で1対多関連、`serialize :subscribed_users` で購読ユーザー配列の管理方法を理解する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | campaigns_controller.rb | `app/controllers/entities/campaigns_controller.rb` | showアクション（30-63行目） |

**主要処理フロー**:
1. **32-35行目**: HTML形式の場合、商談ステージ設定、コメントオブジェクト、タイムライン取得
2. **44-51行目**: XLS/CSV形式の場合、リード一覧をエクスポート
3. **53-61行目**: RSS/ATOM形式の場合、リードをフィード出力

#### Step 3: ビューを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | show.html.haml | `app/views/campaigns/show.html.haml` | メインテンプレート構成 |
| 3-2 | _sidebar_show.html.haml | `app/views/campaigns/_sidebar_show.html.haml` | サイドバー（目標・実績表示） |
| 3-3 | _title_bar.html.haml | `app/views/campaigns/_title_bar.html.haml` | タイトルバー |

**主要処理フロー**:
- **9-10行目（show.html.haml）**: タイトルバーとサイドバーのレンダリング
- **12-13行目**: コメント入力フォームとタイムライン表示
- **17-23行目**: タスク、リード、商談、バージョン履歴のセクション

#### Step 4: サイドバーの目標・実績計算を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | _sidebar_show.html.haml | `app/views/campaigns/_sidebar_show.html.haml` | 目標値と実績値の計算ロジック |

**主要処理フロー**:
- **35-40行目**: 目標商談数の計算（target_leads * target_conversion / 100）
- **60-66行目**: 実績コンバージョン率の計算（opportunities_count * 100 / leads_count）

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

```
[HTTP Request: GET /campaigns/:id]
    │
    ├─ routes.rb (64行目)
    │      └─ CampaignsController#show
    │
    ├─ CampaignsController#show (30-63行目)
    │      ├─ @campaign (CanCanCanによるロード)
    │      ├─ @stage = Setting.unroll(:opportunity_stage)
    │      ├─ @comment = Comment.new
    │      └─ @timeline = timeline(@campaign)
    │             └─ (comments + emails).sort
    │
    └─ campaigns/show.html.haml
           ├─ campaigns/_title_bar.html.haml
           ├─ campaigns/_sidebar_show.html.haml
           │      ├─ キャンペーンサマリー
           │      ├─ 目標値（Targets）
           │      └─ 実績値（Actual Performance）
           ├─ comments/_new.html.haml
           ├─ shared/_timeline.html.haml (collection)
           ├─ tasks/_tasks.html.haml
           ├─ leads/_leads.html.haml
           ├─ opportunities/_opportunities.html.haml
           └─ versions/_versions.html.haml
```

### データフロー図

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

HTTPリクエスト ───▶ ルーティング ───▶ campaigns/show.html.haml
(GET /campaigns/:id)        │
                           ▼
                    CampaignsController#show
                           │
                    ┌──────┼──────┐
                    ▼      ▼      ▼
              campaigns  leads  opportunities
                 DB       DB       DB
                    │      │      │
                    └──────┼──────┘
                           ▼
                    @campaign (詳細)
                    @leads (関連リード)
                    @opportunities (関連商談)
                    @timeline (コメント+メール)
                           │
                           ▼
                    ビューレンダリング ───▶ HTML/CSV/XLS/RSS/ATOM
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| campaign.rb | `app/models/entities/campaign.rb` | モデル | キャンペーンのデータモデル定義 |
| campaigns_controller.rb | `app/controllers/entities/campaigns_controller.rb` | コントローラー | showアクション |
| entities_controller.rb | `app/controllers/entities_controller.rb` | コントローラー | attach, discard, subscribe等の共通処理 |
| show.html.haml | `app/views/campaigns/show.html.haml` | ビュー | 詳細画面メインテンプレート |
| _sidebar_show.html.haml | `app/views/campaigns/_sidebar_show.html.haml` | ビュー | サイドバー（目標・実績） |
| _title_bar.html.haml | `app/views/campaigns/_title_bar.html.haml` | ビュー | タイトルバー |
| _leads.html.haml | `app/views/leads/_leads.html.haml` | ビュー | 関連リード一覧パーシャル |
| _opportunities.html.haml | `app/views/opportunities/_opportunities.html.haml` | ビュー | 関連商談一覧パーシャル |
| _tasks.html.haml | `app/views/tasks/_tasks.html.haml` | ビュー | 関連タスク一覧パーシャル |
| _timeline.html.haml | `app/views/shared/_timeline.html.haml` | ビュー | タイムラインパーシャル |
| _new.html.haml | `app/views/comments/_new.html.haml` | ビュー | コメント入力フォーム |
| routes.rb | `config/routes.rb` | 設定 | URLルーティング定義 |
