# 画面設計書 20-連絡先一覧画面

## 概要

Fat Free CRM における連絡先（Contact）の一覧を表示・管理するための画面設計書である。

### 本画面の処理概要

本画面は、システムに登録された連絡先を一覧形式で表示し、検索・フィルタリング・ページネーションによる効率的な連絡先管理を提供する画面である。

**業務上の目的・背景**：
営業活動において、連絡先は顧客との接点となる重要な情報資産である。連絡先一覧画面を通じて、担当者は顧客情報を素早く検索・確認し、適切なフォローアップ活動を行う。また、連絡先は取引先（Account）に紐付けられ、商談（Opportunity）との関連付けも管理される。リードから変換された連絡先は、変換元リードへの参照を保持する。

**画面へのアクセス方法**：
1. メインナビゲーションの「Contacts」メニューをクリック
2. URL直接入力: `/contacts`

**主要な操作・処理内容**：
1. 連絡先の一覧表示（ページネーション付き）
2. フリーテキスト検索（氏名、メール、電話）
3. 高度な検索（Ransack）
4. 連絡先の新規作成
5. 連絡先の編集
6. 連絡先の削除
7. 表示順序・表示形式の変更
8. 1ページあたりの表示件数変更
9. Excel/CSV形式でのエクスポート

**画面遷移**：
- 遷移元: ダッシュボード、他の一覧画面
- 遷移先: 連絡先詳細画面、連絡先新規作成フォーム、連絡先編集フォーム

**権限による表示制御**：
- 認証済みユーザーのみアクセス可能
- 連絡先のアクセス権限（Public/Private/Shared）に基づいて表示対象が決定

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 26 | 連絡先一覧表示 | 主機能 | 連絡先のページング表示、検索、フィルター |
| 82 | 検索 | 補助機能 | フリーテキスト検索、高度な検索 |
| 87 | エクスポート | 補助機能 | Excel/CSV形式でのデータエクスポート |
| 28 | 連絡先作成 | 遷移先機能 | 一覧画面から新規作成フォームを展開 |

## 画面種別

一覧

## URL/ルーティング

| HTTPメソッド | URL | アクション | 説明 |
|-------------|-----|----------|------|
| GET | /contacts | index | 一覧表示 |
| GET | /contacts.xls | index | Excel形式エクスポート |
| GET | /contacts.csv | index | CSV形式エクスポート |
| GET | /contacts/advanced_search | advanced_search | 高度な検索 |
| POST | /contacts/filter | filter | フィルター適用 |
| GET | /contacts/options | options | 表示オプション |
| GET | /contacts/redraw | redraw | 再描画 |
| GET/POST | /contacts/auto_complete | auto_complete | オートコンプリート |

## 入出力項目

### 検索入力

| 項目名 | 入力形式 | 必須 | 説明 |
|--------|---------|------|------|
| 検索クエリ | テキスト | - | 氏名・メール・電話番号での検索 |
| 高度な検索条件 | Ransack | - | 複合条件での検索 |

### 表示オプション

| 項目名 | 入力形式 | 必須 | 説明 |
|--------|---------|------|------|
| ソート順 | セレクト | - | 名前/作成日/更新日でのソート |
| 名前表示形式 | セレクト | - | 「名 姓」または「姓, 名」 |
| 1ページあたり件数 | セレクト | - | 10/20/30/40/50件 |

## 表示項目

### 連絡先リスト項目

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| アバター | image | 連絡先のアバター画像（40x40） |
| 氏名 | string | full_name（名前表示形式設定による） |
| 取引先情報 | string | 役職・会社名・部署 |
| 紹介者 | string | リードからの紹介者情報（存在する場合） |
| メールアドレス | string | メールアドレス（リンク） |
| 電話番号 | string | 電話番号 |
| 携帯電話 | string | 携帯番号 |
| 作成日時 | datetime | 「X日前に追加」形式 |
| タグ | string | 付与されたタグ一覧 |

### アクションボタン

| ボタン名 | 表示条件 | 処理 |
|---------|---------|------|
| Edit | can?(:update, contact) | 編集フォーム展開 |
| Discard | shown_on_landing_page? | 関連から切り離し |
| Delete | can?(:destroy, contact) | 連絡先削除（確認ダイアログ） |

## イベント仕様

### 01-初期表示

画面アクセス時に get_contacts メソッドで連絡先一覧を取得し、デフォルトのソート順（created_at DESC）で表示する。ページネーションは20件/ページ。

### 02-検索実行

検索ボックスに入力してEnterキーまたは検索ボタンをクリックすると、text_search スコープで氏名・メール・電話番号を検索する。

### 03-新規作成ボタン押下

「Create Contact」ボタンをクリックすると、Ajax通信で新規作成フォーム（_new.html.haml）が展開される。

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

連絡先の「Edit」リンクをクリックすると、Ajax通信で編集フォーム（_edit.html.haml）がインライン展開される。

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

連絡先の「Delete」リンクをクリックすると確認ダイアログが表示され、確認後に連絡先が論理削除される。

### 06-ページネーション

ページネーションリンクをクリックすると、Ajax通信で該当ページの連絡先一覧が取得・表示される。

### 07-表示オプション変更

オプションパネルでソート順・名前表示形式・表示件数を変更すると、redrawアクションで一覧が再描画される。

### 08-エクスポート

「Export」リンクから Excel または CSV 形式でダウンロードする。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 一覧表示 | contacts | SELECT | 連絡先一覧取得 |
| 一覧表示 | accounts | SELECT | 関連取引先取得（includes） |
| 一覧表示 | taggings/tags | SELECT | タグ取得（includes） |
| 検索 | contacts | SELECT | 検索条件でのフィルタリング |
| 削除 | contacts | UPDATE | deleted_at への論理削除 |
| 削除 | versions | INSERT | 削除履歴記録 |

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

#### contacts

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | my(current_user) | アクセス権限に基づく取得 |
| UPDATE (削除時) | deleted_at | 現在日時 | 論理削除 |

## メッセージ仕様

| メッセージ種別 | メッセージコード | 表示内容 | 表示条件 |
|--------------|----------------|---------|---------|
| 成功 | msg_asset_deleted | "#{name} has been deleted." | 削除成功時 |
| 情報 | empty | "There are no contacts yet." | 連絡先が存在しない場合 |

## 例外処理

| 例外ケース | 処理内容 | 表示 |
|-----------|---------|------|
| 認証エラー | ログイン画面にリダイレクト | Deviseのデフォルトメッセージ |

## 備考

- list_includes で :account と :tags を事前読み込み（N+1対策）
- text_search スコープは氏名の順序入れ替え（first last / last first）にも対応
- 名前表示形式の設定はリードと連動（contacts_naming / leads_naming）
- ソート順の設定もリードと連動
- 連絡先がリードから変換されている場合、紹介者情報が表示される
- template_for_current_view で表示テンプレートをカスタマイズ可能
- hook ポイントでプラグインによる拡張が可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | contact.rb | `app/models/entities/contact.rb` | belongs_to :lead（42行目）でリードからの変換を確認 |
| 1-2 | contact.rb | `app/models/entities/contact.rb` | has_one :account（45-46行目）で取引先との関連を確認 |
| 1-3 | contact.rb | `app/models/entities/contact.rb` | text_search スコープ（66-84行目）で検索ロジックを確認 |

**読解のコツ**: text_search は氏名の「名 姓」「姓 名」両方のパターンに対応していることを理解。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | contacts_controller.rb | `app/controllers/entities/contacts_controller.rb` | indexアクション（13-20行目） |
| 2-2 | contacts_controller.rb | `app/controllers/entities/contacts_controller.rb` | redrawアクション（109-128行目） |
| 2-3 | contacts_controller.rb | `app/controllers/entities/contacts_controller.rb` | list_includes メソッド（136-138行目） |

**主要処理フロー**:
1. **14行目**: get_contacts でページング付き一覧取得
2. **17-18行目**: Excel/CSVエクスポート対応
3. **110行目**: redraw で表示件数変更
4. **113-120行目**: ソート・名前表示形式の設定（リードと連動）

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.html.haml | `app/views/contacts/index.html.haml` | 一覧画面の全体構成 |
| 3-2 | _contact.html.haml | `app/views/contacts/_contact.html.haml` | 連絡先行のレンダリング分岐 |
| 3-3 | _index_long.html.haml | `app/views/contacts/_index_long.html.haml` | デフォルトの連絡先表示テンプレート |

**主要処理フロー**:
- **12-15行目（index）**: @contacts.any? で連絡先の有無判定
- **1-5行目（_contact）**: template_for_current_view でカスタムテンプレート対応
- **17行目（_index_long）**: contact.full_name で名前表示形式設定を適用
- **21-23行目（_index_long）**: リードからの紹介者情報を表示

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

```
[HTTP Request: GET /contacts]
    │
    ├─ routes.rb (84行目)
    │      └─ ContactsController#index
    │
    ├─ ContactsController#index (13-20行目)
    │      ├─ get_contacts (alias: get_list_of_records)
    │      │      ├─ list_includes → [:account, :tags]
    │      │      └─ Contact.my(current_user)
    │      │
    │      └─ respond_with(@contacts)
    │             ├─ HTML → contacts/index.html.haml
    │             ├─ XLS → Excel形式
    │             └─ CSV → CSV形式
    │
    └─ contacts/index.html.haml
           ├─ entities/_title_bar.html.haml
           │      └─ 新規作成ボタン
           ├─ #create_contact (Ajax展開先)
           ├─ _search.html.haml (検索機能)
           ├─ #options (表示オプション)
           ├─ #contacts
           │      └─ contacts/_contact.html.haml (collection)
           │             └─ contacts/_index_long.html.haml
           ├─ shared/_paginate_with_per_page.html.haml
           └─ shared/_export.html.haml
```

### データフロー図

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

HTTPリクエスト ───▶ ルーティング ───▶ contacts/index.html.haml
(GET /contacts)           │
                          ▼
                   ContactsController#index
                          │
                   get_contacts
                          │
                   ┌──────┼──────┐
                   ▼      ▼      ▼
               contacts accounts tags
                  DB      DB      DB
                   │      │      │
                   └──────┼──────┘
                          │
                          ▼
                   @contacts (連絡先一覧)
                          │
                   ┌──────┴──────┐
                   ▼             ▼
              HTML表示    Excel/CSV
              (Ajax対応)   エクスポート
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| contact.rb | `app/models/entities/contact.rb` | モデル | 連絡先のデータモデル定義、スコープ |
| contacts_controller.rb | `app/controllers/entities/contacts_controller.rb` | コントローラー | index, redrawアクション |
| entities_controller.rb | `app/controllers/entities_controller.rb` | コントローラー | get_list_of_records |
| index.html.haml | `app/views/contacts/index.html.haml` | ビュー | 一覧画面メインテンプレート |
| _contact.html.haml | `app/views/contacts/_contact.html.haml` | ビュー | 連絡先行パーシャル（分岐） |
| _index_long.html.haml | `app/views/contacts/_index_long.html.haml` | ビュー | デフォルト表示テンプレート |
| _title_bar.html.haml | `app/views/entities/_title_bar.html.haml` | ビュー | タイトルバー（新規作成ボタン） |
| _paginate_with_per_page.html.haml | `app/views/shared/_paginate_with_per_page.html.haml` | ビュー | ページネーション |
| _export.html.haml | `app/views/shared/_export.html.haml` | ビュー | エクスポートリンク |
| routes.rb | `config/routes.rb` | 設定 | URLルーティング定義 |
