# 機能設計書 68-通貨切替

## 概要

本ドキュメントは、通貨切替機能の設計仕様を定義する。ユーザーが商品価格や金額の表示通貨を変更し、選択した通貨でアプリ全体の金額表示を更新する機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：グローバルなECサイトでは、ユーザーが自国の通貨で価格を確認したいというニーズがある。本機能により、複数の通貨オプションからユーザーが希望する通貨を選択でき、価格の理解とコンバージョン率向上に貢献する。

**機能の利用シーン**：
- 海外からアクセスするユーザーが自国通貨で価格を確認したい場合
- 旅行先でその国の通貨で価格を確認したい場合
- 設定画面から通貨オプションを変更する場合

**主要な処理内容**：
1. グローバルデータから利用可能な通貨リストを取得
2. ユーザーが通貨を選択するとSharedPreferencesに保存
3. Hiveキャッシュをクリア（最近閲覧商品）
4. アプリを再起動して新しい通貨設定を反映

**関連システム・外部連携**：
- SharedPreferences（通貨設定の永続化）
- Hive（キャッシュクリア）
- RestartWidget（アプリ再起動）

**権限による制御**：認証状態に関わらず、すべてのユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 29 | 通貨選択画面 | 主画面 | 表示通貨の切替処理（選択後アプリ再起動） |

## 機能種別

設定変更処理（UPDATE操作）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| code | String | Yes | 通貨コード（例: "USD", "EUR", "JPY"） | 利用可能な通貨リストに存在すること |
| name | String | Yes | 通貨名（表示用） | - |

### 入力データソース

- GlobalData.languageData.currenciesから取得した通貨リスト
- ユーザーによるリスト項目タップ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| _currentCurrencyCode | String | 選択された通貨コード |
| _selectedIndex | int | 選択されたインデックス |

### 出力先

- SharedPreferences（CurrencyCode, CurrencyLabel）
- GlobalData.currencyCode
- アプリ再起動後のUI全体に反映（価格表示）

## 処理フロー

### 処理シーケンス

```
1. 画面初期化（initState）
   └─ GlobalData.languageDataから通貨リストを取得
   └─ _fetchSharedPreferenceDataで現在の選択通貨を取得
2. 通貨リスト表示
   └─ ListView.builderで通貨オプションを一覧表示
3. 通貨選択（リスト項目タップ）
   └─ _selectedIndexと_currentCurrencyCodeを更新
   └─ appStoragePref.setCurrencyCodeで通貨コードを保存
   └─ GlobalData.currencyCodeを更新
   └─ appStoragePref.setCurrencyLabelで通貨名を保存
4. キャッシュクリア
   └─ Hive.deleteBoxFromDisk("recentProducts")
5. アプリ再起動
   └─ _closeThisPage呼び出し
   └─ Hive.deleteBoxFromDisk("getCategoriesDrawerData")
   └─ RestartWidget.restartApp(context)
   └─ スプラッシュ画面へ遷移
```

### フローチャート

```mermaid
flowchart TD
    A[画面表示] --> B[通貨リスト取得]
    B --> C[現在選択通貨の取得]
    C --> D[ListView.builder表示]
    D --> E[通貨項目タップ]
    E --> F{同じ通貨選択?}
    F -->|Yes| G[画面を閉じる]
    F -->|No| H[状態更新]
    H --> I[SharedPreferences保存]
    I --> J[GlobalData.currencyCode更新]
    J --> K[Hiveキャッシュクリア]
    K --> L[_closeThisPage]
    L --> M[RestartWidget.restartApp]
    M --> N[スプラッシュ画面へ遷移]
    N --> O[新通貨でアプリ再起動]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-68-01 | デフォルト通貨 | 未設定時はUSDをデフォルトとする | 初回起動時 |
| BR-68-02 | 同一通貨選択 | 既に選択中の通貨をタップした場合は画面を閉じるのみ | 同一選択時 |
| BR-68-03 | キャッシュクリア | 通貨変更時は最近閲覧商品とカテゴリのキャッシュをクリア | 通貨選択時 |
| BR-68-04 | 即時反映 | 通貨変更はアプリ再起動により即時反映 | 通貨選択時 |
| BR-68-05 | ラジオボタン表示 | 現在選択中の通貨はチェック済みラジオボタンで表示 | 常時 |

### 計算ロジック

該当なし（通貨換算はサーバー側で実施）

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

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

本機能はローカルストレージ（SharedPreferences、Hive）のみ操作する。バックエンドへのAPI呼び出しは行わない。

| 操作 | 対象ストレージ | 操作種別 | 概要 |
|-----|---------------|---------|------|
| 通貨コード保存 | SharedPreferences | UPDATE | CurrencyCodeキーに通貨コードを保存 |
| 通貨名保存 | SharedPreferences | UPDATE | CurrencyLabelキーに通貨名を保存 |
| キャッシュクリア | Hive | DELETE | recentProducts, getCategoriesDrawerDataボックスを削除 |

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

該当なし（ローカルストレージのみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | データ不存在 | currencyLanguageListがnull | 空のリスト表示 |
| - | ストレージエラー | SharedPreferences書き込み失敗 | エラーログ出力（UI通知なし） |
| - | キャッシュエラー | Hive削除失敗 | 処理継続（非クリティカル） |

### リトライ仕様

自動リトライは実装されていない。エラー発生時も処理は継続される。

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

ローカルストレージ操作のみのため、トランザクション制御は不要。

## パフォーマンス要件

- 通貨リスト表示: 即時（キャッシュ済みデータ使用）
- 通貨切替後の再起動: 2秒以内

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

- 認証不要で利用可能
- 通貨設定はローカルに保存され、外部に送信されない
- APIリクエストのヘッダーにx-currencyとして通貨コードが含まれる

## 備考

- 通貨リストはアプリ起動時にAPIから取得してGlobalDataに保存されている
- 通貨変更後はスプラッシュ画面経由でホーム画面に戻る
- 価格の実際の換算はサーバー側で行われる

---

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

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

### 推奨読解順序

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

通貨データの構造を理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | currency_language_model.dart | `lib/data_model/currency_language_model.dart` | Currenciesクラスのcode、nameフィールド |

**読解のコツ**:
- CurrencyLanguageListがcurrenciesリストを保持
- 各Currenciesにはcode（"USD"等）とname（"US Dollar"等）がString型で格納

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

処理の起点となる画面ファイルを確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | curency_view.dart | `lib/screens/currency/curency_view.dart` | CurrencyScreenウィジェット、通貨選択処理 |

**主要処理フロー**:
1. **24-26行目**: 状態変数（_selectedIndex、_currentCurrencyCode、currencyLanguageList）の定義
2. **30-33行目**: initStateでGlobalData.languageDataを取得、_fetchSharedPreferenceDataを呼び出し
3. **47-79行目**: _currencyメソッドでListView.builderを使用して通貨リストを表示
4. **83-98行目**: _onTapCurrencyで通貨選択処理（同一選択チェック、設定保存）
5. **101-106行目**: _closeThisPageでキャッシュクリアとアプリ再起動
6. **108-119行目**: _fetchSharedPreferenceDataで現在選択通貨を取得

#### Step 3: 通貨選択処理を理解する

通貨選択時の詳細処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | curency_view.dart | `lib/screens/currency/curency_view.dart` | _onTapCurrencyメソッド |

**主要処理フロー**:
- **84-86行目**: 同じ通貨を選択した場合は画面を閉じるのみ
- **88-91行目**: 状態更新（_selectedIndex、_currentCurrencyCode）
- **92行目**: appStoragePref.setCurrencyCodeで通貨コードを保存
- **93行目**: GlobalData.currencyCodeを更新
- **94行目**: appStoragePref.setCurrencyLabelで通貨名を保存
- **95行目**: Hive.deleteBoxFromDisk("recentProducts")

#### Step 4: アプリ再起動処理を理解する

アプリ再起動とキャッシュクリアの処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | curency_view.dart | `lib/screens/currency/curency_view.dart` | _closeThisPageメソッド |

**主要処理フロー**:
- **102行目**: 再度setCurrencyCodeを呼び出し（"US Dollar"が渡されているのは誤りの可能性）
- **103行目**: Hive.deleteBoxFromDisk("getCategoriesDrawerData")
- **104行目**: RestartWidget.restartApp(context)でアプリ再起動
- **105行目**: スプラッシュ画面へナビゲート

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

```
CurrencyScreen (curency_view.dart)
    │
    ├─ initState
    │      ├─ GlobalData.languageData取得
    │      └─ _fetchSharedPreferenceData()
    │             └─ appStoragePref.getCurrencyCode()
    │
    └─ _currency (ListView.builder)
           │
           └─ GestureDetector.onTap
                  │
                  └─ _onTapCurrency
                         │
                         ├─ 同一選択チェック
                         ├─ 状態更新
                         ├─ appStoragePref.setCurrencyCode(code)
                         ├─ GlobalData.currencyCode更新
                         ├─ appStoragePref.setCurrencyLabel(name)
                         ├─ Hive.deleteBoxFromDisk("recentProducts")
                         │
                         └─ _closeThisPage
                                │
                                ├─ Hive.deleteBoxFromDisk("getCategoriesDrawerData")
                                ├─ RestartWidget.restartApp(context)
                                └─ Navigator.pushNamedAndRemoveUntil(splash)
```

### データフロー図

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

GlobalData.languageData ───▶ 通貨リスト取得 ───▶ ListView表示
        │
        ▼
appStoragePref ─────────▶ 現在選択通貨取得 ───▶ 選択状態表示
        │
        ▼
通貨項目タップ ───────────▶ 同一選択チェック
                                    │
                          ┌─────────┴─────────┐
                          │                   │
                        Yes                  No
                          │                   │
                          ▼                   ▼
                    画面を閉じる        状態更新 & 設定保存
                                              │
                                              ▼
                                    Hiveキャッシュクリア
                                              │
                                              ▼
                                    RestartWidget.restartApp
                                              │
                                              ▼
                                    スプラッシュ画面 ───▶ 新通貨でアプリ表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| curency_view.dart | `lib/screens/currency/curency_view.dart` | ソース | 通貨選択画面 |
| currency_language_model.dart | `lib/data_model/currency_language_model.dart` | ソース | 言語・通貨データモデル |
| app_global_data.dart | `lib/utils/app_global_data.dart` | ソース | グローバルデータ管理 |
| app_storage_pref.dart | `lib/utils/app_storage_pref.dart` | ソース | SharedPreferencesラッパー |
| main.dart | `lib/main.dart` | ソース | RestartWidgetの定義 |
| splash_screen.dart | `lib/screens/splash_screen/view/splash_screen.dart` | ソース | 再起動後の遷移先 |
