# 機能設計書 49-アカウント情報更新

## 概要

本ドキュメントは、ECモバイルアプリケーションにおけるアカウント情報更新機能の設計仕様を定義する。ユーザープロフィール情報（名前、メールアドレス、電話番号、生年月日、パスワード等）を編集・更新する機能である。

### 本機能の処理概要

この機能は、ログイン済みユーザーが自身のアカウント情報を編集し、保存するための処理を提供する。プロフィール画像の変更・削除、基本情報の編集、パスワード変更、ニュースレター購読設定の変更が可能。

**業務上の目的・背景**：ユーザー情報は時間とともに変化する（住所変更、電話番号変更等）。ユーザーが自己管理で情報を更新できる機能を提供することで、常に最新の連絡先情報を維持し、注文処理やカスタマーサポートの品質を確保する。

**機能の利用シーン**：ユーザーがアカウント情報画面で情報を編集し「保存」ボタンを押下した際に利用される。引っ越しによる連絡先変更、パスワードの定期変更、ニュースレター設定の変更などに使用される。

**主要な処理内容**：
1. フォームバリデーション
2. 処理中ダイアログの表示
3. GraphQL APIでアカウント更新リクエスト送信
4. 更新結果の通知
5. SharedPreferencesへの更新情報反映
6. 成功時の画面遷移（前画面へ戻る）

**関連システム・外部連携**：バックエンドのBagisto GraphQL APIと連携し、アカウント更新処理を実行する。画像アップロードがある場合はマルチパートリクエストとなる。

**権限による制御**：ログイン済みユーザーのみがアクセス可能。ユーザーは自身のアカウント情報のみを更新できる。パスワード変更時は現在のパスワードの入力が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 22 | アカウント情報画面 | 主画面 | ユーザープロフィール情報の編集・更新処理 |

## 機能種別

データ更新 / フォームバリデーション / API連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| firstName | String | Yes | 名 | 必須入力 |
| lastName | String | Yes | 姓 | 必須入力 |
| email | String | Yes | メールアドレス | 必須、メール形式 |
| gender | String | Yes | 性別 | Male/Female/Other |
| dob | String | No | 生年月日 | YYYY-MM-DD形式 |
| phone | String | Yes | 電話番号 | 必須、電話番号形式 |
| oldPassword | String | No | 現在のパスワード | パスワード変更時必須 |
| password | String | No | 新しいパスワード | パスワード変更時必須 |
| confirmPassword | String | No | パスワード確認 | passwordと一致 |
| avatar | String | No | プロフィール画像パス | ファイルパスまたは'delete' |
| subscribedToNewsLetter | bool | No | ニュースレター購読 | true/false |

### 入力データソース

- 画面入力：ProfileDetailViewフォームからの入力
- 画像選択：デバイスのカメラまたはギャラリーから選択
- ユーザーセッション：認証トークン（SharedPreferencesから取得）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| status | bool | 処理成功フラグ |
| message | String | 処理結果メッセージ |
| graphqlErrors | String | エラー詳細（失敗時） |
| data.name | String | 更新後のユーザー名 |
| data.email | String | 更新後のメールアドレス |
| data.imageUrl | String | 更新後のプロフィール画像URL |

### 出力先

- 画面表示：成功/失敗通知メッセージ
- SharedPreferences：更新後のユーザー情報を保存
- 画面遷移：成功時は前画面へ戻る

## 処理フロー

### 処理シーケンス

```
1. フォーム入力・編集
   └─ TextEditingController、Dropdownで入力
2. 保存ボタン押下
   └─ _onPressSaveButton呼び出し
3. バリデーション
   └─ _formKey.currentState!.validate()
4. 処理中ダイアログ表示
   └─ showDialog with CircularProgressIndicator
5. 更新イベント発行
   └─ AccountInfoUpdateEvent発行
6. API呼び出し
   └─ callAccountUpdateApi実行
7. レスポンス処理
   └─ AccountUpdateにデシリアライズ
8. 結果通知
   └─ 成功時：successNotification、失敗時：errorNotification
9. SharedPreferences更新
   └─ 成功時：_updateSharedPreferences呼び出し
10. 画面遷移
    └─ 成功時：2秒後にNavigator.pop
```

### フローチャート

```mermaid
flowchart TD
    A[保存ボタン押下] --> B{バリデーション成功?}
    B -->|No| C[エラー表示]
    B -->|Yes| D[処理中ダイアログ表示]
    D --> E[AccountInfoUpdateEvent発行]
    E --> F[callAccountUpdateApi呼び出し]
    F --> G{API成功?}
    G -->|Yes| H{status == true?}
    G -->|No| I[エラー通知表示]
    H -->|Yes| J[成功通知表示]
    H -->|No| K[エラー通知表示]
    J --> L[SharedPreferences更新]
    L --> M[2秒待機]
    M --> N[Navigator.pop]
    N --> O[前画面へ戻る]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-49-01 | 認証必須 | ログイン済みユーザーのみアカウント更新可能 | 常時 |
| BR-49-02 | 自己情報のみ | ユーザーは自身のアカウント情報のみ更新可能 | 常時 |
| BR-49-03 | 必須フィールド | firstName、lastName、email、phone、genderは必須 | 常時 |
| BR-49-04 | パスワード変更ルール | パスワード変更時は現在のパスワードと新パスワード両方必須 | パスワード変更時 |
| BR-49-05 | 画像削除 | avatar='delete'で画像削除 | 画像削除時 |
| BR-49-06 | 遷移タイミング | 更新成功後2秒待機してから画面遷移 | 成功時 |

### 計算ロジック

バリデーション：
```dart
if (_formKey.currentState!.validate()) {
  // 更新処理実行
}
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| アカウント更新 | customers | UPDATE | ユーザー情報を更新 |

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

#### customers（GraphQL API経由）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | first_name, last_name, email, phone, date_of_birth, gender, password, image等 | 認証トークンに紐づくユーザー | パスワードは暗号化 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | バリデーションエラー | 必須フィールド未入力 | フィールドエラー表示 |
| - | API通信エラー | ネットワーク接続不可 | エラー通知表示 |
| - | 認証エラー | セッション切れ | エラー通知表示 |
| - | ビジネスエラー | メール重複、パスワード不正等 | graphqlErrorsの内容を表示 |

### リトライ仕様

- 自動リトライなし
- ユーザーが再度保存ボタンを押下することで再試行可能

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

- フロントエンドからは単一API呼び出し
- サーバーサイドでトランザクション管理

## パフォーマンス要件

- 更新処理完了：3秒以内
- 画像アップロード含む場合：5秒以内

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

- 認証トークンを使用したAPI呼び出し
- パスワードは平文で送信（HTTPS前提）
- パスワード変更時は現在のパスワードによる本人確認

## 備考

- ダイアログは3秒後に自動で閉じる（念のため）
- SharedPreferencesへの保存項目：CustomerName、CustomerImage、CustomerEmail
- 画像削除時はavatar='delete'を送信

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | account_update_model.dart | `lib/data_model/account_models/account_update_model.dart` | AccountUpdateの構造（status, message, data） |

#### Step 2: イベント定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | account_info_event.dart | `lib/screens/account/bloc/account_info_event.dart` | AccountInfoUpdateEventのパラメータ |

**主要処理フロー**:
- **21-46行目**: AccountInfoUpdateEventの定義（全パラメータ）

#### Step 3: BLoC処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | account_info_bloc.dart | `lib/screens/account/bloc/account_info_bloc.dart` | AccountInfoUpdateEventのハンドリング |

**主要処理フロー**:
- **30-37行目**: AccountInfoUpdateEvent処理、callAccountUpdateApi呼び出し

#### Step 4: リポジトリ層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | account_info_repository.dart | `lib/screens/account/bloc/account_info_repository.dart` | callAccountUpdateApiメソッド |

**主要処理フロー**:
- **47-77行目**: callAccountUpdateApiでApiClient.updateCustomerData呼び出し

#### Step 5: UI処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | account_screen.dart | `lib/screens/account/view/account_screen.dart` | _onPressSaveButton、結果ハンドリング |

**主要処理フロー**:
- **225-276行目**: _onPressSaveButton実装
  - **226行目**: バリデーション
  - **227-259行目**: 処理中ダイアログ
  - **261-272行目**: AccountInfoUpdateEvent発行
- **99-117行目**: AccountInfoUpdateStateのlistener処理
- **280-286行目**: _updateSharedPreferences

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

```
AccountScreen (Widget)
    │
    ├─ _onPressSaveButton()
    │      │
    │      ├─ _formKey.currentState!.validate()
    │      │
    │      ├─ showDialog (処理中)
    │      │
    │      └─ AccountInfoUpdateEvent発行
    │
    └─ AccountInfoBloc
           │
           └─ AccountInfoUpdateState
                  │
                  └─ AccountInfoRepositoryImp.callAccountUpdateApi()
                         │
                         └─ ApiClient.updateCustomerData()
```

### データフロー図

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

フォーム入力
    │
    ▼
保存ボタン押下
    │
    ▼
バリデーション
    │
    ▼ [成功]
AccountInfoUpdateEvent ───▶ AccountInfoBloc
                                  │
                                  ▼
                        AccountInfoRepository.callAccountUpdateApi()
                                  │
                                  ▼
                        ApiClient (GraphQL mutation)
                                  │
                                  ▼
                           AccountUpdate
                                  │
                                  ▼
                        AccountInfoUpdateState ───▶ 成功/失敗通知
                                                        │
                                                        ▼ [成功時]
                                              SharedPreferences更新
                                                        │
                                                        ▼
                                                  Navigator.pop
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| account_screen.dart | `lib/screens/account/view/account_screen.dart` | ソース | メイン画面、保存処理 |
| account_info_bloc.dart | `lib/screens/account/bloc/account_info_bloc.dart` | ソース | 更新処理のBLoC |
| account_info_event.dart | `lib/screens/account/bloc/account_info_event.dart` | ソース | AccountInfoUpdateEvent定義 |
| account_info_state.dart | `lib/screens/account/bloc/account_info_state.dart` | ソース | AccountInfoUpdateState定義 |
| account_info_repository.dart | `lib/screens/account/bloc/account_info_repository.dart` | ソース | callAccountUpdateApiメソッド |
| profile_detail.dart | `lib/screens/account/widget/profile_detail.dart` | ソース | フォーム入力UI |
| account_update_model.dart | `lib/data_model/account_models/account_update_model.dart` | ソース | APIレスポンスモデル |
