# 画面設計書 21-連絡先詳細画面

## 概要

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

### 本画面の処理概要

連絡先詳細画面は、CRMシステムにおいて顧客との接点となる連絡先情報を詳細に表示・管理するための中核画面である。

**業務上の目的・背景**：営業担当者が顧客との商談や問い合わせ対応を行う際、連絡先の詳細情報（連絡先情報、所属取引先、関連商談、コミュニケーション履歴）を一元的に把握する必要がある。本画面により、顧客対応の品質向上と営業活動の効率化を実現する。

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

**主要な操作・処理内容**：
1. 連絡先の基本情報（氏名、役職、部署、連絡先情報）の確認
2. 所属取引先へのリンクからの取引先情報確認
3. 関連商談の一覧表示と詳細画面への遷移
4. 関連タスクの一覧表示と完了/未完了の切り替え
5. コメントの投稿と既存コメントの確認
6. メールを含むタイムラインでの活動履歴確認
7. vCard形式でのエクスポート
8. 編集・削除操作
9. 変更通知の購読/購読解除

**画面遷移**：
- 遷移元：連絡先一覧画面、取引先詳細画面、商談詳細画面、リード変換後
- 遷移先：連絡先編集フォーム、取引先詳細画面、商談詳細画面、商談新規作成フォーム、タスク新規作成フォーム

**権限による表示制御**：連絡先のアクセス権限（Public/Private/Shared）に基づき、閲覧・編集可能なユーザーが制限される。自分が作成した連絡先、自分に割り当てられた連絡先、共有設定された連絡先のみアクセス可能。

## 関連機能

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

## 画面種別

詳細画面

## URL/ルーティング

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

## 入出力項目

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|-----|------|------|
| id | Integer | 必須 | 連絡先ID |
| format | String | 任意 | レスポンスフォーマット（html/js/json/vcf） |

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

| 変数名 | 型 | 説明 |
|--------|-----|------|
| @contact | Contact | 連絡先オブジェクト |
| @stage | Array | 商談ステージ選択肢 |
| @comment | Comment | 新規コメント用オブジェクト |
| @timeline | Array | コメントとメールの時系列配列 |

## 表示項目

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

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| アバター | @contact.avatar | ユーザーアバター画像 |
| 取引先名 | @contact.account.name | 所属取引先（リンク） |
| 役職 | @contact.title | 役職 |
| 部署 | @contact.department | 部署名 |
| 住所 | @contact.business_address | 勤務先住所 |
| 電話番号 | @contact.phone | 電話番号（do_not_callの場合は取り消し線） |
| 携帯電話 | @contact.mobile | 携帯電話番号 |
| FAX | @contact.fax | FAX番号 |
| メールアドレス | @contact.email | メインメールアドレス |
| 代替メール | @contact.alt_email | 代替メールアドレス |
| ブログ | @contact.blog | ブログURL |
| Twitter | @contact.twitter | Twitterアカウント |
| LinkedIn | @contact.linkedin | LinkedInプロフィール |
| Facebook | @contact.facebook | Facebookプロフィール |
| 担当者 | @contact.assignee.full_name | 担当ユーザー |
| リード | @contact.lead.name | 変換元リード（リンク） |
| キャンペーン | @contact.lead.campaign.name | 関連キャンペーン（リンク） |
| 背景情報 | @contact.background_info | 補足情報 |
| タグ | @contact.tags | 付与されたタグ |

### メインコンテンツ

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

## イベント仕様

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

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

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

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

### 3-コメント投稿

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

### 4-vCardエクスポート

- **トリガー**: vCard形式でダウンロード
- **処理**: 連絡先情報をvCard形式で生成し、ファイルとしてダウンロード
- **レスポンス**: `{連絡先氏名}.vcf`ファイル

### 5-購読/購読解除

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

### 6-商談新規作成

- **トリガー**: 商談追加ボタンをクリック
- **処理**: 商談新規作成フォームを表示（連絡先との紐付け済み）
- **遷移先**: 商談新規作成フォーム（モーダル/インライン）

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

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

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

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

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

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

#### contacts

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

#### versions

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

#### comments

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | commentable_type | 'Contact' | 関連モデル名 |
| INSERT | commentable_id | @contact.id | 関連レコードID |
| INSERT | user_id | current_user.id | 投稿者 |
| INSERT | comment | 入力値 | コメント本文 |

## メッセージ仕様

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

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| 連絡先が存在しない | 404エラー、一覧画面へリダイレクト |
| アクセス権限なし | CanCanによるアクセス拒否、一覧画面へリダイレクト |
| vCardエクスポートエラー | 標準エラー画面表示 |

## 備考

- do_not_callフラグがtrueの場合、電話番号は取り消し線で表示される
- タイムラインはコメントとメールを作成日時の降順で表示
- カスタムフィールドはサイドバーに動的に表示される
- Paper Trailによる変更履歴追跡が有効

---

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

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

### 推奨読解順序

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

まず、連絡先エンティティのデータ構造と関連を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | contact.rb | `app/models/entities/contact.rb` | Contactモデルの定義、関連（belongs_to/has_many）、バリデーション、スコープを確認 |
| 1-2 | comment.rb | `app/models/polymorphic/comment.rb` | ポリモーフィックなコメント関連を確認 |
| 1-3 | task.rb | `app/models/polymorphic/task.rb` | ポリモーフィックなタスク関連を確認 |

**読解のコツ**: Railsのアソシエーション（belongs_to, has_many, has_one :through）に注目し、どのテーブルが関連しているか把握する。`uses_user_permissions`、`acts_as_commentable`などのモジュールインクルードにも注目。

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

処理の起点となるコントローラーアクションを特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | contacts_controller.rb | `app/controllers/entities/contacts_controller.rb` | showアクション（25-32行目）の処理フローを確認 |
| 2-2 | entities_controller.rb | `app/controllers/entities_controller.rb` | 親クラスの共通処理（before_action、update_recently_viewed等）を確認 |

**主要処理フロー**:
1. **26行目**: `@stage = Setting.unroll(:opportunity_stage)` - 商談ステージ選択肢を取得
2. **27行目**: `@comment = Comment.new` - 新規コメント用オブジェクト生成
3. **28行目**: `@timeline = timeline(@contact)` - コメントとメールを時系列で取得
4. **30行目**: vCard形式でのレスポンス対応

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | show.html.haml | `app/views/contacts/show.html.haml` | メインテンプレートの構造、パーシャルの呼び出し |
| 3-2 | _title_bar.html.haml | `app/views/contacts/_title_bar.html.haml` | タイトルバーの編集・削除リンク |
| 3-3 | _sidebar_show.html.haml | `app/views/contacts/_sidebar_show.html.haml` | サイドバーの詳細情報表示 |

**主要処理フロー**:
- **9行目**: `render 'contacts/title_bar'` - タイトルバーをレンダリング
- **10行目**: `render 'contacts/sidebar_show'` - サイドバーをレンダリング
- **12行目**: `render "comments/new"` - コメントフォームをレンダリング
- **13行目**: `render partial: "shared/timeline"` - タイムラインをレンダリング
- **17行目**: `render partial: "tasks/tasks"` - タスク一覧をレンダリング
- **19行目**: `render partial: "opportunities/opportunities"` - 商談一覧をレンダリング

#### Step 4: 関連処理を理解する

購読、削除、vCardエクスポートなどの関連処理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | entities_controller.rb | `app/controllers/entities_controller.rb` | subscribe/unsubscribeアクション（41-61行目） |
| 4-2 | contact_helper.rb | `app/helpers/contact_helper.rb` | vcard_forヘルパーメソッド |

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

```
ContactsController#show
    │
    ├─ EntitiesController (before_action)
    │      ├─ set_current_tab
    │      ├─ set_view
    │      └─ load_and_authorize_resource (CanCan)
    │
    ├─ Contact.find (モデル取得)
    │      └─ User permissions check
    │
    ├─ Setting.unroll(:opportunity_stage)
    │
    ├─ Comment.new
    │
    ├─ timeline(@contact)
    │      ├─ @contact.comments
    │      └─ @contact.emails
    │
    ├─ update_recently_viewed (after_action)
    │      └─ Version.create (閲覧履歴)
    │
    └─ respond_with(@contact)
           ├─ 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
           │      ├─ opportunities/_opportunities.html.haml
           │      └─ versions/_versions.html.haml
           └─ format.vcf → vCard生成
```

### データフロー図

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

Request                                                  Response
/contacts/:id ────────▶ ContactsController#show
                              │
                              ├──▶ Contact.find(:id)
                              │         │
                              │         └──▶ [contacts]テーブル
                              │
                              ├──▶ timeline()
                              │         │
                              │         ├──▶ [comments]テーブル
                              │         └──▶ [emails]テーブル
                              │
                              ├──▶ update_recently_viewed
                              │         │
                              │         └──▶ [versions]テーブル INSERT
                              │
                              └──────────────────────────▶ HTML/VCF
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| contact.rb | `app/models/entities/contact.rb` | モデル | 連絡先エンティティの定義 |
| contacts_controller.rb | `app/controllers/entities/contacts_controller.rb` | コントローラ | 連絡先CRUD処理 |
| entities_controller.rb | `app/controllers/entities_controller.rb` | コントローラ | エンティティ共通処理 |
| show.html.haml | `app/views/contacts/show.html.haml` | テンプレート | 詳細画面メインビュー |
| _title_bar.html.haml | `app/views/contacts/_title_bar.html.haml` | テンプレート | タイトルバー部品 |
| _sidebar_show.html.haml | `app/views/contacts/_sidebar_show.html.haml` | テンプレート | サイドバー部品 |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（84-101行目） |
| contact_helper.rb | `app/helpers/contacts_helper.rb` | ヘルパー | vCard生成等のヘルパーメソッド |
