# 機能設計書 48-ユーザープロファイル編集

## 概要

本ドキュメントは、Fat Free CRMのユーザープロファイル編集機能（UsersController#edit, #update）の設計仕様を定義するものである。

### 本機能の処理概要

ユーザープロファイル編集機能は、ユーザーの個人情報（名前、連絡先、会社情報、メール通知設定など）を編集・更新する機能である。editアクションで編集フォームを表示し、updateアクションで変更内容を保存する。

**業務上の目的・背景**：CRMシステムにおいて、ユーザーは自分の連絡先情報やプロファイル情報を最新の状態に保つ必要がある。役職変更、連絡先変更、通知設定の変更などを自分自身で行えることで、管理者の負担を軽減し、情報の鮮度を維持できる。

**機能の利用シーン**：ユーザーが自分のプロファイルページで「プロファイル編集」リンクをクリックし、個人情報や通知設定を変更する場面で利用される。異動時の役職・会社情報更新、連絡先変更、メール通知設定の変更などに使用される。

**主要な処理内容**：
1. 【edit】対象ユーザーを取得して編集フォームを表示
2. 【update】更新パラメータを受信してユーザー情報を更新
3. 【update】更新結果に応じて成功/エラー応答

**関連システム・外部連携**：なし（内部処理のみ）

**権限による制御**：CanCanCanで権限管理。自分のプロファイルまたは管理者のみ編集可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 32 | ユーザー詳細画面（プロフィール） | 主画面 | プロフィール情報の編集 |

## 機能種別

データ更新処理 / UPDATE操作

## 入力仕様

### 入力パラメータ

#### editアクション

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | Integer | Yes | 編集対象ユーザーのID | 存在するユーザーであること |
| cancel | String | No | キャンセルフラグ | "true"でキャンセル処理 |

#### updateアクション

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | Integer | Yes | 更新対象ユーザーのID | 存在するユーザーであること |
| user[username] | String | No | ユーザー名 | 一意であること |
| user[email] | String | Yes | メールアドレス | 有効なメール形式、一意 |
| user[first_name] | String | No | 名 | - |
| user[last_name] | String | No | 姓 | - |
| user[title] | String | No | 役職 | - |
| user[company] | String | No | 会社名 | - |
| user[alt_email] | String | No | 代替メールアドレス | - |
| user[phone] | String | No | 電話番号 | - |
| user[mobile] | String | No | 携帯電話番号 | - |
| user[aim] | String | No | AIM ID | - |
| user[yahoo] | String | No | Yahoo ID | - |
| user[google] | String | No | Google ID | - |
| user[subscribe_to_comment_replies] | Boolean | No | コメント返信通知 | true/false |
| user[receive_assigned_notifications] | Boolean | No | アサイン通知 | true/false |

### 入力データソース

- URLパラメータ：ユーザーID
- 画面入力：編集フォーム

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| @user | User | 編集対象ユーザーオブジェクト |
| flash[:notice] | String | 更新成功メッセージ |

### 出力先

- データベース：usersテーブルへUPDATE
- 画面表示：AJAXレスポンスで編集フォームまたは更新後のプロファイル表示

## 処理フロー

### 処理シーケンス

```
【editアクション】
1. ユーザー取得
   └─ load_and_authorize_resourceで自動取得・権限チェック

2. キャンセル処理判定
   ├─ cancel=true: 編集フォームを閉じる
   └─ cancel=false: 編集フォームを表示

【updateアクション】
1. ユーザー取得
   └─ load_and_authorize_resourceで自動取得・権限チェック

2. パラメータ前処理
   └─ email, alt_emailの空白を除去（strip!）

3. ユーザー更新
   └─ @user.update(user_params)

4. レスポンス生成
   ├─ 成功時：flash[:notice]設定、プロファイル再表示
   └─ 失敗時：編集フォームにエラー表示
```

### フローチャート

```mermaid
flowchart TD
    subgraph editアクション
        A1[編集リクエスト受信] --> B1[権限チェック・ユーザー取得]
        B1 --> C1{権限あり?}
        C1 -->|No| D1[アクセス拒否]
        C1 -->|Yes| E1{cancel=true?}
        E1 -->|Yes| F1[フォームを閉じる]
        E1 -->|No| G1[編集フォーム表示]
    end

    subgraph updateアクション
        A2[更新リクエスト受信] --> B2[権限チェック・ユーザー取得]
        B2 --> C2{権限あり?}
        C2 -->|No| D2[アクセス拒否]
        C2 -->|Yes| E2[パラメータ前処理]
        E2 --> F2[ユーザー更新]
        F2 --> G2{更新成功?}
        G2 -->|Yes| H2[成功メッセージ・プロファイル表示]
        G2 -->|No| I2[エラー表示]
    end
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-48-01 | 権限制御 | 自分のプロファイルまたは管理者のみ編集可能 | 常時 |
| BR-48-02 | メールアドレス空白除去 | email, alt_emailフィールドの前後空白を自動除去 | 更新時 |
| BR-48-03 | 一意性チェック | email, usernameは一意である必要がある | 更新時 |
| BR-48-04 | 通知設定 | subscribe_to_comment_replies, receive_assigned_notificationsで通知を制御 | 更新時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ユーザー取得 | users | SELECT | 対象ユーザー取得 |
| ユーザー更新 | users | UPDATE | ユーザー情報更新 |
| バージョン履歴 | versions | INSERT | 変更履歴レコード作成（paper_trail） |

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

#### users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | 全カラム | id = :user_id | 対象ユーザー取得 |
| UPDATE | first_name | params[:user][:first_name] | 名 |
| UPDATE | last_name | params[:user][:last_name] | 姓 |
| UPDATE | email | params[:user][:email] | メールアドレス |
| UPDATE | その他 | 対応するパラメータ | 各種プロファイル情報 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | RecordNotFound | 対象ユーザーが存在しない | 404エラー応答 |
| - | CanCan::AccessDenied | アクセス権限なし | 403エラー応答 |
| - | バリデーションエラー | メールアドレス形式不正、一意性違反など | 入力フォームにエラー表示 |

### リトライ仕様

リトライ不要（ユーザーが再入力して再送信）

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

更新処理はActiveRecordのデフォルトトランザクションで実行

## パフォーマンス要件

- 編集フォーム表示は500ms以内に応答
- 更新処理は500ms以内に応答

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

- 認証必須：ApplicationControllerで認証チェック
- 権限管理：CanCanCanで詳細な権限制御
- パラメータサニタイズ：Strong Parametersで許可パラメータを制限
- XSS対策：ビューでのエスケープ処理

## 備考

- 編集フォームはインライン表示され、AJAXで更新
- パスワード変更は別機能（No.50）で実施

---

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

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

### 推奨読解順序

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

ユーザーモデルのバリデーションと属性を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | user.rb | `app/models/users/user.rb` | バリデーション（87-98行目） |

**読解のコツ**: Userモデルはemailとusernameに一意性バリデーションを持つ。email形式のバリデーションも定義されている。

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

edit/updateアクションの処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | users_controller.rb | `app/controllers/users_controller.rb` | editアクション（27-29行目） |
| 2-2 | users_controller.rb | `app/controllers/users_controller.rb` | updateアクション（34-38行目） |
| 2-3 | users_controller.rb | `app/controllers/users_controller.rb` | user_paramsメソッド（128-150行目） |

**主要処理フロー**:
1. **13行目**: load_and_authorize_resourceでユーザー取得と権限チェック
2. **35行目**: updateメソッドでユーザー更新
3. **36行目**: flash[:notice]に成功メッセージ設定
4. **131-132行目**: email, alt_emailの空白除去

#### Step 3: ビューレスポンスを理解する

JavaScript応答の生成を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | edit.js.haml | `app/views/users/edit.js.haml` | フォーム表示/キャンセル処理（1-9行目） |
| 3-2 | update.js.haml | `app/views/users/update.js.haml` | 更新後の表示処理（1-10行目） |
| 3-3 | _profile.html.haml | `app/views/users/_profile.html.haml` | 編集フォームパーシャル |

**主要処理フロー**:
- **edit.js.haml 1-3行目**: cancel=trueの場合、フォームを閉じる
- **edit.js.haml 5-9行目**: 編集フォームを表示、他のフォームを非表示
- **update.js.haml 1-7行目**: 成功時にフォームを閉じてプロファイル再表示
- **update.js.haml 8-10行目**: エラー時にフォーム再表示してフォーカス

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

```
UsersController#edit
    │
    ├─ load_and_authorize_resource (CanCanCan)
    │      ├─ User.find
    │      └─ authorize! :edit, @user
    │
    └─ respond_with(@user)
           └─ edit.js.haml
                  └─ _profile.html.haml

UsersController#update
    │
    ├─ load_and_authorize_resource (CanCanCan)
    │      ├─ User.find
    │      └─ authorize! :update, @user
    │
    ├─ user_params (Strong Parameters)
    │      └─ email/alt_email strip!
    │
    └─ @user.update(user_params)
           └─ update.js.haml
                  └─ _user.html.haml (成功時)
```

### データフロー図

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

【edit】
ユーザーID ───▶ UsersController#edit ───▶ JavaScript応答
                    │                        └─ 編集フォーム表示
                    └─ 権限チェック

【update】
編集フォーム ───▶ UsersController#update ───▶ データベース
  └─ user params      │                          └─ UPDATE users
                       ├─ 権限チェック
                       ├─ パラメータ前処理       ───▶ JavaScript応答
                       └─ ユーザー更新               ├─ 成功: プロファイル表示
                                                      └─ 失敗: エラー表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| users_controller.rb | `app/controllers/users_controller.rb` | コントローラー | edit/updateアクション |
| user.rb | `app/models/users/user.rb` | モデル | Userモデル、バリデーション |
| edit.js.haml | `app/views/users/edit.js.haml` | ビュー | 編集フォーム表示JavaScript |
| update.js.haml | `app/views/users/update.js.haml` | ビュー | 更新後表示JavaScript |
| _profile.html.haml | `app/views/users/_profile.html.haml` | ビュー | 編集フォームパーシャル |
| _user.html.haml | `app/views/users/_user.html.haml` | ビュー | ユーザー情報パーシャル |
| routes.rb | `config/routes.rb` | 設定 | ルーティング設定（155-163行目） |
