# 機能設計書 73-カスタムフィールド管理

## 概要

本ドキュメントは、Fat Free CRM の管理者向けカスタムフィールド管理機能の設計を定義する。この機能により、システム管理者はエンティティ（取引先、連絡先、リード、商談、キャンペーン）に追加するカスタムフィールドの一覧を確認・管理することができる。

### 本機能の処理概要

カスタムフィールド管理機能は、CRM システムの柔軟性を高めるための管理者専用機能である。標準フィールドでは対応できない業務固有の項目を、各エンティティに動的に追加することができる。本機能では、登録済みのカスタムフィールドとフィールドグループの一覧を表示し、フィールドの構成状況を把握することができる。

**業務上の目的・背景**：各組織には固有の業務プロセスがあり、標準のCRMフィールドだけでは必要な情報を管理できないことがある。例えば、業界特有の分類コード、社内管理番号、カスタム属性などを追加する必要がある。カスタムフィールド管理機能により、システムを再構築することなく、業務要件に合わせたフィールドの追加・管理が可能となる。

**機能の利用シーン**：
- 新しいカスタムフィールドを追加する前に既存フィールドの構成を確認する場合
- フィールドグループの構成状況を把握する場合
- 各エンティティに設定されているカスタムフィールドの棚卸しを行う場合
- カスタムフィールドの表示順や設定を確認する場合

**主要な処理内容**：
1. フィールドグループ一覧の取得（エンティティタイプ別）
2. 各フィールドグループに属するフィールドの取得
3. コアフィールドとカスタムフィールドの区別表示
4. エンティティタイプ切り替え機能

**関連システム・外部連携**：本機能は外部システムとの連携はなく、Fat Free CRM 内部のデータベースのみを参照する。カスタムフィールドは動的にデータベースカラムを追加する仕組みを採用している。

**権限による制御**：この機能は管理者権限を持つユーザーのみが実行可能である。一般ユーザーは管理画面にアクセスできず、カスタムフィールドの管理は行えない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 43 | カスタムフィールド管理画面 | 主画面 | カスタムフィールド一覧表示、フィールドグループ表示 |
| 44 | カスタムフィールド詳細画面 | 参照画面 | カスタムフィールド詳細確認 |

## 機能種別

CRUD操作（Read / 一覧表示）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| klass_name | String | No | 表示対象のエンティティクラス名（Account, Contact, Lead, Opportunity, Campaign） | 有効なエンティティ名であること |

### 入力データソース

- URLパラメータ（エンティティタイプ選択）
- タブ切り替え操作（ユーザー操作）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| field_groups | Array<FieldGroup> | フィールドグループの一覧 |
| fields | Array<Field> | 各グループに属するフィールドの一覧 |
| klass_name | String | 現在選択中のエンティティクラス名 |

### 出力先

- 画面表示（カスタムフィールド管理画面）
- HTML形式でのレスポンス

## 処理フロー

### 処理シーケンス

```
1. indexアクション呼び出し
   └─ 管理者権限チェック（before_action）
   └─ 現在タブの設定（setup_current_tab）
2. フィールドグループの取得
   └─ FieldGroup.where(klass_name: klass_name)
   └─ 各グループに属するフィールドの取得（has_many :fields）
3. 一覧画面の表示
   └─ エンティティタイプ別タブ
   └─ フィールドグループごとのフィールド一覧
```

### フローチャート

```mermaid
flowchart TD
    A[管理画面アクセス] --> B{管理者権限?}
    B -->|No| C[リダイレクト]
    B -->|Yes| D[indexアクション]
    D --> E[エンティティタイプ取得]
    E --> F[FieldGroup取得]
    F --> G[各グループのField取得]
    G --> H[一覧画面表示]
    H --> I{タブ切り替え?}
    I -->|Yes| E
    I -->|No| J[操作待ち]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-73-01 | 管理者権限必須 | カスタムフィールド管理は管理者ユーザーのみ実行可能 | 常時 |
| BR-73-02 | エンティティ単位表示 | フィールドはエンティティタイプごとに分類して表示 | 一覧表示時 |
| BR-73-03 | グループ単位整理 | フィールドはフィールドグループごとにまとめて表示 | 一覧表示時 |
| BR-73-04 | コア/カスタム区別 | CoreFieldとCustomFieldを区別して表示 | 一覧表示時 |

### 計算ロジック

特になし（参照処理のみ）

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| フィールドグループ取得 | field_groups | SELECT | klass_nameによるグループ検索 |
| フィールド取得 | fields | SELECT | field_group_idによるフィールド検索 |

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

#### field_groups テーブル

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, name, label, klass_name, position, tag_id | WHERE klass_name = :klass_name | エンティティ別取得 |

#### fields テーブル

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, type, name, label, as, required, disabled, position, field_group_id | WHERE field_group_id IN (:group_ids) ORDER BY position | グループ別取得 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 403 | Forbidden | 管理者権限がない | ログインページへリダイレクト |
| 404 | NotFound | 無効なエンティティタイプ指定 | デフォルトエンティティで表示 |

### リトライ仕様

リトライは不要（参照処理のみ）

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

読み取り専用のため、トランザクション制御は不要。

## パフォーマンス要件

- レスポンス時間：2秒以内
- N+1問題の回避（includes によるEager Loading）

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

- 管理者認証必須（before_action :require_admin_user）
- 読み取り専用のため、データ改ざんリスクはなし
- XSS 対策（ビューでのエスケープ処理）

## 備考

- Field モデルは STI（Single Table Inheritance）を使用し、CoreField と CustomField を区別
- CustomField は動的にデータベースカラムを追加する仕組みを採用
- フィールドグループはタグと関連付けることができ、タグ条件に応じた表示制御が可能

---

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

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

### 推奨読解順序

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

カスタムフィールド機能のデータモデルを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | field.rb | `app/models/fields/field.rb` | Fieldモデルの基底クラス、STI構造、バリデーション |
| 1-2 | field_group.rb | `app/models/fields/field_group.rb` | FieldGroupモデル、Fieldとの関連 |
| 1-3 | custom_field.rb | `app/models/fields/custom_field.rb` | CustomFieldモデル、動的カラム追加 |

**読解のコツ**: Field モデルは STI（Single Table Inheritance）を使用しており、type カラムでサブクラス（CoreField, CustomField）を区別する。`BASE_FIELD_TYPES` 定数でサポートされるフィールドタイプを定義している。

**主要処理フロー**:
- **field.rb 31-36行目**: `serialize` によるcollectionとsettingsの設定
- **field.rb 37行目**: `belongs_to :field_group` - グループとの関連
- **field.rb 45-60行目**: `BASE_FIELD_TYPES` - サポートされるフィールドタイプ
- **field_group.rb 24行目**: `has_many :fields` - フィールドとの1対多関連

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

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

**主要処理フロー**:
- **9行目**: `before_action :setup_current_tab` - タブ設定
- **15-16行目**: `index` アクション - 一覧表示（空のアクション、ビューで処理）
- **123-125行目**: `setup_current_tab` - 現在タブを 'admin/fields' に設定

#### Step 3: 管理者コントローラー基底クラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | application_controller.rb | `app/controllers/admin/application_controller.rb` | 管理者権限チェックの実装 |

**主要処理フロー**:
- **9行目**: `before_action :require_admin_user` - 全アクションで管理者権限をチェック

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

```
Admin::FieldsController
    │
    ├─ Admin::ApplicationController
    │      └─ require_admin_user（管理者権限チェック）
    │
    ├─ setup_current_tab
    │      └─ set_current_tab('admin/fields')
    │
    └─ index アクション
           └─ ビュー処理
                  ├─ FieldGroup.where(klass_name: ...)
                  │      └─ fields（has_many関連）
                  │
                  └─ Field の一覧表示
                         ├─ CoreField
                         └─ CustomField
```

### データフロー図

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

klass_name(URL) ──▶ FieldsController#index ──▶ 一覧画面(HTML)
                          │
                          ▼
                     ビュー処理
                          │
                          ├─ FieldGroup.where(klass_name)
                          │      │
                          │      ▼
                          │  field_groups テーブル
                          │
                          └─ field_group.fields
                                 │
                                 ▼
                             fields テーブル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| field.rb | `app/models/fields/field.rb` | モデル | Fieldモデル基底クラス |
| custom_field.rb | `app/models/fields/custom_field.rb` | モデル | CustomFieldモデル |
| core_field.rb | `app/models/fields/core_field.rb` | モデル | CoreFieldモデル |
| field_group.rb | `app/models/fields/field_group.rb` | モデル | FieldGroupモデル |
| custom_field_pair.rb | `app/models/fields/custom_field_pair.rb` | モデル | ペアフィールドモデル |
| fields_controller.rb | `app/controllers/admin/fields_controller.rb` | コントローラー | フィールドCRUD処理 |
| application_controller.rb | `app/controllers/admin/application_controller.rb` | コントローラー | 管理者基底コントローラー |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（190-198, 206-207行目） |
