# 画面設計書 25-商談詳細画面

## 概要

本ドキュメントは、Fat Free CRMシステムにおける商談詳細画面の設計を記述する。商談の詳細情報表示、関連連絡先・タスクの管理、コメント機能、タイムライン表示などの機能を提供する画面である。

### 本画面の処理概要

商談詳細画面は、営業パイプライン管理において個別の商談を詳細に分析・管理するための中核画面である。

**業務上の目的・背景**：営業担当者が商談の進捗状況、予想金額、成約確度、クローズ予定日などを詳細に把握し、適切な営業戦略を立案する必要がある。本画面により、商談の360度ビューを提供し、営業活動の精度向上を実現する。

**画面へのアクセス方法**：
- 商談一覧画面から商談名をクリック
- ダッシュボードの商談セクションから商談名をクリック
- 取引先詳細画面の関連商談セクションからリンクをクリック
- キャンペーン詳細画面の関連商談セクションからリンクをクリック
- 連絡先詳細画面の関連商談セクションからリンクをクリック

**主要な操作・処理内容**：
1. 商談の基本情報（名前、金額、確度、ステージ、クローズ日）の確認
2. 加重金額（金額×確度）の確認
3. 関連取引先・キャンペーンへのリンクからの情報確認
4. 関連連絡先の一覧表示と詳細画面への遷移
5. 関連タスクの一覧表示と完了/未完了の切り替え
6. コメントの投稿と既存コメントの確認
7. メールを含むタイムラインでの活動履歴確認
8. 編集・削除操作
9. 変更通知の購読/購読解除

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

**権限による表示制御**：商談のアクセス権限（Public/Private/Shared）に基づき、閲覧・編集可能なユーザーが制限される。

## 関連機能

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

## 画面種別

詳細画面

## URL/ルーティング

- URL: `/opportunities/:id`
- HTTPメソッド: GET
- コントローラ: `OpportunitiesController#show`
- フォーマット: HTML, JS, JSON

## 入出力項目

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|-----|------|------|
| id | Integer | 必須 | 商談ID |

### 出力データ（インスタンス変数）

| 変数名 | 型 | 説明 |
|--------|-----|------|
| @opportunity | Opportunity | 商談オブジェクト |
| @comment | Comment | 新規コメント用オブジェクト |
| @timeline | Array | コメントとメールの時系列配列 |

## 表示項目

### サイドバー情報パネル

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| ステージ | @opportunity.stage | 現在のステージ |
| クローズ日 | @opportunity.closes_on | 成約予定日 |
| 残り日数 | 計算値 | クローズ日までの日数（遅延時はマイナス表示） |
| 確度 | @opportunity.probability | 成約確度（%） |
| 金額 | @opportunity.amount | 商談金額 |
| 割引 | @opportunity.discount | 割引額（割引率も表示） |
| 加重金額 | @opportunity.weighted_amount | 金額×確度÷100 |
| 担当者 | @opportunity.assignee.full_name | 担当ユーザー |
| 取引先 | @opportunity.account.name | 関連取引先（リンク） |
| キャンペーン | @opportunity.campaign.name | 関連キャンペーン（リンク） |
| 背景情報 | @opportunity.background_info | 補足情報 |
| タグ | @opportunity.tags | 付与されたタグ |

### メインコンテンツ

| セクション | 説明 |
|-----------|------|
| タイトルバー | 商談名、編集・削除リンク、ビュー切替ボタン |
| コメント入力フォーム | 新規コメント作成フォーム |
| タイムライン | コメントとメールの時系列表示 |
| タスク一覧 | 関連タスクの表示と管理 |
| 連絡先一覧 | 関連連絡先の表示とリンク |
| バージョン履歴 | 変更履歴の表示 |

## イベント仕様

### 1-編集リンククリック

- **トリガー**: 「編集」リンクをクリック
- **処理**: Ajaxで編集フォームを取得し、画面上に展開
- **遷移先**: 同一画面内に編集フォーム表示

### 2-削除リンククリック

- **トリガー**: 「削除?」リンクをクリック
- **処理**: 確認ダイアログ表示後、削除処理実行
- **遷移先**: 商談一覧画面（`/opportunities`）

### 3-コメント投稿

- **トリガー**: コメントフォームで投稿ボタンをクリック
- **処理**: Ajax経由でコメントを保存し、タイムラインに追加
- **遷移先**: 同一画面（タイムライン更新）

### 4-購読/購読解除

- **トリガー**: 購読/購読解除リンクをクリック
- **処理**: Ajax経由で購読状態を切り替え
- **遷移先**: 同一画面（購読状態更新）

### 5-連絡先追加

- **トリガー**: 連絡先追加ボタンをクリック
- **処理**: 連絡先選択ポップアップまたは新規作成フォームを表示
- **遷移先**: 同一画面（連絡先一覧更新）

### 6-タスク完了/未完了切り替え

- **トリガー**: タスクのチェックボックスをクリック
- **処理**: Ajax経由でタスクの完了状態を切り替え
- **遷移先**: 同一画面（タスク状態更新）

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | versions | INSERT | 閲覧履歴記録 |
| コメント投稿 | comments | INSERT | コメントレコード追加 |
| 購読/購読解除 | opportunities | UPDATE | subscribed_users配列更新 |
| 削除ボタン押下 | opportunities | UPDATE | deleted_at設定（論理削除） |
| 削除ボタン押下 | campaigns | UPDATE | opportunities_count減算 |
| タスク完了 | tasks | UPDATE | completed_at, completed_by更新 |

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

#### opportunities

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | subscribed_users | current_user.idの追加/削除 | 購読状態管理 |
| UPDATE | deleted_at | 現在日時 | 論理削除 |

#### versions

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | item_type | 'Opportunity' | 対象モデル名 |
| INSERT | item_id | @opportunity.id | 対象レコードID |
| INSERT | event | 'view' | イベント種別 |
| INSERT | whodunnit | current_user.id | 操作ユーザー |

## メッセージ仕様

| 種別 | メッセージキー | 表示条件 |
|------|---------------|---------|
| 成功 | :msg_asset_deleted | 商談削除成功時 |
| エラー | :msg_asset_not_available | 権限なし/存在しない商談アクセス時 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| 商談が存在しない | 404エラー、一覧画面へリダイレクト |
| アクセス権限なし | CanCanによるアクセス拒否、一覧画面へリダイレクト |

## 備考

- 加重金額は（金額 - 割引）× 確度 / 100 で計算
- クローズ日超過時は「X days late」と警告表示
- タイムラインはコメントとメールを作成日時の降順で表示
- カスタムフィールドはサイドバーに動的に表示
- Paper Trailによる変更履歴追跡が有効

---

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

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

### 推奨読解順序

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

商談エンティティのデータ構造と関連を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | opportunity.rb | `app/models/entities/opportunity.rb` | 関連（belongs_to/has_many）、weighted_amount計算（103-105行目） |
| 1-2 | contact_opportunity.rb | `app/models/relationships/contact_opportunity.rb` | 商談-連絡先関連 |

**読解のコツ**: `weighted_amount`メソッド（103-105行目）で加重金額の計算ロジックを確認。

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

コントローラーのshowアクションを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | opportunities_controller.rb | `app/controllers/entities/opportunities_controller.rb` | showアクション（27-31行目） |
| 2-2 | entities_controller.rb | `app/controllers/entities_controller.rb` | timeline、update_recently_viewed |

**主要処理フロー**:
1. **28行目**: `@comment = Comment.new` - 新規コメント用オブジェクト生成
2. **29行目**: `@timeline = timeline(@opportunity)` - コメントとメールを時系列で取得

#### Step 3: ビューテンプレートを理解する

画面の構造と表示ロジックを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | show.html.haml | `app/views/opportunities/show.html.haml` | メインテンプレートの構造 |
| 3-2 | _title_bar.html.haml | `app/views/opportunities/_title_bar.html.haml` | タイトルバー |
| 3-3 | _sidebar_show.html.haml | `app/views/opportunities/_sidebar_show.html.haml` | サイドバー詳細情報 |

**主要処理フロー**:
- **9行目**: `render 'opportunities/title_bar'` - タイトルバー
- **10行目**: `render 'opportunities/sidebar_show'` - サイドバー
- **12行目**: `render "comments/new"` - コメントフォーム
- **17行目**: `render "tasks/tasks"` - タスク一覧
- **19行目**: `render "contacts/contacts"` - 連絡先一覧

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

```
OpportunitiesController#show
    │
    ├─ load_and_authorize_resource (CanCan)
    │      └─ Opportunity.find(params[:id])
    │
    ├─ Comment.new
    │
    ├─ timeline(@opportunity)
    │      ├─ @opportunity.comments
    │      └─ @opportunity.emails
    │
    ├─ update_recently_viewed (after_action)
    │      └─ Version.create (閲覧履歴)
    │
    └─ respond_with(@opportunity)
           └─ format.html → show.html.haml
                  ├─ _title_bar.html.haml
                  ├─ _sidebar_show.html.haml
                  ├─ comments/_new.html.haml
                  ├─ shared/_timeline.html.haml
                  ├─ tasks/_tasks.html.haml
                  ├─ contacts/_contacts.html.haml
                  └─ versions/_versions.html.haml
```

### データフロー図

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

Request
/opportunities/:id ────▶ OpportunitiesController#show
                              │
                              ├──▶ Opportunity.find(:id)
                              │         │
                              │         └──▶ [opportunities]テーブル
                              │
                              ├──▶ timeline()
                              │         │
                              │         ├──▶ [comments]テーブル
                              │         └──▶ [emails]テーブル
                              │
                              ├──▶ update_recently_viewed
                              │         │
                              │         └──▶ [versions]テーブル INSERT
                              │
                              └────────────────────────▶ HTML
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| opportunity.rb | `app/models/entities/opportunity.rb` | モデル | 商談エンティティ |
| opportunities_controller.rb | `app/controllers/entities/opportunities_controller.rb` | コントローラ | showアクション |
| show.html.haml | `app/views/opportunities/show.html.haml` | テンプレート | 詳細画面メインビュー |
| _title_bar.html.haml | `app/views/opportunities/_title_bar.html.haml` | テンプレート | タイトルバー |
| _sidebar_show.html.haml | `app/views/opportunities/_sidebar_show.html.haml` | テンプレート | サイドバー |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義 |
