# 画面設計書 18-リード編集フォーム

## 概要

Fat Free CRM における既存リード（見込み客）の情報を編集するためのフォーム画面設計書である。

### 本画面の処理概要

本画面は、既存のリード情報を更新するための入力フォームであり、Ajax通信によるモーダル形式で表示される。

**業務上の目的・背景**：
リードの進捗に伴い、連絡先情報の更新やステータスの変更が必要となる場合がある。本画面を通じて、リードの基本情報、連絡先詳細、担当者、ステータスなどを更新し、正確な情報管理を行う。また、レーティングの見直しやキャンペーンの変更により、リードの優先度や属性を適切に管理する。

**画面へのアクセス方法**：
1. リード詳細画面で「Edit」ボタンをクリック
2. リード一覧画面で編集アイコンをクリック
3. Ajax通信でモーダルとして表示される

**主要な操作・処理内容**：
1. 基本情報の編集（名、姓、メール、電話）
2. タグの編集
3. ステータス・担当者・レーティングの変更
4. ソース・キャンペーンの変更
5. 連絡先詳細の編集（役職、会社、住所、携帯等）
6. Web情報の編集
7. カスタムフィールドの編集
8. アクセス権限の変更
9. 保存またはキャンセル

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

**権限による表示制御**：
- リードのアクセス権限に基づいて編集可否が決定
- 作成者または共有されたユーザーのみ編集可能

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 23 | リード編集 | 主機能 | リード情報更新 |
| 83 | タグ付け | 補助機能 | リードへのタグ付け |
| 84 | アクセス権限管理 | 補助機能 | リードのアクセス権限設定 |

## 画面種別

編集

## URL/ルーティング

| HTTPメソッド | URL | アクション | 説明 |
|-------------|-----|----------|------|
| GET | /leads/:id/edit | edit | 編集フォーム表示 |
| PUT/PATCH | /leads/:id | update | 更新実行 |

## 入出力項目

### 基本情報セクション（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）

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

### Webセクション

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

### 権限セクション

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

## 表示項目

既存値が各入力フィールドにプリセットされる。

## イベント仕様

### 01-フォーム表示

「Edit」リンクをクリックすると、Ajax通信で編集フォームが読み込まれ、既存の値がプリセットされた状態でモーダルとして展開される。

### 02-キャンペーン変更

キャンペーンを変更すると、JavaScriptでアクセス権限のCampaignオプションの有効/無効が切り替わる。キャンペーン変更時はleads_countの増減処理が発生する。

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

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

### 04-キャンセル

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

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 保存 | leads | UPDATE | リード情報更新 |
| 保存（キャンペーン変更） | campaigns | UPDATE | 旧キャンペーンのleads_countデクリメント |
| 保存（キャンペーン変更） | campaigns | UPDATE | 新キャンペーンのleads_countインクリメント |
| 保存（権限変更） | permissions | DELETE/INSERT | 権限レコード更新 |
| 保存（タグ変更） | taggings | DELETE/INSERT | タグ紐付け更新 |
| 保存（住所変更） | addresses | UPDATE | 住所情報更新 |
| 保存 | versions | INSERT | 更新履歴記録 |

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

#### leads

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | campaign_id | 選択されたキャンペーンID | |
| UPDATE | assigned_to | 選択された担当者ID | |
| UPDATE | first_name | 入力値 | |
| UPDATE | last_name | 入力値 | |
| UPDATE | access | 入力値 | |
| UPDATE | title | 入力値 | |
| UPDATE | company | 入力値 | |
| UPDATE | source | 入力値 | |
| UPDATE | status | 入力値 | |
| UPDATE | email | 入力値 | |
| UPDATE | phone | 入力値 | |
| UPDATE | mobile | 入力値 | |
| UPDATE | rating | 入力値 | |
| UPDATE | do_not_call | 入力値 | |
| UPDATE | updated_at | 現在日時 | |

#### campaigns

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | leads_count | デクリメント | 旧キャンペーン（キャンペーン変更時） |
| 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のデフォルトメッセージ |
| 権限エラー | 403エラー | アクセス権限がありません |

## 備考

- simple_form_for を使用したフォーム生成
- remote: true により Ajax 送信
- one_submit_only によりダブルサブミット防止
- edit: true パラメータが各パーシャルに渡され、編集モード固有の表示制御
- コメント追加セクションは編集フォームには含まれない
- キャンペーン変更時は update_with_lead_counters メソッドで leads_count を管理

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | lead.rb | `app/models/entities/lead.rb` | update_with_lead_counters メソッド（108-119行目）を確認 |

**読解のコツ**: キャンペーンが変更された場合、旧キャンペーンの decrement_leads_count と新キャンペーンの increment_leads_count が実行される点を理解。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | leads_controller.rb | `app/controllers/entities/leads_controller.rb` | editアクション（53-60行目） |
| 2-2 | leads_controller.rb | `app/controllers/entities/leads_controller.rb` | updateアクション（82-93行目） |

**主要処理フロー**:
1. **54行目**: get_campaigns でキャンペーン一覧取得
2. **56-57行目**: @previous で前のリード取得
3. **86行目**: access を最初に設定
4. **87行目**: update_with_lead_counters でキャンペーン変更を考慮した更新

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | _edit.html.haml | `app/views/leads/_edit.html.haml` | 編集フォームの構成 |

**主要処理フロー**:
- **1行目**: .remote クラスでコンテナを定義
- **2行目**: simple_form_for でフォーム開始
- **8-14行目**: 各セクションのパーシャルレンダリング（edit: true）
- **17-22行目**: 保存ボタン（compound_address設定による分岐）

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

```
[HTTP Request: GET /leads/:id/edit]
    │
    ├─ routes.rb (103行目)
    │      └─ LeadsController#edit
    │
    ├─ LeadsController#edit (53-60行目)
    │      ├─ get_campaigns
    │      ├─ @previous (前のリード取得)
    │      └─ respond_with(@lead)
    │
    └─ leads/_edit.html.haml
           ├─ simple_form_for(@lead, remote: true)
           ├─ leads/_top_section.html.haml (edit: true)
           ├─ fields/_edit_custom_field_group.html.haml (edit: true)
           ├─ leads/_status.html.haml (edit: true)
           ├─ leads/_contact.html.haml (edit: true)
           ├─ leads/_web.html.haml (edit: true)
           ├─ fields/_groups.html.haml (edit: true)
           └─ entities/_permissions.html.haml (edit: true)

[HTTP Request: PUT /leads/:id]
    │
    └─ LeadsController#update (82-93行目)
           ├─ @lead.access = resource_params[:access]
           ├─ @lead.update_with_lead_counters(resource_params)
           └─ update_sidebar
```

### データフロー図

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

フォーム入力 ───────▶ params[:lead]
                           │
                           ▼
                    LeadsController#update
                           │
                    ┌──────┴──────┐
                    ▼             ▼
              access設定       バリデーション
              (最初に実行)          │
                    │         失敗 │
                    │             ▼
                    │        エラーメッセージ
                    ▼
              update_with_lead_counters
                    │
              ┌─────┼─────────────┐
              ▼     ▼             ▼
           leads campaigns    campaigns
           UPDATE  (旧) -1    (新) +1
                    │
                    ▼
              Ajax レスポンス ───▶ 詳細/一覧画面更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| lead.rb | `app/models/entities/lead.rb` | モデル | update_with_lead_counters |
| leads_controller.rb | `app/controllers/entities/leads_controller.rb` | コントローラー | edit/updateアクション |
| _edit.html.haml | `app/views/leads/_edit.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ルーティング定義 |
