# 機能設計書 64-ユーザーアカウント再有効化

## 概要

本ドキュメントは、Fat Free CRM の管理機能における「ユーザーアカウント再有効化」機能の設計を記述する。

### 本機能の処理概要

管理者が停止中のユーザーアカウントを再有効化するための機能である。再有効化されたユーザーは再びシステムにログインできるようになる。

**業務上の目的・背景**：長期休暇や休職から復帰した従業員、または誤って停止されたアカウントを再度有効にする必要がある場合に使用する。停止中に保持されていた全てのデータ・権限がそのまま利用可能となる。

**機能の利用シーン**：
- 長期休暇・育児休暇から復帰した従業員のアカウント再有効化
- 誤停止されたアカウントの復旧
- セキュリティ調査完了後のアカウント再開
- 承認待ち状態のユーザーの承認（needs_approval 設定時）

**主要な処理内容**：
1. 再有効化対象ユーザーの特定
2. suspended_at カラムの null 設定
3. 画面の即時更新（AJAX）

**関連システム・外部連携**：Devise 認証システムと連携。suspended_at が null になることで `active_for_authentication?` が true を返し、ログインが許可される。

**権限による制御**：本機能は管理者権限（admin: true）を持つユーザーのみが実行可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 34 | ユーザー管理一覧画面 | 主画面 | 再有効化リンクの表示元 |
| 35 | ユーザー管理詳細画面 | 補助機能 | 停止中アカウントの再有効化 |

## 機能種別

CRUD操作（Update）/ 状態管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | Integer | Yes | 再有効化対象ユーザーID | 存在するユーザーID |

### 入力データソース

- URL パラメータ（ユーザーID）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| @user | User | 再有効化後のユーザーオブジェクト |

### 出力先

- 画面表示（AJAX レスポンスによる部分更新）
- users テーブル（suspended_at カラム）

## 処理フロー

### 処理シーケンス

```
1. 管理者がユーザー一覧画面で再有効化リンクをクリック
   └─ 停止中のユーザーにのみ表示

2. 再有効化実行
   └─ AJAX リクエスト: PUT /admin/users/:id/reactivate

3. reactivate アクションで再有効化処理を実行
   └─ suspended_at に nil を設定

4. 結果を返却
   └─ ユーザー行を更新（アクティブ状態の表示に変更）
```

### フローチャート

```mermaid
flowchart TD
    A[再有効化リンククリック] --> B[PUT /admin/users/:id/reactivate]
    B --> C[load_resource でユーザー取得]
    C --> D[suspended_at = nil]
    D --> E[update_attribute 実行]
    E --> F[画面更新 JS 返却]
    F --> G[ユーザー行を更新表示]
    G --> H[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-64-01 | 即時反映 | 再有効化後、対象ユーザーは即座にログイン可能 | 常時 |
| BR-64-02 | データ復元 | 停止中に保持されていた全データ・権限がそのまま利用可能 | 常時 |
| BR-64-03 | 承認処理 | needs_approval 設定時、承認待ちユーザーの承認としても機能 | Setting.user_signup == :needs_approval |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| アカウント再有効化 | users | UPDATE | suspended_at カラムを null に設定 |

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

#### users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | suspended_at | nil | バリデーションスキップ（update_attribute） |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 認可エラー | 非管理者によるアクセス | ルート画面にリダイレクト |

### リトライ仕様

特になし（単純な UPDATE 操作のため）

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

`update_attribute` は単一カラムの更新であり、バリデーションをスキップして即時コミットされる。

## パフォーマンス要件

- AJAX リクエストのため、レスポンス時間は 500ms 以内を目標
- 単一カラムの UPDATE のみであり、特別なパフォーマンス考慮は不要

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

- 管理者権限チェック（before_action :require_admin_user）
- CSRF トークンによるクロスサイトリクエストフォージェリ対策

## 備考

- 再有効化されたユーザーは以下の状態になる：
  - `suspended?` が false を返す
  - `active_for_authentication?` が true を返す（他の条件も満たす場合）
  - ユーザー一覧で「Active」または「Admin」ステータスが表示される
- 承認待ちユーザー（awaits_approval? が true）を再有効化すると、承認済みとなりログイン可能になる

---

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

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

### 推奨読解順序

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

まず、ユーザーモデルの再有効化関連メソッドを理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | user.rb | `app/models/users/user.rb` | suspended? メソッド、awaits_approval? メソッド |
| 1-2 | schema.rb | `db/schema.rb` | users テーブルの suspended_at カラム |

**読解のコツ**:
- **111-113行目**: `suspended?` は `suspended_at != nil` で判定
- **116-118行目**: `awaits_approval?` は `suspended? && sign_in_count == 0 && Setting.user_signup == :needs_approval` で判定

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | users_controller.rb | `app/controllers/admin/users_controller.rb` | reactivate アクション |
| 2-2 | application_controller.rb | `app/controllers/admin/application_controller.rb` | 管理者権限チェック |

**主要処理フロー**:
- **96-100行目**: reactivate アクション

```ruby
def reactivate
  @user.update_attribute(:suspended_at, nil)
  respond_with(@user)
end
```

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | _user.html.haml | `app/views/admin/users/_user.html.haml` | 再有効化リンクの表示条件 |
| 3-2 | reactivate.js.haml | `app/views/admin/users/reactivate.js.haml` | 再有効化後の画面更新処理 |

**読解のコツ**:
- `_user.html.haml` の18-19行目で `user.suspended?` の場合に再有効化リンクを表示
- `reactivate.js.haml` は `suspend.js.haml` と同様の処理（行の再描画）

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | routes.rb | `config/routes.rb` | admin/users の reactivate ルート |

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

```
[Admin::UsersController#reactivate]
    │
    ├─ @user.update_attribute(:suspended_at, nil)
    │      └─ バリデーションスキップで直接 UPDATE
    │
    └─ respond_with(@user)
           └─ reactivate.js.haml
                  └─ _user.html.haml（再レンダリング）

[User#active_for_authentication?]（ログイン時に呼ばれる）
    │
    ├─ super（Devise の基本チェック）
    ├─ confirmed?
    ├─ !awaits_approval?
    │      └─ suspended? && sign_in_count == 0 && Setting.user_signup == :needs_approval
    └─ !suspended?
           └─ suspended_at != nil → nil なので false
```

### データフロー図

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

ユーザーID         ───▶ load_resource             ───▶ @user
                           │
                           ▼
                  update_attribute
                  (suspended_at = nil)
                           │
                           ▼
                   users テーブル更新
                           │
                           ▼
                   画面更新（AJAX）
                           │
                           ▼
                  ステータス表示変更
                  (Suspended → Active/Admin)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| users_controller.rb | `app/controllers/admin/users_controller.rb` | コントローラー | reactivate アクションの実装 |
| application_controller.rb | `app/controllers/admin/application_controller.rb` | コントローラー | 管理者権限チェック |
| user.rb | `app/models/users/user.rb` | モデル | suspended?, awaits_approval?, active_for_authentication? メソッド |
| _user.html.haml | `app/views/admin/users/_user.html.haml` | ビュー | ユーザー行の表示、再有効化リンク |
| reactivate.js.haml | `app/views/admin/users/reactivate.js.haml` | ビュー | 再有効化後の画面更新 JS |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（PUT /admin/users/:id/reactivate） |
| schema.rb | `db/schema.rb` | 設定 | データベーススキーマ（suspended_at カラム） |
