# 画面設計書 42-タグ管理画面

## 概要

本ドキュメントは、Fat Free CRMの管理画面におけるタグ管理画面の設計書です。管理者がシステム全体で使用されるタグの一覧表示、作成、編集、削除を行うための画面を定義します。

### 本画面の処理概要

本画面は、CRMシステム内で使用されるタグを一元管理するための管理画面です。タグは取引先、連絡先、リード、商談などの各エンティティに対して付与でき、データの分類やフィルタリングに活用されます。また、タグはカスタムフィールドグループと関連付けることで、特定のタグが付いたレコードに対して追加フィールドを表示する機能も提供します。

**業務上の目的・背景**：CRMデータを効率的に分類・検索するため、タグによる横断的なラベリングが必要です。管理者がタグを一元管理することで、組織全体で統一されたタグ体系を維持し、データの整合性と検索効率を向上させます。また、AIプロンプト機能と連携してタグの提案を受けることも可能です。

**画面へのアクセス方法**：管理画面のナビゲーションから「Tags」タブを選択、または `/admin/tags` に直接アクセスします。管理画面トップからサイドバーのメニューを経由してもアクセス可能です。

**主要な操作・処理内容**：
1. 全タグの一覧表示（タグ名、使用状況を含む）
2. 新規タグの作成（Create Tagリンクからインラインフォーム表示）
3. 既存タグの編集
4. タグの削除（関連するフィールドグループがない場合のみ）
5. タグの使用状況確認（どのエンティティで何件使用されているか）
6. AIプロンプトによるタグ提案の表示（設定済みの場合）

**画面遷移**：管理画面トップ（No.34）から遷移します。新規作成・編集はインラインフォームで行われ、ページ遷移は発生しません。削除時は確認ダイアログが表示されます。

**権限による表示制御**：管理者（admin権限を持つユーザー）のみがアクセス可能です。一般ユーザーがアクセスしようとした場合は、管理画面トップへリダイレクトされます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 69 | タグ管理一覧 | 主機能 | 全タグの一覧表示 |
| 70 | タグ作成 | 補助機能 | 新規タグの作成 |
| 71 | タグ編集 | 補助機能 | 既存タグの名前変更 |
| 72 | タグ削除 | 補助機能 | タグの削除処理 |

## 画面種別

一覧（管理画面）

## URL/ルーティング

- **URL**: `/admin/tags`
- **HTTPメソッド**: GET（一覧表示）
- **ルーティング定義**: `config/routes.rb` 内の `namespace :admin do resources :tags, except: [:show] do member do get :confirm end end end`
- **コントローラ**: `Admin::TagsController#index`

## 入出力項目

本画面は主に一覧表示のため、直接の入力項目はありません。新規作成・編集時のフォーム項目は以下の通りです。

| 項目名 | 項目ID | データ型 | 必須 | 最大長 | 入力形式 | 備考 |
|--------|--------|----------|------|--------|----------|------|
| タグ名 | tag[name] | string | Yes | 255 | テキスト | 一意性制約あり（acts_as_taggable_on） |

## 表示項目

| 項目名 | 表示形式 | データソース | 備考 |
|--------|----------|--------------|------|
| タグ一覧 | リスト形式 | @tags = Tag.all | 全タグを表示 |
| タグ名 | テキスト | tag.name | 各タグの名前 |
| 使用状況 | テキスト | tag.model_tagging_counts | タグが付与されたエンティティの種類と件数 |
| 関連フィールドグループ | リスト | FieldGroup.where(tag_id: tag.id) | タグに関連付けられたフィールドグループ |
| 編集リンク | link | edit_admin_tag_path(tag) | インライン編集フォームを開く |
| 削除リンク/確認リンク | link | admin_tag_path(tag) / confirm_admin_tag_path(tag) | 条件に応じて表示変更 |
| 新規作成リンク | link | new_admin_tag_path | インラインフォームを開く |
| AIプロンプトリンク | link | - | AI設定がある場合のみ表示 |

## イベント仕様

### 1-新規作成リンク押下（Create Tag）

- **処理フロー**:
  1. `link_to_inline` によりAjaxリクエストで `GET /admin/tags/new` を呼び出し
  2. `Admin::TagsController#new` が実行される
  3. 新規作成フォームがインラインで表示される（`#create_tag` 領域に展開）

### 2-編集リンク押下（Edit）

- **処理フロー**:
  1. Ajaxリクエストで `GET /admin/tags/:id/edit` を呼び出し
  2. `Admin::TagsController#edit` が実行される
  3. 編集フォームがインラインで表示される
  4. `@previous` に前回編集したタグの情報が保持される（連続編集対応）

### 3-削除リンク押下（Delete）

- **条件**: 関連するフィールドグループがなく、タグ付けもない場合
- **処理フロー**:
  1. Ajaxリクエストで `DELETE /admin/tags/:id` を呼び出し
  2. `Admin::TagsController#destroy` が実行される
  3. タグが削除され、一覧から除去される

### 4-確認リンク押下（Confirm）

- **条件**: 関連するフィールドグループはないが、タグ付けがある場合
- **処理フロー**:
  1. Ajaxリクエストで `GET /admin/tags/:id/confirm` を呼び出し
  2. 削除確認ダイアログが表示される
  3. 確認後、削除処理が実行される

### 5-フィールドグループ関連時の削除制限

- **条件**: 関連するフィールドグループがある場合
- **処理**: 削除リンクがグレーアウトされ、削除不可となる

### 6-AIプロンプトリンク押下

- **条件**: `Setting[:about_my_business]` または `Setting[:how_i_plan_to_use_ffcrm]` が設定されている場合
- **処理**: AIによるタグ提案機能を呼び出す

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 新規作成 | tags | INSERT | 新しいタグレコードを作成 |
| 編集 | tags | UPDATE | タグ名を更新 |
| 削除 | tags | DELETE | タグレコードを削除 |
| 削除 | taggings | DELETE | 関連するタグ付けも削除される（CASCADE） |

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

#### tags

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name | フォーム入力値 `tag[name]` | 必須 |
| INSERT | taggings_count | 0 | デフォルト値 |
| INSERT | created_at | 現在時刻 | 自動設定 |
| UPDATE | name | フォーム入力値 `tag[name]` | - |
| UPDATE | updated_at | 現在時刻 | 自動設定 |
| DELETE | - | WHERE id = :id | before_destroyコールバックあり |

## メッセージ仕様

| メッセージ種別 | 条件 | メッセージ内容 | 表示位置 |
|---------------|------|---------------|----------|
| 空表示 | タグが存在しない | "shared/empty"パーシャル（No data to display） | 一覧領域 |
| 確認 | タグ付けありで削除時 | 確認ダイアログ（関連レコード数を表示） | モーダル |
| 情報 | フィールドグループ関連あり | "Delete"がグレー表示（削除不可） | 一覧各行 |

## 例外処理

| 例外条件 | 処理内容 | 表示・動作 |
|----------|----------|-----------|
| タグが見つからない | RecordNotFound例外 | 404エラーページを表示 |
| 権限不足（非管理者） | before_actionでリダイレクト | 管理画面トップへリダイレクト |
| 削除時にフィールドグループ関連あり | before_destroy で false 返却 | 削除が実行されない |
| 通信エラー | Ajaxエラーハンドリング | クライアント側でエラー表示 |

## 備考

- タグはacts_as_taggable_on gemを使用して実装されています。`Tag`モデルは`ActsAsTaggableOn::Tag`を継承しています。
- タグの使用状況は`model_tagging_counts`メソッドで集計され、エンティティ種別ごとの件数が表示されます。
- フィールドグループと関連付けられたタグは削除できません。これはデータの整合性を保つための制約です。
- AIプロンプト機能は、ビジネス情報が設定されている場合にのみ利用可能です。

---

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

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

### 推奨読解順序

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

タグとタグ付けの関連を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | tag.rb | `app/models/polymorphic/tag.rb` | Tagモデル、ActsAsTaggableOn::Tagの継承、before_destroyコールバック |
| 1-2 | schema.rb | `db/schema.rb` | tagsテーブル（406-410行目）、taggingsテーブル（394-404行目）の構造 |

**読解のコツ**: `ActsAsTaggableOn::Tag`を継承している点に注目し、gem由来の機能と独自拡張を区別してください。`model_tagging_counts`メソッドは独自実装です。

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

コントローラのアクションを確認します。

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

**主要処理フロー**:
1. **16-19行目**: `index` アクション - `Tag.all`で全タグを取得
2. **24-26行目**: `new` アクション - 新規タグオブジェクトを生成
3. **30-32行目**: `edit` アクション - 編集対象タグをロード、前回編集情報を保持
4. **37-41行目**: `create` アクション - タグを作成
5. **46-50行目**: `update` アクション - タグを更新
6. **55-59行目**: `destroy` アクション - タグを削除

#### Step 3: ビューテンプレートを理解する

一覧画面の構造を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.html.haml | `app/views/admin/tags/index.html.haml` | 一覧画面のメインテンプレート |
| 3-2 | _tag.html.haml | `app/views/admin/tags/_tag.html.haml` | 各タグ行のパーシャル |

**主要処理フロー**:
- **4行目（index）**: `link_to_inline` で新規作成リンクを生成
- **12-15行目（index）**: タグ一覧をパーシャルでレンダリング
- **17-19行目（index）**: AI設定がある場合にAIプロンプトリンクを表示
- **6-13行目（_tag）**: 編集・削除リンクの条件分岐

#### Step 4: ルーティングを理解する

URLとコントローラの対応を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | routes.rb | `config/routes.rb` | admin名前空間内のtagsリソース定義（200-204行目） |

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

```
ブラウザ（/admin/tags アクセス）
    │
    └─ GET /admin/tags
           │
           └─ Admin::TagsController#index
                  │
                  ├─ Tag.all
                  │      └─ ActsAsTaggableOn::Tag からの継承
                  │
                  └─ index.html.haml レンダリング
                         │
                         ├─ @tags.each
                         │      └─ _tag.html.haml
                         │             │
                         │             ├─ tag.model_tagging_counts
                         │             │      └─ Tagging.where(tag_id:).group().count
                         │             │
                         │             └─ FieldGroup.where(tag_id:)
                         │
                         └─ AI プロンプトリンク（条件付き）
                                └─ Setting[:about_my_business]
```

### データフロー図

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

URL アクセス
(/admin/tags) ───▶ TagsController#index ───▶ 一覧画面表示
                          │
                          └─ Tag.all
                                 │
                                 ├─ tags テーブル
                                 │
                                 └─ taggings テーブル
                                        (model_tagging_counts)

新規作成/編集 ───▶ TagsController#create/update
フォーム入力              │
 └─ tag[name]             └─ tag.update(tag_params)
                                 │
                                 └─▶ tags テーブル (INSERT/UPDATE)

削除リンク ───▶ TagsController#destroy
                      │
                      ├─ before_destroy :no_associated_field_groups
                      │      └─ FieldGroup.where(tag_id:).none?
                      │
                      └─▶ tags テーブル (DELETE)
                             └─▶ taggings テーブル (CASCADE DELETE)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| tag.rb | `app/models/polymorphic/tag.rb` | モデル | タグエンティティ、削除制約、使用状況集計 |
| tagging.rb | `app/models/polymorphic/tagging.rb` | モデル | タグ付け関連（acts_as_taggable_on） |
| tags_controller.rb | `app/controllers/admin/tags_controller.rb` | コントローラ | CRUDアクション処理 |
| index.html.haml | `app/views/admin/tags/index.html.haml` | ビュー | 一覧画面メインテンプレート |
| _tag.html.haml | `app/views/admin/tags/_tag.html.haml` | ビュー | タグ行パーシャル |
| routes.rb | `config/routes.rb` | 設定 | URLルーティング定義 |
| schema.rb | `db/schema.rb` | 設定 | データベーススキーマ |
| field_group.rb | `app/models/fields/field_group.rb` | モデル | フィールドグループ（タグとの関連） |
