# 機能設計書 25-リードの変換（コンバート）

## 概要

本ドキュメントは、Fat Free CRMシステムにおけるリード変換（コンバート）機能の設計を定義する。この機能は、リードを連絡先、取引先、商談に変換するための画面を表示する。実際の変換処理は機能No.26「リードのプロモート」で行われる。

### 本機能の処理概要

リード変換機能は、見込み顧客（リード）を正式な顧客（連絡先・取引先）および商談に変換するための入力画面を提供する機能である。

**業務上の目的・背景**：営業プロセスにおいて、見込み顧客が購買意欲を示した段階で、リードから連絡先、取引先、商談への変換が必要になる。この変換により、リード管理から顧客管理・商談管理へとシームレスに移行でき、営業パイプラインの正確な管理が可能になる。

**機能の利用シーン**：リードとの商談が具体化した場合、リードから見積もり依頼があった場合、リードが正式な取引先として認定された場合に利用される。変換画面では既存の取引先を選択するか、新規取引先を作成するかを選択できる。

**主要な処理内容**：
1. リード変換フォームの表示（convertアクション）
2. 既存取引先リストの取得と表示
3. 新規取引先作成フォームの準備
4. 商談作成オプションの表示
5. 担当者割り当ての選択

**関連システム・外部連携**：取引先機能、連絡先機能、商談機能との連携により、リードからの一括変換を実現する。

**権限による制御**：CanCanによる認可制御が行われ、リードへのアクセス権限を持つユーザーのみが変換画面にアクセス可能である。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 19 | リード変換画面 | 主画面 | リードを連絡先・取引先・商談に変換する画面表示 |
| 19 | リード変換画面 | 遷移先機能 | リードのプロモート（機能No.26） |
| 19 | リード変換画面 | 補助機能 | リードの却下（機能No.27） |

## 機能種別

データ参照（READ） / フォーム表示

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | Integer | Yes | リードID | 数値、存在確認 |
| previous | String | No | 前の編集フォームのID | DOM要素ID |

### 入力データソース

- URL: GET `/leads/:id/convert`
- HTTPメソッド: GET
- データソース: URLパラメータ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| @lead | Lead | 変換対象のリードオブジェクト |
| @account | Account | 新規取引先用の空オブジェクト（リードの会社名を初期値に設定） |
| @accounts | Array | ユーザーがアクセス可能な取引先一覧 |
| @opportunity | Opportunity | 新規商談用の空オブジェクト |
| @previous | Lead/String | 前の状態を保持する参照 |

### 出力先

- JS形式: AJAX応答（convert.js.haml → _convert.html.haml）

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ GET /leads/:id/convert を受信
2. 認証・認可チェック
   └─ CanCanによる権限確認
3. リード取得
   └─ 指定IDのリードを取得
4. 新規取引先準備
   └─ リードの会社名を初期値にしたAccountオブジェクト作成
5. 取引先一覧取得
   └─ ユーザーがアクセス可能な取引先を取得
6. 新規商談準備
   └─ リードのキャンペーン・ソースを引き継いだOpportunityオブジェクト作成
7. レスポンス生成
   └─ 変換フォームを表示
```

### フローチャート

```mermaid
flowchart TD
    A[GET /leads/:id/convert] --> B[認証チェック]
    B --> C{認可チェック}
    C -->|許可| D[リードデータ取得]
    C -->|拒否| E[403 Forbidden]
    D --> F[新規Account準備]
    F --> G[取引先一覧取得]
    G --> H[新規Opportunity準備]
    H --> I[@previous設定]
    I --> J[変換フォーム表示]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-25-01 | 取引先初期値 | 新規取引先のnameにはリードのcompanyを設定 | 常時 |
| BR-25-02 | 取引先アクセス | 新規取引先のaccessは"Lead"を設定（リードの権限を継承） | 常時 |
| BR-25-03 | 商談初期値 | 新規商談にはリードのcampaignとsourceを設定 | 常時 |
| BR-25-04 | 商談ステージ | 新規商談のstageは"prospecting"（見込み段階） | 常時 |
| BR-25-05 | 商談アクセス | 新規商談のaccessは"Lead"を設定（リードの権限を継承） | 常時 |

### 計算ロジック

特になし（フォーム表示のみ）

## データベース操作仕様

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| リード取得 | leads | SELECT | 指定IDのリード情報取得 |
| 取引先一覧取得 | accounts | SELECT | ユーザーがアクセス可能な取引先一覧取得 |

### テーブル別操作詳細

#### leads

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | id = :id | 全カラム取得 |

#### accounts

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | my(current_user) | ユーザーアクセス可能な取引先 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 404 | Not Found | 指定IDのリードが存在しない | エラーページ表示 |
| 403 | Forbidden | アクセス権限がない | エラーページ表示 |

### リトライ仕様

リトライは実装されていない（参照操作のため不要）

## トランザクション仕様

参照操作のみのためトランザクション制御は不要

## パフォーマンス要件

- 変換フォーム表示のレスポンスタイム: 1秒以内

## セキュリティ考慮事項

- CanCanによる認可制御でアクセス権限をチェック
- 取引先一覧はユーザーがアクセス可能なもののみ表示

## 備考

- 変換フォームでは「既存取引先を選択」または「新規取引先を作成」を選択可能
- 商談作成はオプション（商談名を入力した場合のみ作成）
- 実際の変換処理は機能No.26「リードのプロモート」で実行

---

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

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

### 推奨読解順序

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

変換対象となるエンティティの関係を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | lead.rb | `app/models/entities/lead.rb` | リードモデルの属性、関連（campaign, contact） |
| 1-2 | account.rb | `app/models/entities/account.rb` | 取引先モデル |
| 1-3 | opportunity.rb | `app/models/entities/opportunity.rb` | 商談モデル |

**読解のコツ**:
- **lead.rb 42-43行目**: belongs_to :campaign - リードとキャンペーンの関連
- **lead.rb 44行目**: has_one :contact - 変換後の連絡先との関連

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

コントローラーのconvertアクションがエントリーポイントである。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | leads_controller.rb | `app/controllers/entities/leads_controller.rb` | convertアクションの実装 |

**主要処理フロー**:
1. **108-116行目** (convertアクション):
   - **109行目**: @account作成 - リードのcompanyを初期値に
   - **110行目**: @accounts取得 - ユーザーアクセス可能な取引先一覧
   - **111行目**: @opportunity作成 - リードのcampaign/sourceを引き継ぎ
   - **113行目**: @previous設定 - キャンセル時の戻り先

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

変換フォームの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | convert.js.haml | `app/views/leads/convert.js.haml` | AJAX応答でフォーム表示 |
| 3-2 | _convert.html.haml | `app/views/leads/_convert.html.haml` | 変換フォームの構造 |

**主要処理フロー**:
- **_convert.html.haml 2行目**: form_forでpromotアクションにPOST
- **_convert.html.haml 14-19行目**: account_select_or_create - 取引先選択/作成UI
- **_convert.html.haml 20行目**: _opportunity.html.haml - 商談入力セクション

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

```
LeadsController#convert
    │
    ├─ @account = Account.new(...)
    │      ├─ user: current_user
    │      ├─ name: @lead.company
    │      └─ access: "Lead"
    │
    ├─ @accounts = Account.my(current_user).order('name')
    │
    ├─ @opportunity = Opportunity.new(...)
    │      ├─ user: current_user
    │      ├─ access: "Lead"
    │      ├─ stage: "prospecting"
    │      ├─ campaign: @lead.campaign
    │      └─ source: @lead.source
    │
    ├─ @previous = Lead.my(current_user).find_by_id(...)
    │
    └─ respond_with(@lead)
           └─ convert.js.haml
                  └─ _convert.html.haml
                         ├─ account_select_or_create
                         ├─ _opportunity.html.haml
                         └─ _convert_permissions.html.haml
```

### データフロー図

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

GET /leads/:id/convert ───▶ LeadsController#convert ───▶ JS
      │                           │
      │                           ├─▶ Lead.find
      │                           │       └─▶ [leads]テーブル
      │                           │
      │                           ├─▶ Account.new (初期値設定)
      │                           │
      │                           ├─▶ Account.my(current_user)
      │                           │       └─▶ [accounts]テーブル
      │                           │
      │                           └─▶ Opportunity.new (初期値設定)
      │
      └─▶ convert.js.haml
              └─▶ _convert.html.haml
                     ├─▶ 取引先選択/新規作成UI
                     └─▶ 商談入力フォーム
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| leads_controller.rb | `app/controllers/entities/leads_controller.rb` | コントローラー | リード操作のエントリーポイント |
| lead.rb | `app/models/entities/lead.rb` | モデル | リードのデータモデル定義 |
| account.rb | `app/models/entities/account.rb` | モデル | 取引先のデータモデル定義 |
| opportunity.rb | `app/models/entities/opportunity.rb` | モデル | 商談のデータモデル定義 |
| convert.js.haml | `app/views/leads/convert.js.haml` | ビュー | AJAX応答でフォーム表示 |
| _convert.html.haml | `app/views/leads/_convert.html.haml` | ビュー | 変換フォーム |
| _opportunity.html.haml | `app/views/leads/_opportunity.html.haml` | ビュー | 商談入力セクション |
| _convert_permissions.html.haml | `app/views/leads/_convert_permissions.html.haml` | ビュー | 権限設定セクション |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義 |
