# 機能設計書 71-タグ編集

## 概要

本ドキュメントは、Fat Free CRM の管理者向けタグ編集機能の設計を定義する。この機能により、システム管理者は既存タグの名前を変更することができる。

### 本機能の処理概要

タグ編集機能は、CRM システム全体で使用されるタグの名前を更新する管理者専用機能である。タグは取引先、リード、連絡先、商談、キャンペーンなど複数のエンティティに紐付けられており、タグ名の変更は全ての関連エンティティに即座に反映される。

**業務上の目的・背景**：業務運用の中でタグの命名規則が変更になったり、タグ名の誤りを訂正したりする必要が生じる。この機能により、管理者はタグの整理・統一を行い、CRM データの分類精度を維持することができる。また、組織の用語変更やブランディング変更に伴うタグ名の更新にも対応可能である。

**機能の利用シーン**：
- タグ名のタイプミスを修正する場合
- 命名規則の標準化に伴いタグ名を変更する場合
- 業務用語の変更に伴いタグ名を更新する場合
- 類似タグの整理・統合前の名前変更

**主要な処理内容**：
1. 編集対象タグの取得（IDによる検索）
2. 編集フォームの表示（AJAXによるモーダル表示）
3. タグ名の更新処理（バリデーション含む）
4. 更新結果のレスポンス返却（HTML/JS形式）

**関連システム・外部連携**：本機能は外部システムとの連携はなく、Fat Free CRM 内部のデータベースのみを操作する。ActsAsTaggableOn gem を拡張したTag モデルを使用している。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 42 | タグ管理画面 | 主画面 | タグ一覧からの編集ボタン押下、編集フォーム表示、更新実行 |

## 機能種別

CRUD操作（Update）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | Integer | Yes | 編集対象タグのID | 存在するタグIDであること |
| tag[name] | String | Yes | 新しいタグ名 | 空でないこと、一意であること |
| tag[taggings_count] | Integer | No | タグ使用回数（通常は編集しない） | 整数であること |

### 入力データソース

- 画面入力（タグ管理画面の編集フォーム）
- URLパラメータ（タグID）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| @tag | Tag | 更新されたタグオブジェクト |
| @previous | Tag/Integer | 前の編集対象（連続編集用） |

### 出力先

- 画面表示（AJAX応答によるタグ一覧の更新）
- HTMLまたはJavaScript形式でのレスポンス

## 処理フロー

### 処理シーケンス

```
1. editアクション呼び出し
   └─ タグIDによる対象タグの取得（load_resource）
   └─ 前回編集対象の取得（detect_previous_id）
2. 編集フォームの表示
   └─ AJAXリクエストに対してモーダルフォームを返却
3. updateアクション呼び出し
   └─ Strong Parametersによるパラメータフィルタリング
   └─ タグ属性の更新（tag.update）
4. レスポンス返却
   └─ respond_with による適切な形式での応答
```

### フローチャート

```mermaid
flowchart TD
    A[編集ボタン押下] --> B[editアクション]
    B --> C[タグ取得]
    C --> D{タグ存在?}
    D -->|No| E[404エラー]
    D -->|Yes| F[編集フォーム表示]
    F --> G[フォーム入力]
    G --> H[更新ボタン押下]
    H --> I[updateアクション]
    I --> J[パラメータ検証]
    J --> K{バリデーション成功?}
    K -->|No| L[エラー表示]
    K -->|Yes| M[タグ更新]
    M --> N[一覧更新]
    L --> G
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-71-01 | 管理者権限必須 | タグ編集は管理者ユーザーのみ実行可能 | 常時 |
| BR-71-02 | タグ名一意性 | タグ名はシステム内で一意である必要がある | タグ名変更時 |
| BR-71-03 | 関連エンティティ自動反映 | タグ名変更は紐付けられた全エンティティに自動反映 | タグ更新成功時 |

### 計算ロジック

特になし（単純な属性更新）

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| タグ取得 | tags | SELECT | IDによるタグ検索 |
| タグ更新 | tags | UPDATE | name, updated_at の更新 |

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

#### tags テーブル

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | name | フォーム入力値 | タグ名 |
| UPDATE | updated_at | 現在時刻 | 自動更新 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 404 | NotFound | 指定IDのタグが存在しない | エラーページ表示 |
| 422 | ValidationError | タグ名が空または重複 | フォームにエラーメッセージ表示 |
| 403 | Forbidden | 管理者権限がない | ログインページへリダイレクト |

### リトライ仕様

リトライは不要（ユーザーが再度更新ボタンを押下することで対応）

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

単一レコードの更新のため、ActiveRecordのデフォルトトランザクション（自動コミット）を使用。明示的なトランザクション制御は行わない。

## パフォーマンス要件

- レスポンス時間：1秒以内（AJAX応答）
- 同時実行：管理者のみのアクセスのため、同時実行数は限定的

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

- 管理者認証必須（before_action :require_admin_user）
- Strong Parameters によるマスアサインメント防止
- CSRF トークン検証（Rails標準）
- XSS 対策（ビューでのエスケープ処理）

## 備考

- ActsAsTaggableOn gem の Tag クラスを継承したカスタム Tag モデルを使用
- タグはフィールドグループ（FieldGroup）と関連付けられている場合があり、その場合は削除制限がかかる

---

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

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

### 推奨読解順序

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

Tag モデルは ActsAsTaggableOn gem の Tag クラスを継承しており、FieldGroup との関連を持つ。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | tag.rb | `app/models/polymorphic/tag.rb` | Tagモデルの構造、FieldGroupとの関連、削除前バリデーション |

**読解のコツ**: ActsAsTaggableOn::Tag を継承しているため、基本的なタグ機能（name, taggings_count等）は親クラスで定義されている。Fat Free CRM 固有の拡張部分のみがこのファイルに記述されている。

**主要処理フロー**:
- **9行目**: `before_destroy :no_associated_field_groups` - 削除前にFieldGroupとの関連をチェック
- **12-14行目**: `no_associated_field_groups` メソッド - 関連するFieldGroupがある場合は削除を禁止

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

タグ編集のコントローラーアクションを確認する。

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

**主要処理フロー**:
- **8行目**: `Admin::ApplicationController` を継承 - 管理者権限チェックを継承
- **11行目**: `load_resource` - CanCanCan による自動リソースロード
- **29-32行目**: `edit` アクション - 編集フォーム表示、前回編集対象の取得
- **46-50行目**: `update` アクション - タグ属性の更新処理
- **68-70行目**: `tag_params` メソッド - Strong Parameters によるパラメータフィルタリング

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

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

**主要処理フロー**:
- **9行目**: `before_action :require_admin_user` - 全アクションで管理者権限をチェック
- **25-30行目**: `require_admin_user` メソッド - ユーザー認証と管理者権限の確認

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

```
Admin::TagsController
    │
    ├─ Admin::ApplicationController
    │      └─ require_admin_user（管理者権限チェック）
    │
    ├─ load_resource（CanCanCan）
    │      └─ Tag.find(params[:id])
    │
    ├─ edit アクション
    │      └─ detect_previous_id（前回編集対象取得）
    │
    └─ update アクション
           ├─ tag_params（Strong Parameters）
           └─ @tag.update（ActiveRecord）
                  └─ tags テーブル更新
```

### データフロー図

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

タグID(URL) ───────▶ TagsController#edit ───▶ 編集フォーム(HTML/JS)
                          │
                          ▼
                     Tag.find
                          │
                          ▼
                     tags テーブル

tag[name](Form) ──▶ TagsController#update ──▶ 更新結果(HTML/JS)
                          │
                          ▼
                     tag_params
                          │
                          ▼
                     @tag.update
                          │
                          ▼
                     tags テーブル更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| tag.rb | `app/models/polymorphic/tag.rb` | モデル | Tagモデル定義 |
| tags_controller.rb | `app/controllers/admin/tags_controller.rb` | コントローラー | タグCRUD処理 |
| application_controller.rb | `app/controllers/admin/application_controller.rb` | コントローラー | 管理者基底コントローラー |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（200-204行目） |
