# 機能設計書 60-ユーザー作成

## 概要

本ドキュメントは、Fat Free CRMにおける管理者向けユーザー作成機能の設計書である。システム管理者が新規ユーザーアカウントを作成するための機能について、処理仕様・データベース操作・コード構造を定義する。

### 本機能の処理概要

管理者が新規ユーザーアカウントを作成する機能である。ユーザー名、メールアドレス、パスワード、個人情報、管理者権限、グループ所属を設定してユーザーを作成する。システム設定によっては作成したユーザーが承認待ち状態になる場合がある。

**業務上の目的・背景**：新入社員やプロジェクトメンバーの追加時に、管理者がユーザーアカウントを迅速に作成できる必要がある。セルフサービス登録（機能No.54）とは異なり、管理者が権限設定やグループ所属を含めて完全なアカウント設定を行える。

**機能の利用シーン**：
- 新入社員のアカウント作成
- 外部パートナーへのアクセス権付与
- 管理者権限を持つユーザーの追加
- 特定のグループへ所属するユーザーの一括作成

**主要な処理内容**：
1. 管理画面からユーザー作成フォームを表示
2. ユーザー情報（ユーザー名、メール、パスワード、個人情報）を入力
3. 管理者権限フラグを設定
4. 所属グループを選択
5. フォーム送信でユーザーレコードを作成
6. システム設定に応じて承認待ち状態に設定
7. ユーザー一覧を更新

**関連システム・外部連携**：特になし

**権限による制御**：管理者（admin=true）のみアクセス可能

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 36 | ユーザー管理新規作成フォーム | 主画面 | 管理者によるユーザー作成 |

## 機能種別

ユーザー作成処理 / INSERT操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| user[username] | String | Yes | ユーザー名 | 必須、一意、英数字・ハイフン・アンダースコアのみ |
| user[email] | String | Yes | メールアドレス | 必須、一意、メール形式 |
| user[password] | String | No | パスワード | 任意（未指定時は未設定） |
| user[password_confirmation] | String | No | パスワード確認 | passwordと一致 |
| user[admin] | Boolean | No | 管理者権限 | true/false |
| user[first_name] | String | No | 名 | なし |
| user[last_name] | String | No | 姓 | なし |
| user[title] | String | No | 役職 | なし |
| user[company] | String | No | 会社名 | なし |
| user[group_ids] | Array | No | 所属グループID配列 | 有効なグループID |

### 入力データソース

- 画面入力（ユーザー作成フォーム）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 作成されたユーザー | User | 新規ユーザーレコード |
| JavaScript | String | ユーザー一覧を更新するJS |

### 出力先

- usersテーブル（新規レコード）
- groups_usersテーブル（グループ所属）
- 画面（ユーザー一覧更新）

## 処理フロー

### 処理シーケンス

```
1. ユーザー作成フォーム表示（GET /admin/users/new）
   └─ Admin::UsersController#new
2. フォーム入力
   └─ ユーザー情報、管理者フラグ、グループ所属
3. フォーム送信（POST /admin/users）
   └─ Admin::UsersController#create
4. バリデーション実行
   ├─ username: 一意性、形式チェック
   └─ email: 一意性、形式チェック
5. 承認待ちチェック
   └─ suspend_if_needs_approval（Setting.user_signup確認）
6. ユーザーレコード作成
   └─ @user.save
7. グループ関連付け
   └─ groups_usersへINSERT
8. JSレスポンス
   └─ ユーザー一覧に新規ユーザーを追加
```

### フローチャート

```mermaid
flowchart TD
    A[作成フォーム表示] --> B[ユーザー情報入力]
    B --> C[フォーム送信]
    C --> D{バリデーション}
    D -->|失敗| E[エラー表示]
    D -->|成功| F[suspend_if_needs_approval]
    F --> G[ユーザー保存]
    G --> H{保存成功?}
    H -->|Yes| I[一覧更新JS]
    H -->|No| E
    E --> B
    I --> J[ハイライト表示]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-60-01 | 管理者限定 | 管理者のみがユーザーを作成可能 | 常時 |
| BR-60-02 | ユーザー名一意性 | ユーザー名はシステム内で一意 | 常時 |
| BR-60-03 | メール一意性 | メールアドレスはシステム内で一意 | 常時 |
| BR-60-04 | 承認フロー | needs_approval設定時は承認待ち状態で作成 | 設定依存 |
| BR-60-05 | 管理者自己保護 | 現在の管理者は自分のadmin権限を外せない | 編集時 |
| BR-60-06 | パスワード任意 | 管理者作成時はパスワード未設定可能 | 常時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ユーザー作成 | users | INSERT | 新規ユーザーレコード作成 |
| グループ関連付け | groups_users | INSERT | グループ所属レコード作成 |

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

#### users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | username | 入力値 | 必須 |
| INSERT | email | 入力値 | 必須 |
| INSERT | encrypted_password | bcryptハッシュ値 | パスワード指定時 |
| INSERT | password_salt | ソルト値 | パスワード指定時 |
| INSERT | admin | 入力値（true/false） | 管理者権限 |
| INSERT | first_name | 入力値 | 任意 |
| INSERT | last_name | 入力値 | 任意 |
| INSERT | title | 入力値 | 任意 |
| INSERT | company | 入力値 | 任意 |
| INSERT | sign_in_count | 0 | 初期値 |
| INSERT | suspended_at | 現在日時またはNULL | needs_approval時に設定 |

#### groups_users

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | バリデーションエラー | ユーザー名が既に使用されている | エラーメッセージ表示 |
| - | バリデーションエラー | メールアドレスが既に使用されている | エラーメッセージ表示 |
| - | バリデーションエラー | パスワードと確認が不一致 | エラーメッセージ表示 |
| - | バリデーションエラー | ユーザー名の形式が不正 | エラーメッセージ表示 |
| - | バリデーションエラー | メールアドレスの形式が不正 | エラーメッセージ表示 |

### リトライ仕様

- バリデーション失敗時は同一フォームで修正・再試行可能

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

ユーザーレコード作成とグループ関連付けは同一トランザクションで処理。

## パフォーマンス要件

- レスポンス時間: 1秒以内
- パスワードハッシュ化にbcryptを使用

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

- 管理者のみアクセス可能（Admin::ApplicationController#require_admin）
- パスワードはbcryptでハッシュ化して保存
- CSRFトークン検証あり
- 自動補完無効（autocomplete: 'off'）

## 備考

- load_resourceはcreateアクションでは除外（User.new(user_params)で明示的に作成）
- 作成成功時はユーザー一覧に新規ユーザーをプリペンドしてハイライト表示
- 作成失敗時はフォームを再表示してエラーを表示

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | user.rb | `app/models/users/user.rb` | ユーザーモデル、バリデーション、関連 |
| 1-2 | schema.rb | `db/schema.rb` | usersテーブル、groups_usersテーブル |

**読解のコツ**:
- **51行目（user.rb）**: `before_create :suspend_if_needs_approval`
- **65行目（user.rb）**: `has_and_belongs_to_many :groups`
- **87-98行目（user.rb）**: バリデーションルール
- **182-184行目（user.rb）**: `suspend_if_needs_approval`メソッド

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | admin/users_controller.rb | `app/controllers/admin/users_controller.rb` | new, createアクション |
| 2-2 | routes.rb | `config/routes.rb` | 管理者ルーティング |

**主要処理フロー**:
1. **31-33行目（admin/users_controller.rb）**: newアクション
2. **46-52行目（admin/users_controller.rb）**: createアクション - User.new、suspend_if_needs_approval、save
3. **104-128行目（admin/users_controller.rb）**: user_params - Strong Parameters

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | new.js.haml | `app/views/admin/users/new.js.haml` | フォーム表示JS |
| 3-2 | _new.html.haml | `app/views/admin/users/_new.html.haml` | 作成フォーム |
| 3-3 | _profile.html.haml | `app/views/admin/users/_profile.html.haml` | プロファイル入力フォーム |
| 3-4 | create.js.haml | `app/views/admin/users/create.js.haml` | 作成結果のJS |

**主要処理フロー**:
- **_new.html.haml**: form_forでフォーム生成、autocomplete: 'off'
- **_profile.html.haml**: username, email, password, admin, 個人情報, グループ選択
- **create.js.haml**: 成功時は一覧にプリペンド、失敗時はフォーム再表示

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

```
GET /admin/users/new
    │
    └─ Admin::UsersController#new
           └─ new.js.haml
                  └─ _new.html.haml
                         └─ _profile.html.haml

POST /admin/users
    │
    └─ Admin::UsersController#create
           │
           ├─ User.new(user_params)
           │
           ├─ @user.suspend_if_needs_approval
           │
           ├─ @user.save
           │      ├─ バリデーション
           │      └─ groups_usersへINSERT
           │
           └─ respond_with(@user)
                  └─ create.js.haml
                         ├─ 成功時: 一覧にプリペンド、ハイライト
                         └─ 失敗時: フォーム再表示
```

### データフロー図

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

ユーザー情報
  │
  ├─ username ───▶ バリデーション ───────────▶ usersテーブル
  ├─ email ──────▶ 一意性チェック
  ├─ password ───▶ bcryptハッシュ化 ─────────▶ encrypted_password
  ├─ admin ──────▶ 直接設定
  └─ group_ids ──▶ グループ関連付け ─────────▶ groups_usersテーブル
                           │
                           └───────────────────▶ JSレスポンス
                                                   │
                                                   ▼
                                              一覧更新・ハイライト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| admin/users_controller.rb | `app/controllers/admin/users_controller.rb` | コントローラー | ユーザー作成 |
| user.rb | `app/models/users/user.rb` | モデル | ユーザーモデル |
| new.js.haml | `app/views/admin/users/new.js.haml` | ビュー | フォーム表示JS |
| _new.html.haml | `app/views/admin/users/_new.html.haml` | ビュー | 作成フォーム |
| _profile.html.haml | `app/views/admin/users/_profile.html.haml` | ビュー | プロファイル入力 |
| create.js.haml | `app/views/admin/users/create.js.haml` | ビュー | 作成結果JS |
| routes.rb | `config/routes.rb` | 設定 | ルーティング |
| schema.rb | `db/schema.rb` | スキーマ | テーブル定義 |
