# 画面設計書 15-リード一覧画面

## 概要

Fat Free CRM におけるリード（見込み客）を一覧表示・管理するための画面設計書である。

### 本画面の処理概要

本画面は、営業活動の起点となるリード（見込み客）情報を一覧形式で表示し、効率的な管理を可能にする画面である。

**業務上の目的・背景**：
営業チームがマーケティング活動や展示会などで獲得した見込み客（リード）を一元管理する必要がある。本画面を通じて、リードのステータス（新規、連絡済み、商談中、変換済み、却下済み）を把握し、優先的にフォローすべきリードを特定できる。リードの適切な管理は、商談機会の創出と売上向上に直結する重要な業務である。

**画面へのアクセス方法**：
1. ログイン後、サイドバーまたはナビゲーションメニューから「Leads」をクリック
2. ダッシュボードのリード関連リンクからアクセス
3. URL直接入力: `/leads`

**主要な操作・処理内容**：
1. リード一覧の表示（ページネーション対応）
2. ステータスによるフィルタリング（new, contacted, converted, rejected等）
3. テキスト検索による絞り込み
4. 新規リード作成フォームの表示（Ajaxモーダル）
5. リード詳細画面への遷移
6. リードの編集・削除
7. CSV/XLSエクスポート
8. 高度な検索（Ransack）
9. 表示順・表示件数の設定

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

**権限による表示制御**：
- 認証済みユーザーのみアクセス可能（CanCanCan による認可）
- ユーザーは自身が作成したリード、または共有されたリードのみ表示・操作可能
- アクセス権限（Public/Private/Shared/Campaign）によって他ユーザーへの公開範囲が決定される

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 20 | リード一覧表示 | 主機能 | リード一覧表示、ステータスフィルタリング、CSV/XLSエクスポート |
| 81 | 高度な検索 | 補助機能 | Ransackによる詳細検索 |
| 24 | リード削除 | 補助機能 | リードの削除処理 |

## 画面種別

一覧

## URL/ルーティング

| HTTPメソッド | URL | アクション | 説明 |
|-------------|-----|----------|------|
| GET | /leads | index | 一覧表示 |
| GET | /leads.csv | index | CSV形式でエクスポート |
| GET | /leads.xls | index | XLS形式でエクスポート |
| POST | /leads/filter | filter | ステータスフィルタリング |
| GET | /leads/redraw | redraw | 表示設定変更後の再描画 |
| GET | /leads/advanced_search | advanced_search | 高度な検索 |
| GET | /leads/autocomplete_account_name | autocomplete_account_name | 会社名オートコンプリート |

## 入出力項目

### 検索・フィルタ入力

| 項目名 | 入力形式 | 必須 | 説明 |
|--------|---------|------|------|
| 検索キーワード | テキスト | - | 氏名、会社名、メールアドレスでの検索 |
| ステータスフィルタ | チェックボックス | - | new, contacted, converted, rejected |
| 表示件数 | セレクト | - | 1ページあたりの表示件数 |
| ソート順 | セレクト | - | 名前、作成日、更新日等 |
| 名前表示順 | ラジオボタン | - | 名前の表示順（姓-名 / 名-姓） |

## 表示項目

### リード一覧

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| リード名 | string | 氏名（first_name + last_name）（リンク） |
| 会社名 | string | 所属会社 |
| 役職 | string | 役職 |
| ステータス | string | new/contacted/converted/rejected |
| ソース | string | リード獲得元（campaign, referral, web等） |
| レーティング | integer | 優先度/重要度（星表示） |
| メールアドレス | string | メールアドレス |
| 電話番号 | string | 電話番号 |
| タグ | string | 付与されたタグ |
| 作成日 | datetime | 作成日時 |

### サイドバー（ステータス別件数）

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| 各ステータスの件数 | integer | ステータス別のリード数 |
| その他の件数 | integer | ステータス未設定のリード数 |
| 合計件数 | integer | 全リード数 |

## イベント仕様

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

「Create Lead」ボタンをクリックすると、Ajax通信でリード新規作成フォーム（_new.html.haml）がモーダルとして画面上部に展開される。

### 02-リード名リンク押下

リード名のリンクをクリックすると、該当リードの詳細画面（/leads/:id）に遷移する。

### 03-ステータスフィルタ変更

サイドバーのステータスチェックボックスをクリックすると、Ajax通信でフィルタリング処理が実行され、一覧が再描画される。セッションにフィルタ条件が保存される。

### 04-検索実行

検索フォームにキーワードを入力してEnterまたは検索ボタンを押下すると、氏名・会社名・メールアドレスでのテキスト検索が実行される。

### 05-CSV/XLSエクスポート

エクスポートリンクをクリックすると、現在の検索・フィルタ条件に基づいたデータがCSVまたはXLS形式でダウンロードされる。

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

ページリンクをクリックすると、指定ページのデータが読み込まれ一覧が更新される。

### 07-表示件数変更

表示件数セレクトボックスを変更すると、ユーザー設定（pref）に保存され、1ページ目から再描画される。

### 08-ソート順変更

ソート順を変更すると、ユーザー設定に保存され、一覧が再ソートされる。リードとコンタクトで同じソート設定が共有される場合がある。

### 09-名前表示順変更

名前表示順を変更すると、「名-姓」または「姓-名」の形式で一覧の表示が切り替わる。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 一覧表示 | leads | SELECT | 条件に応じたリード取得 |
| フィルタリング | - | - | セッションへの保存のみ |
| 削除 | leads | UPDATE | deleted_at への論理削除 |
| 削除 | campaigns | UPDATE | leads_count のデクリメント |
| 削除 | versions | INSERT | 削除履歴の記録 |

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

#### leads

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | user_id または permissions で認可 | my(current_user)スコープ適用 |
| UPDATE (削除時) | deleted_at | 現在日時 | 論理削除 |

#### campaigns

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE (削除時) | leads_count | デクリメント | リードにキャンペーンが紐付いている場合 |

## メッセージ仕様

| メッセージ種別 | メッセージコード | 表示内容 | 表示条件 |
|--------------|----------------|---------|---------|
| 成功 | msg_asset_deleted | "#{name} has been deleted." | 削除成功時 |
| 情報 | - | "No leads found." | 検索結果0件時 |

## 例外処理

| 例外ケース | 処理内容 | 表示 |
|-----------|---------|------|
| 認証エラー | ログイン画面にリダイレクト | Deviseのデフォルトメッセージ |
| 権限エラー | 403エラー | アクセス権限がありません |
| データなし | 空メッセージ表示 | shared/_empty パーシャル |

## 備考

- リードステータスは `Setting.lead_status` で設定される
- ソート順は `Lead.sort_by_map` で定義
- paper_trail によりバージョン履歴が記録される
- acts_as_taggable_on によりタグ付けが可能
- リードの削除時にキャンペーンの leads_count がデクリメントされる
- 名前表示順（naming）の設定はリードとコンタクトで同期可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | lead.rb | `app/models/entities/lead.rb` | Leadモデルの定義、バリデーション、スコープ、関連を確認 |

**読解のコツ**: `belongs_to :campaign` でキャンペーンとの関連、`has_one :contact` でコンタクトへの変換関連を確認。`text_search` スコープ（62行目）で検索対象フィールドを把握。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | leads_controller.rb | `app/controllers/entities/leads_controller.rb` | indexアクション（14-21行目） |
| 2-2 | entities_controller.rb | `app/controllers/entities_controller.rb` | 親クラスの共通処理 |

**主要処理フロー**:
1. **15行目**: `get_leads` でリード一覧を取得
2. **186-194行目（leads_controller.rb）**: `filter`アクションでステータスフィルタリング
3. **164-183行目**: `redraw`アクションで表示設定変更後の再描画

#### Step 3: ルーティングを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | routes.rb | `config/routes.rb` | leadsリソースのルート定義（103-123行目） |

**主要処理フロー**:
- **103行目**: `resources :leads` でRESTfulルート生成
- **104-113行目**: collectionルート（advanced_search, filter, autocomplete_account_name等）
- **114-122行目**: memberルート（convert, promote, reject等）

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | index.html.haml | `app/views/leads/index.html.haml` | 一覧画面のメインテンプレート |
| 4-2 | _lead.html.haml | `app/views/leads/_lead.html.haml` | 各リード行のパーシャル |
| 4-3 | _sidebar_index.html.haml | `app/views/leads/_sidebar_index.html.haml` | サイドバー（フィルタ）のパーシャル |

**主要処理フロー**:
- **1行目（index.html.haml）**: スタイル読み込み
- **3行目**: タイトルバーのレンダリング
- **11-15行目**: リード一覧のイテレーション
- **17-18行目**: ページネーションとエクスポート

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

```
[HTTP Request: GET /leads]
    │
    ├─ routes.rb (103行目)
    │      └─ LeadsController#index
    │
    ├─ LeadsController#index (14-21行目)
    │      ├─ get_leads (= get_list_of_records)
    │      │      ├─ ransack_search.result
    │      │      ├─ scope.state(filter) [フィルタ適用]
    │      │      ├─ scope.text_search(query) [テキスト検索]
    │      │      └─ scope.paginate [ページネーション]
    │      │
    │      └─ respond_with @leads
    │             ├─ format.html [leads/index.html.haml]
    │             ├─ format.xls [header layout + XLS]
    │             └─ format.csv [CSV出力]
    │
    └─ leads/index.html.haml
           ├─ entities/_title_bar.html.haml
           ├─ leads/_lead.html.haml (collection)
           ├─ leads/_sidebar_index.html.haml
           ├─ shared/_paginate_with_per_page.html.haml
           └─ shared/_export.html.haml
```

### データフロー図

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

HTTPリクエスト ───▶ ルーティング ───▶ leads/index.html.haml
   │                    │
   │                    ▼
   │             LeadsController
   │                    │
   ├─ query     ───▶ text_search (first_name_or_last_name_or_company_or_email)
   ├─ status    ───▶ state scope (フィルタ)
   └─ page      ───▶ paginate (will_paginate)
                       │
                       ▼
                leads テーブル ───▶ @leads
                       │
                       ▼
                ビューレンダリング ───▶ HTML/CSV/XLS
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| lead.rb | `app/models/entities/lead.rb` | モデル | リードのデータモデル定義 |
| leads_controller.rb | `app/controllers/entities/leads_controller.rb` | コントローラー | リード関連のアクション処理 |
| entities_controller.rb | `app/controllers/entities_controller.rb` | コントローラー | エンティティ共通の基底クラス |
| index.html.haml | `app/views/leads/index.html.haml` | ビュー | 一覧画面のメインテンプレート |
| _lead.html.haml | `app/views/leads/_lead.html.haml` | ビュー | 一覧の各行パーシャル |
| _sidebar_index.html.haml | `app/views/leads/_sidebar_index.html.haml` | ビュー | サイドバーフィルタ |
| _title_bar.html.haml | `app/views/entities/_title_bar.html.haml` | ビュー | タイトルバー共通パーシャル |
| routes.rb | `config/routes.rb` | 設定 | URLルーティング定義 |
