# 画面設計書 40-グループ管理新規作成フォーム

## 概要

本ドキュメントは、Fat Free CRMにおけるグループ管理新規作成フォーム（管理者用）の設計仕様を記載する。本画面は管理者が新規グループを作成するためのフォームを提供する。

### 本画面の処理概要

本画面は、管理者がシステム内に新規グループを作成するためのフォームを提供する。グループ名と所属ユーザーを指定し、グループを作成する。Ajax通信でモーダル/インライン形式で表示される。

**業務上の目的・背景**：CRMシステムでユーザーをグルーピングし、アクセス権限を効率的に管理するための機能を提供する。営業チームの部署やプロジェクトチームなど、業務上のグループを作成することで、エンティティ（取引先、商談、連絡先等）へのアクセス権限をグループ単位で付与できるようになる。新しい部署の設立やチーム編成時に使用される管理者向けの機能である。

**画面へのアクセス方法**：以下の方法でアクセス可能：
1. グループ管理一覧画面で「Create Group」リンクをクリック
2. URL `/admin/groups/new` に直接アクセス（Ajax形式）

**主要な操作・処理内容**：
1. グループ名の入力
2. 所属ユーザーの選択（複数選択可）
3. グループ作成の実行

**画面遷移**：
- 遷移元：グループ管理一覧画面
- 遷移先：グループ管理一覧画面（作成成功後）

**権限による表示制御**：管理者（admin）ユーザーのみがアクセス可能。Admin::ApplicationControllerの認証・認可により制御される。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 66 | グループ作成 | 主機能 | 新規グループ作成 |

## 画面種別

登録（管理 / モーダル / Ajax）

## URL/ルーティング

| HTTPメソッド | URL | コントローラ#アクション | 説明 |
|-------------|-----|----------------------|------|
| GET | /admin/groups/new | admin/groups#new | 新規作成フォーム取得 |
| POST | /admin/groups | admin/groups#create | グループ作成実行 |

## 入出力項目

| 項目名 | 項目ID | 入力タイプ | 必須 | 備考 |
|--------|--------|-----------|------|------|
| グループ名 | name | text | ○ | 一意性バリデーションあり |
| ユーザー | user_ids | select (multiple) | ○ | select2で複数選択 |

## 表示項目

フォーム入力項目のみ。

## イベント仕様

### 1-フォーム表示

**トリガー**: 「Create Group」リンクのクリック

**処理フロー**:
1. Ajax で GET /admin/groups/new リクエストが送信される
2. Admin::GroupsController#new アクションが呼び出される
3. new.js.haml が応答し、_new.html.haml パーシャルを #create_group 領域に展開

**コントローラ処理（admin/groups_controller.rb 26-28行目）**:
```ruby
def new
  respond_with(@group)
end
```

### 2-グループ作成

**トリガー**: 「Create Group」ボタン押下

**処理フロー**:
1. Ajax で POST /admin/groups リクエストが送信される
2. Admin::GroupsController#create アクションが呼び出される
3. @group.attributes = group_params で属性を設定
4. @group.save でデータベースに保存
5. create.js.haml が応答し、一覧を更新

**コントローラ処理（admin/groups_controller.rb 38-44行目）**:
```ruby
def create
  @group.attributes = group_params
  @group.save

  respond_with(@group)
end
```

### 3-キャンセル

**トリガー**: 「Cancel」リンクのクリック

**処理フロー**:
1. link_to_cancel により フォームを閉じる
2. 一覧画面の状態に戻る

### 4-フォームクローズ

**トリガー**: 閉じるリンクのクリック

**処理フロー**:
1. link_to_close により フォームを非表示に

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| フォーム表示 | users | SELECT | ユーザー一覧を取得（select2用） |
| グループ作成 | groups | INSERT | 新規グループを登録 |
| グループ作成 | groups_users | INSERT | グループ・ユーザー関連を登録 |

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

#### groups

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name | フォーム入力値 | |
| INSERT | created_at | 現在日時 | 自動設定 |
| INSERT | updated_at | 現在日時 | 自動設定 |

#### groups_users（中間テーブル）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | group_id | 作成されたグループID | |
| INSERT | user_id | 選択されたユーザーID | |

## メッセージ仕様

| 種別 | メッセージキー | 表示内容 | 表示条件 |
|------|--------------|---------|---------|
| ラベル | create_group | グループ作成 | フォームタイトル、送信ボタン |
| ラベル | name | 名前 | 入力フィールドラベル |
| ラベル | users | ユーザー | 入力フィールドラベル |
| エラー | name_required | グループ名を入力してください | name空白時（presence） |
| エラー | name_taken | このグループ名は既に使用されています | name重複時（uniqueness） |

## 例外処理

| 例外 | 対応 |
|------|------|
| バリデーションエラー | エラーメッセージをフォーム上部に表示 |
| グループ名重複 | バリデーションエラーとして表示 |
| 未認証アクセス | ログイン画面へリダイレクト |
| 管理者以外のアクセス | 403 Forbidden を返却 |

## 備考

- フォームは Ajax（remote: true）で送信される
- one_submit_only ヘルパーで二重送信を防止
- autocomplete: 'off' でブラウザの自動入力を無効化
- select2 を使用してユーザー選択をUIフレンドリーに
- _form.html.haml パーシャルを共有して入力フォームを構成
- ユーザー選択は User.all.map {|u| [u.full_name, u.id]} で全ユーザーを選択肢として表示

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | group.rb | `app/models/users/group.rb` | バリデーション（12行目）、アソシエーション（9行目） |
| 1-2 | schema.rb | `db/schema.rb` | groupsテーブル（273-277行目）、groups_usersテーブル（279-285行目） |

**読解のコツ**: Groupモデルは `validates :name, presence: true, uniqueness: true`（12行目）でグループ名の必須・一意性を検証する。

```ruby
class Group < ActiveRecord::Base
  has_and_belongs_to_many :users
  has_many :permissions
  validates :name, presence: true, uniqueness: true
end
```

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | routes.rb | `config/routes.rb` | admin/groups リソース（166行目） |
| 2-2 | admin/groups_controller.rb | `app/controllers/admin/groups_controller.rb` | new, create アクション、group_params メソッド |

**主要処理フロー**:
1. **26-28行目**: new アクションでフォーム表示
2. **40行目**: `@group.attributes = group_params` で属性設定
3. **41行目**: `@group.save` で保存
4. **64-66行目**: `group_params` で `:name` と `user_ids: []` を許可

```ruby
def group_params
  params.require(:group).permit(:name, user_ids: [])
end
```

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | _new.html.haml | `app/views/admin/groups/_new.html.haml` | フォーム構造（1-13行目） |
| 3-2 | _form.html.haml | `app/views/admin/groups/_form.html.haml` | 共通入力フィールド（1-11行目） |

**主要処理フロー**:
- **_new.html.haml 2行目**: `form_for([:admin, @group], html: one_submit_only.merge({autocomplete: 'off'}), remote: true)` でAjaxフォーム生成
- **_new.html.haml 7行目**: `render "admin/groups/form", f: f` でフォーム入力部分を描画
- **_form.html.haml 5-6行目**: グループ名入力フィールド
- **_form.html.haml 9-11行目**: ユーザー選択（select2、複数選択）

```haml
= f.select :user_ids, User.all.map {|u| [u.full_name, u.id]}, {}, multiple: true, class: 'select2'
```

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

```
リクエスト: POST /admin/groups
    │
    ├─ routes.rb
    │      └─ namespace :admin { resources :groups }
    │
    ├─ Admin::GroupsController
    │      ├─ load_resource (CanCanCan)
    │      │
    │      └─ create (38-44行目)
    │             ├─ @group.attributes = group_params
    │             │      └─ group_params (64-66行目)
    │             │             ├─ :name
    │             │             └─ user_ids: []
    │             │
    │             └─ @group.save
    │                    ├─ validations
    │                    │      ├─ presence: name
    │                    │      └─ uniqueness: name
    │                    ├─ INSERT INTO groups
    │                    └─ INSERT INTO groups_users (for each user_id)
    │
    └─ create.js.haml
           └─ 一覧更新/エラー表示
```

### データフロー図

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

フォーム入力     ───▶ Admin::GroupsController  ───▶ groups テーブル
POST /admin/groups    │                            │
                      ├─ group_params              ├─ INSERT group
                      │      ├─ :name              │
                      │      └─ user_ids: []       └─ INSERT groups_users
                      │                                 (for each user_id)
                      └─ @group.save
                             └─ validations
                                    ├─ presence
                                    └─ uniqueness
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| _new.html.haml | `app/views/admin/groups/_new.html.haml` | パーシャル | 新規作成フォーム |
| _form.html.haml | `app/views/admin/groups/_form.html.haml` | パーシャル | フォーム入力フィールド |
| new.js.haml | `app/views/admin/groups/new.js.haml` | JavaScript | フォーム表示処理 |
| create.js.haml | `app/views/admin/groups/create.js.haml` | JavaScript | 作成結果処理 |
| groups_controller.rb | `app/controllers/admin/groups_controller.rb` | コントローラ | 管理者用グループ操作 |
| group.rb | `app/models/users/group.rb` | モデル | Groupモデル定義 |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義 |
