# 画面設計書 17-リード新規作成フォーム

## 概要

Fat Free CRM における新規リード（見込み客）を作成するためのフォーム画面設計書である。

### 本画面の処理概要

本画面は、新しいリード（見込み客）を登録するための入力フォームであり、Ajax通信によるモーダル形式で表示される。

**業務上の目的・背景**：
営業・マーケティング担当者が展示会、Webフォーム、電話問い合わせなどで獲得した見込み客情報を登録する。リードの基本情報（氏名、連絡先）に加えて、獲得元（ソース）やキャンペーンとの紐付けを行うことで、マーケティング効果の測定や適切なフォローアップを可能にする。レーティング設定により、リードの優先度を管理できる。

**画面へのアクセス方法**：
1. リード一覧画面で「Create Lead」ボタンをクリック
2. キャンペーン詳細画面のリードセクションで新規作成リンクをクリック
3. Ajax通信でモーダルとして表示される

**主要な操作・処理内容**：
1. 基本情報の入力（名、姓、メール、電話）
2. タグの付与
3. ステータス・担当者・レーティングの設定
4. ソース・キャンペーンの選択
5. 連絡先詳細の入力（役職、会社、住所、携帯等）
6. Web情報の入力（Blog, LinkedIn等）
7. カスタムフィールドの入力
8. コメントの追加（オプション）
9. アクセス権限の設定（Public/Private/Shared/Campaign）
10. 保存またはキャンセル

**画面遷移**：
- 遷移元: リード一覧画面、キャンペーン詳細画面
- 遷移先（保存成功時）: 遷移元画面（更新）
- 遷移先（キャンセル時）: 遷移元画面（変更なし）

**権限による表示制御**：
- 認証済みユーザーのみアクセス可能
- 新規作成は全ての認証ユーザーに許可
- キャンペーンからの作成時は「Campaign」権限が選択可能

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 22 | リード作成 | 主機能 | 新規リード情報入力、キャンペーン紐付け、作成実行 |
| 83 | タグ付け | 補助機能 | リードへのタグ付け |
| 84 | アクセス権限管理 | 補助機能 | リードのアクセス権限設定 |

## 画面種別

登録

## URL/ルーティング

| HTTPメソッド | URL | アクション | 説明 |
|-------------|-----|----------|------|
| GET | /leads/new | new | 新規作成フォーム表示 |
| POST | /leads | create | 新規作成実行 |

## 入出力項目

### 基本情報セクション（Top Section）

| 項目名 | 入力形式 | 必須 | 最大長 | 説明 |
|--------|---------|------|--------|------|
| 名（First Name） | テキスト | 設定依存 | 64文字 | 名前（Setting.require_first_names による） |
| 姓（Last Name） | テキスト | 設定依存 | 64文字 | 姓（Setting.require_last_names による） |
| メールアドレス | テキスト | - | 64文字 | メールアドレス |
| 電話番号 | テキスト | - | 32文字 | 電話番号 |
| 背景情報 | テキストエリア | - | 255文字 | 背景説明（設定有効時のみ表示） |
| タグ | テキスト | - | - | カンマ区切りでタグを入力 |

### ステータスセクション（Status）

| 項目名 | 入力形式 | 必須 | 説明 |
|--------|---------|------|------|
| 担当者 | セレクトボックス | - | アサインされるユーザー |
| ステータス | セレクトボックス | - | new/contacted/converted/rejected |
| レーティング | セレクトボックス | - | 星評価（1-5） |
| ソース | セレクトボックス | - | campaign/referral/web/other等 |
| キャンペーン | セレクトボックス | - | 紐付けるキャンペーン |

### 連絡先セクション（Contact Info）

| 項目名 | 入力形式 | 必須 | 説明 |
|--------|---------|------|------|
| 役職 | テキスト | - | 役職名 |
| 会社名 | テキスト（オートコンプリート） | - | 所属会社（Account名で補完） |
| 代替メール | テキスト | - | 代替メールアドレス |
| 携帯電話 | テキスト | - | 携帯番号 |
| 住所 | 複合フィールド | - | ビジネス住所 |
| 紹介者 | テキスト | - | 紹介者名 |
| 電話禁止 | チェックボックス | - | do_not_call フラグ |

### Webセクション

| 項目名 | 入力形式 | 必須 | 説明 |
|--------|---------|------|------|
| Blog | テキスト | - | ブログURL |
| LinkedIn | テキスト | - | LinkedInプロフィールURL |
| Facebook | テキスト | - | FacebookプロフィールURL |
| Twitter | テキスト | - | Twitterハンドル |

### コメントセクション

| 項目名 | 入力形式 | 必須 | 説明 |
|--------|---------|------|------|
| コメント | テキストエリア | - | 作成時の初期コメント |

### 権限セクション

| 項目名 | 入力形式 | 必須 | 説明 |
|--------|---------|------|------|
| アクセス権限 | ラジオボタン | ○ | Public/Private/Shared/Campaign |
| 共有ユーザー | マルチセレクト | 条件付 | Shared選択時に表示 |
| 共有グループ | マルチセレクト | 条件付 | Shared選択時に表示 |

## 表示項目

なし（入力フォームのみ）

## イベント仕様

### 01-フォーム表示

「Create Lead」リンクをクリックすると、Ajax通信で新規作成フォームが読み込まれ、モーダルとして展開される。キャンペーン詳細画面から呼ばれた場合、キャンペーンが自動選択される。

### 02-会社名入力

会社名フィールドでは、autocomplete_account_name_leads_path によるオートコンプリート機能が提供され、既存の取引先名が候補として表示される。

### 03-キャンペーン選択

キャンペーンを選択すると、JavaScriptでアクセス権限のCampaignオプションが有効化/無効化される（crm.flip_campaign_permissions）。

### 04-アクセス権限選択

- Public: 全ユーザーがアクセス可能
- Private: 作成者のみアクセス可能
- Shared: 選択したユーザー/グループがアクセス可能
- Campaign: キャンペーンの権限を継承（キャンペーン選択時のみ有効）

### 05-保存ボタン押下

「Create Lead」ボタンをクリックすると、Ajax通信でPOSTリクエストが送信される。Setting.compound_address が有効な場合、送信前にヒントがクリアされる。

### 06-キャンセル

「Cancel」リンクをクリックすると、フォームが閉じ、入力内容は破棄される。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 保存 | leads | INSERT | 新規リード作成 |
| 保存（コメントあり） | comments | INSERT | 初期コメント追加 |
| 保存（Shared） | permissions | INSERT | 共有権限レコード作成 |
| 保存（キャンペーンあり） | campaigns | UPDATE | leads_count インクリメント |
| 保存 | taggings | INSERT | タグ紐付け |
| 保存 | addresses | INSERT | 住所情報 |
| 保存 | versions | INSERT | 作成履歴記録 |

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

#### leads

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | user_id | current_user.id | 作成者 |
| INSERT | campaign_id | 選択されたキャンペーンID | |
| INSERT | assigned_to | 選択された担当者ID | |
| INSERT | first_name | 入力値 | |
| INSERT | last_name | 入力値 | |
| INSERT | access | 入力値 | Public/Private/Shared/Campaign |
| INSERT | title | 入力値 | 役職 |
| INSERT | company | 入力値 | 会社名 |
| INSERT | source | 入力値 | ソース |
| INSERT | status | 入力値 | デフォルト: new |
| INSERT | email | 入力値 | |
| INSERT | phone | 入力値 | |
| INSERT | mobile | 入力値 | |
| INSERT | blog | 入力値 | |
| INSERT | linkedin | 入力値 | |
| INSERT | facebook | 入力値 | |
| INSERT | twitter | 入力値 | |
| INSERT | rating | 入力値 | デフォルト: 0 |
| INSERT | do_not_call | 入力値 | デフォルト: false |
| INSERT | referred_by | 入力値 | |

#### campaigns

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | leads_count | インクリメント | キャンペーンが指定された場合 |

## メッセージ仕様

| メッセージ種別 | メッセージコード | 表示内容 | 表示条件 |
|--------------|----------------|---------|---------|
| エラー | missing_first_name | "First name is required." | 名未入力時（設定依存） |
| エラー | missing_last_name | "Last name is required." | 姓未入力時（設定依存） |
| エラー | share_lead | "Please select users and/or groups to share with." | Shared選択時に共有先未選択 |

## 例外処理

| 例外ケース | 処理内容 | 表示 |
|-----------|---------|------|
| バリデーションエラー | フォーム再表示 | エラーメッセージをフィールド上部に表示 |
| 認証エラー | ログイン画面にリダイレクト | Deviseのデフォルトメッセージ |
| サーバーエラー | エラー画面表示 | 500エラー画面 |

## 備考

- simple_form_for を使用したフォーム生成
- remote: true により Ajax 送信
- one_submit_only によりダブルサブミット防止
- キャンペーン詳細画面からの作成時、ソースは「campaign」に固定、キャンペーンも自動選択
- Company フィールドは既存の Account 名でオートコンプリート
- Setting.compound_address 設定により住所入力UIが変わる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | lead.rb | `app/models/entities/lead.rb` | バリデーション定義（76-79行目）を確認 |
| 1-2 | lead.rb | `app/models/entities/lead.rb` | save_with_permissions メソッド（96-104行目） |

**読解のコツ**: `validates_presence_of :first_name, if: -> { Setting.require_first_names }` のように設定により必須が変わる点を理解。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | leads_controller.rb | `app/controllers/entities/leads_controller.rb` | newアクション（35-50行目） |
| 2-2 | leads_controller.rb | `app/controllers/entities/leads_controller.rb` | createアクション（63-79行目） |

**主要処理フロー**:
1. **37行目**: デフォルト属性の設定（user, access, assigned_to）
2. **38行目**: get_campaigns でキャンペーン一覧取得
3. **69行目**: save_with_permissions でキャンペーン紐付けを含む保存
4. **70行目**: コメント追加

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | _new.html.haml | `app/views/leads/_new.html.haml` | 新規作成フォームの構成 |
| 3-2 | _top_section.html.haml | `app/views/leads/_top_section.html.haml` | 基本情報入力セクション |
| 3-3 | _status.html.haml | `app/views/leads/_status.html.haml` | ステータス・ソース選択 |
| 3-4 | _contact.html.haml | `app/views/leads/_contact.html.haml` | 連絡先詳細入力 |

**主要処理フロー**:
- **4行目（_new.html.haml）**: キャンペーンIDを隠しフィールドで送信
- **8-15行目**: 各セクションのパーシャルレンダリング
- **19-23行目**: 保存ボタン（compound_address設定による分岐）

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

```
[HTTP Request: GET /leads/new]
    │
    ├─ routes.rb (103行目)
    │      └─ LeadsController#new
    │
    ├─ LeadsController#new (35-50行目)
    │      ├─ @lead.attributes = { user, access, assigned_to }
    │      ├─ get_campaigns
    │      └─ respond_with(@lead)
    │
    └─ leads/_new.html.haml
           ├─ simple_form_for(@lead, remote: true)
           ├─ hidden_field(:campaign)
           ├─ leads/_top_section.html.haml
           ├─ fields/_edit_custom_field_group.html.haml
           ├─ leads/_status.html.haml
           │      ├─ user_select (担当者)
           │      ├─ status select
           │      ├─ rating select
           │      ├─ source select
           │      └─ campaign select
           ├─ leads/_contact.html.haml
           │      ├─ title, company
           │      ├─ alt_email, mobile
           │      ├─ address
           │      └─ do_not_call checkbox
           ├─ shared/_add_comment.html.haml
           ├─ leads/_web.html.haml
           ├─ fields/_groups.html.haml
           └─ entities/_permissions.html.haml
```

### データフロー図

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

フォーム入力 ───────▶ params[:lead], params[:campaign]
                           │
                           ▼
                    LeadsController#create
                           │
                    ┌──────┴──────┐
                    ▼             ▼
              バリデーション    失敗
                    │             │
               成功 │             ▼
                    │        エラーメッセージ
                    ▼
              save_with_permissions
                    │
              ┌─────┼─────┬─────┐
              ▼     ▼     ▼     ▼
           leads campaigns comments permissions
           INSERT  UPDATE   INSERT   INSERT
                    │
                    ▼
              Ajax レスポンス ───▶ 一覧画面更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| lead.rb | `app/models/entities/lead.rb` | モデル | リードのバリデーション・保存ロジック |
| leads_controller.rb | `app/controllers/entities/leads_controller.rb` | コントローラー | new/createアクション |
| _new.html.haml | `app/views/leads/_new.html.haml` | ビュー | 新規作成フォームメインテンプレート |
| _top_section.html.haml | `app/views/leads/_top_section.html.haml` | ビュー | 基本情報入力セクション |
| _status.html.haml | `app/views/leads/_status.html.haml` | ビュー | ステータス・ソース選択 |
| _contact.html.haml | `app/views/leads/_contact.html.haml` | ビュー | 連絡先詳細入力 |
| _web.html.haml | `app/views/leads/_web.html.haml` | ビュー | Web情報入力 |
| _permissions.html.haml | `app/views/entities/_permissions.html.haml` | ビュー | 権限設定セクション |
| routes.rb | `config/routes.rb` | 設定 | URLルーティング定義 |
