# 画面設計書 66-プロフィール

## 概要

本ドキュメントは、Shopware 6 管理画面（Administration）におけるプロフィール画面の設計を記述したものです。ログイン中の管理者ユーザーが自身のプロフィール情報を編集するための画面です。

### 本画面の処理概要

プロフィール画面は、現在ログインしている管理者ユーザーが自身のアカウント情報を管理するための画面です。個人情報、パスワード、言語設定、タイムゾーン、検索設定、プライバシー設定などを変更できます。

**業務上の目的・背景**：管理者ユーザーは自身の設定をカスタマイズすることで、より効率的に管理画面を利用できます。言語やタイムゾーンの設定により、ローカライズされた環境で作業でき、検索設定により必要な情報に素早くアクセスできます。

**画面へのアクセス方法**：管理画面右上のユーザーアイコンをクリックし、「プロフィール」を選択してアクセスします。またはURL直接アクセス: `#/sw/profile/index` です。

**主要な操作・処理内容**：
1. **一般設定**：名前、メールアドレス、パスワード、アバター画像の変更
2. **言語・タイムゾーン設定**：管理画面の表示言語とタイムゾーンの設定
3. **検索設定**：管理画面内検索の動作設定（最小検索文字数、検索対象エンティティ）
4. **プライバシー設定**：データ収集に関する設定

**画面遷移**：
- 遷移元：管理画面ヘッダーのユーザーメニュー
- 遷移先：なし（プロフィール画面のため）
- 内部タブ：一般、検索設定、プライバシー設定

**権限による表示制御**：
- `user.update_profile`：プロフィールの表示および更新が可能

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 関連機能なし |

## 画面種別

編集

## URL/ルーティング

| 項目 | 値 |
|------|---|
| モジュール名 | sw-profile |
| メインルート | sw.profile.index |
| 一般タブルート | sw.profile.index.general |
| 検索設定タブルート | sw.profile.index.searchPreferences |
| プライバシー設定タブルート | sw.profile.index.privacyPreferences |
| URLパス | #/sw/profile/index |

## 入出力項目

### 一般設定

| 項目名 | 項目ID | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| 名 | firstName | String | No | ユーザーの名（読み取り専用） |
| 姓 | lastName | String | No | ユーザーの姓（読み取り専用） |
| メールアドレス | email | String | Yes | ユーザーのメールアドレス |
| ユーザー名 | username | String | No | ログインユーザー名（読み取り専用） |
| 新しいパスワード | newPassword | String | No | 変更する場合のみ入力 |
| 新しいパスワード（確認） | newPasswordConfirm | String | No | パスワード確認 |
| 現在のパスワード | confirmPassword | String | Yes（変更時） | 変更を確定するためのパスワード |
| アバター | avatarId | UUID | No | プロフィール画像 |
| 言語 | localeId | UUID | Yes | 管理画面の表示言語 |
| タイムゾーン | timeZone | String | Yes | ユーザーのタイムゾーン |

### 検索設定

| 項目名 | 項目ID | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| 最小検索文字数 | minSearchTermLength | Integer | No | 検索を実行する最小文字数 |
| 検索対象エンティティ | searchPreferences | Array | No | 検索対象とするエンティティの設定 |

## 表示項目

### 一般タブ

| セクション | 表示項目 | 説明 |
|------------|----------|------|
| 個人情報 | アバター画像 | プロフィール画像のアップロード・変更 |
| 個人情報 | 名・姓 | ユーザー名（読み取り専用） |
| 個人情報 | メールアドレス | 編集可能なメールフィールド |
| 個人情報 | ユーザー名 | ログインユーザー名（読み取り専用） |
| パスワード | 新しいパスワード | パスワード入力フィールド |
| パスワード | 新しいパスワード（確認） | パスワード確認入力フィールド |
| 設定 | 言語 | 言語選択ドロップダウン |
| 設定 | タイムゾーン | タイムゾーン選択ドロップダウン |

### 検索設定タブ

| セクション | 表示項目 | 説明 |
|------------|----------|------|
| 検索設定 | 最小検索文字数 | 数値入力フィールド |
| 検索対象 | エンティティリスト | 検索対象とするエンティティのチェックリスト |

### プライバシー設定タブ

| セクション | 表示項目 | 説明 |
|------------|----------|------|
| プライバシー | 各種プライバシー設定 | データ収集に関する設定 |

## イベント仕様

### 1-保存ボタン押下

**トリガー**: 「保存」ボタンクリック

**処理フロー**:
1. `onSave` メソッドが実行される
2. 現在のタブに応じて処理を分岐
   - 検索設定タブ: `saveMinSearchTermLength()` と `saveUserSearchPreferences()` を実行
   - 一般タブ: メール・パスワードのバリデーション後、パスワード確認モーダルを表示
3. SSOユーザーの場合は直接 `saveUser()` を実行

**データフロー**:
```
ユーザー入力 → バリデーション → confirmPasswordModal → saveUser() → API → Database
```

### 2-パスワード確認モーダル

**トリガー**: パスワード変更時または一般設定保存時

**処理フロー**:
1. `confirmPasswordModal` が true になりモーダル表示
2. 現在のパスワードを入力
3. `onVerifyPasswordFinished` で検証完了後、`saveUser()` を実行

### 3-アバター画像変更

**トリガー**: メディアアップロードまたはメディア選択

**処理フロー**:
1. `setMediaItem` または `onMediaSelectionChange` が実行される
2. `user.avatarId` を更新
3. `loadMediaItem` でプレビュー画像を読み込み

### 4-言語変更

**トリガー**: 言語ドロップダウンの値変更

**処理フロー**:
1. `user.localeId` が更新される
2. 保存後、`localeHelper.setLocaleWithId()` で管理画面の言語を変更
3. 画面が新しい言語で再描画

### 5-検索設定保存

**トリガー**: 検索設定タブでの保存

**処理フロー**:
1. `saveMinSearchTermLength()` で最小検索文字数を保存
2. `saveUserSearchPreferences()` で検索対象エンティティ設定を保存
3. `userConfigService.upsert()` でユーザー設定を永続化

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| プロフィール保存 | user | UPDATE | ユーザー情報の更新 |
| 検索設定保存 | user_config | UPDATE/INSERT | 検索設定の保存 |
| アバター変更 | user | UPDATE | avatarId の更新 |

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

#### user

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | email | 入力値 | メールアドレス |
| UPDATE | password | ハッシュ化された値 | パスワード（変更時のみ） |
| UPDATE | locale_id | UUID | 言語設定 |
| UPDATE | time_zone | タイムゾーン文字列 | タイムゾーン |
| UPDATE | avatar_id | UUID | アバター画像 |

#### user_config

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE/INSERT | key | 設定キー | ユーザー設定キー |
| UPDATE/INSERT | value | JSON | 検索設定値 |
| UPDATE/INSERT | user_id | UUID | 対象ユーザー |

## メッセージ仕様

| 種別 | メッセージキー | メッセージ内容 | 表示条件 |
|------|--------------|--------------|---------|
| エラー | sw-profile.index.notificationInvalidEmailErrorMessage | メールアドレスが無効です | メールアドレスバリデーション失敗時 |
| エラー | sw-profile.index.notificationPasswordErrorMessage | パスワードが一致しません | パスワード確認不一致時 |
| エラー | sw-profile.index.notificationSaveErrorMessage | 保存に失敗しました | 保存処理失敗時 |

## 例外処理

| 例外状態 | 対応処理 | 画面表示 |
|---------|---------|---------|
| 権限不足 | 画面アクセス不可 | 権限エラーページを表示 |
| メールアドレス無効 | エラー通知表示 | 「メールアドレスが無効です」メッセージ |
| パスワード不一致 | エラー通知表示 | 「パスワードが一致しません」メッセージ |
| パスワード検証失敗 | エラー通知表示 | 「現在のパスワードが正しくありません」メッセージ |
| API通信エラー | エラー通知表示 | 「保存に失敗しました」メッセージ |

## 備考

- プロフィール画面はログイン中のユーザー自身の情報のみ編集可能です
- SSOユーザーの場合、パスワード確認プロセスがスキップされます
- パスワード変更後は再ログイン処理が自動的に行われます
- 言語変更は即座に管理画面全体に反映されます
- メディアアップローダーには `media.creator` 権限が必要です

---

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

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

### 推奨読解順序

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

プロフィール画面では user エンティティと user_config を使用します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | UserDefinition | `src/Core/Framework/Api/Acl/Role/UserDefinition.php` | ユーザーエンティティの定義 |
| 1-2 | UserConfigDefinition | `src/Core/Framework/Api/Acl/Role/UserConfigDefinition.php` | ユーザー設定エンティティの定義 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.js | `src/Administration/Resources/app/administration/src/module/sw-profile/index.js` | モジュール登録とルート定義 |

**主要処理フロー**:
1. **10-24行目**: コンポーネントの遅延ロード登録
2. **27-74行目**: `Module.register` でモジュールを登録
3. **36-72行目**: ルート定義（index、general、searchPreferences、privacyPreferences）

#### Step 3: ページコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sw-profile-index/index.js | `src/Administration/Resources/app/administration/src/module/sw-profile/page/sw-profile-index/index.js` | ページのメインロジック |

**主要処理フロー**:
- **142-175行目**: `createdComponent` でユーザーデータ取得
- **245-272行目**: `onSave` で保存処理（タブ別分岐）
- **304-369行目**: `saveUser` でユーザー情報保存
- **435-469行目**: `saveUserSearchPreferences` で検索設定保存

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

```
sw-profile-index (Page)
    │
    ├─ sw-profile-index-general (View)
    │      ├─ userRepository
    │      │      └─ CRUD操作
    │      │
    │      ├─ userService
    │      │      └─ getUser(), updateUser()
    │      │
    │      ├─ loginService
    │      │      └─ loginByUsername() [パスワード変更後]
    │      │
    │      └─ mediaRepository
    │             └─ アバター画像取得
    │
    ├─ sw-profile-index-search-preferences (View)
    │      ├─ searchRankingService
    │      │      └─ saveMinSearchTermLength()
    │      │
    │      └─ userConfigService
    │             └─ upsert() [検索設定保存]
    │
    └─ sw-profile-index-privacy-preferences (View)
           └─ プライバシー設定
```

### データフロー図

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

プロフィール入力    ───▶   sw-profile-index-general   ───▶  user テーブル
(email, password等)              │
                                 ├─▶ userRepository.save()
                                 │   または
                                 └─▶ userService.updateUser()

検索設定入力        ───▶   sw-profile-index-          ───▶  user_config テーブル
                           search-preferences
                                   │
                                   └─▶ userConfigService.upsert()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.js | `src/Administration/Resources/app/administration/src/module/sw-profile/index.js` | ソース | モジュール登録・ルート定義 |
| sw-profile-index/index.js | `src/Administration/Resources/app/administration/src/module/sw-profile/page/sw-profile-index/index.js` | ソース | メインページロジック |
| sw-profile-index-general/index.js | `src/Administration/Resources/app/administration/src/module/sw-profile/view/sw-profile-index-general/index.js` | ソース | 一般設定タブ |
| sw-profile-index-search-preferences/index.js | `src/Administration/Resources/app/administration/src/module/sw-profile/view/sw-profile-index-search-preferences/index.js` | ソース | 検索設定タブ |
| sw-profile-index-privacy-preferences/index.js | `src/Administration/Resources/app/administration/src/module/sw-profile/view/sw-profile-index-privacy-preferences/index.js` | ソース | プライバシー設定タブ |
| sw-profile.store.js | `src/Administration/Resources/app/administration/src/module/sw-profile/store/sw-profile.store.js` | ソース | プロフィール状態管理ストア |
| acl/index.js | `src/Administration/Resources/app/administration/src/module/sw-profile/acl/index.js` | ソース | 権限定義 |
