# 機能設計書 37-配送先住所選択

## 概要

本ドキュメントは、チェックアウト時の配送先住所選択機能の設計を記述する。

### 本機能の処理概要

本機能は、チェックアウト画面のステップ1で、ユーザーが登録済み住所から請求先・配送先住所を選択、またはゲストとして新規住所を入力する機能である。

**業務上の目的・背景**：ECサイトにおいて、正確な配送先情報は注文処理の基盤となる。本機能により、ログインユーザーは過去に登録した住所を再利用でき、入力の手間を省ける。また、「請求先と同じ」オプションにより、配送先の二重入力を回避できる。

**機能の利用シーン**：チェックアウト画面のステップ1（住所選択）で本機能が使用される。

**主要な処理内容**：
1. ログインユーザーの場合、登録済み住所一覧を取得・表示
2. デフォルト住所を自動選択
3. 請求先住所の選択
4. 「請求先と同じ」チェックによる配送先の自動設定
5. 別の配送先を選択する場合は、配送先住所リストから選択
6. ゲストユーザーの場合は住所入力フォームを表示
7. 選択/入力完了後、親画面にcallBackで住所情報を渡す

**関連システム・外部連携**：GraphQL APIを介したBagistoバックエンドとの通信

**権限による制御**：ログインユーザーは登録済み住所選択、ゲストは新規入力

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 14 | チェックアウト画面 | 主画面 | チェックアウト時の配送先住所選択 |

## 機能種別

データ取得・選択処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| callBack | Function | Yes | 住所選択完了時のコールバック | - |

### 入力データソース

- ログインユーザー: getAddressData APIで取得した住所一覧
- ゲストユーザー: フォーム入力値

## 出力仕様

### 出力データ（callBack引数）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| billingCompanyName | String? | 請求先会社名 |
| billingFirstName | String? | 請求先名（姓） |
| billingLastName | String? | 請求先名（名） |
| billingAddress | String? | 請求先住所1 |
| billingAddress2 | String? | 請求先住所2 |
| billingCountry | String? | 請求先国コード |
| billingState | String? | 請求先都道府県 |
| billingCity | String? | 請求先市区町村 |
| billingPostCode | String? | 請求先郵便番号 |
| billingPhone | String? | 請求先電話番号 |
| shippingCompanyName | String? | 配送先会社名 |
| shippingFirstName | String? | 配送先名（姓） |
| shippingLastName | String? | 配送先名（名） |
| shippingAddress | String? | 配送先住所1 |
| shippingAddress2 | String? | 配送先住所2 |
| shippingCountry | String? | 配送先国コード |
| shippingState | String? | 配送先都道府県 |
| shippingCity | String? | 配送先市区町村 |
| shippingPostCode | String? | 配送先郵便番号 |
| shippingPhone | String? | 配送先電話番号 |
| billingAddressId | int | 請求先住所ID |
| shippingAddressId | int | 配送先住所ID |
| addressType | AddressType | 変更された住所種別 |
| isShippingSame | bool | 配送先が請求先と同一か |

### 出力先

- 親画面（CheckoutScreen）へのcallBack呼び出し

## 処理フロー

### 処理シーケンス

```
1. 画面表示時にCheckOutAddressEvent発火
   └─ initState内でBloc.add実行
2. Blocがリポジトリを通じてAPI呼び出し
   └─ CheckOutRepository.callCheckoutAddressApi
3. ApiClient.getAddressDataでGraphQL通信
   └─ accountAddresses queryを実行
4. 住所一覧を取得し、デフォルト住所を自動選択
   └─ isDefault=trueの住所を初期選択
5. ユーザーが住所を選択または変更
   └─ BillingAndShippingAddressViewで選択
6. callBackで親画面に住所情報を渡す
   └─ callAddressCallback実行
```

### フローチャート

```mermaid
flowchart TD
    A[住所ビュー表示] --> B{ログインユーザー?}
    B -->|Yes| C[住所一覧API取得]
    B -->|No| D[住所入力フォーム表示]
    C --> E[デフォルト住所を自動選択]
    E --> F[請求先住所表示]
    F --> G{配送先同一?}
    G -->|Yes| H[配送先に請求先をコピー]
    G -->|No| I[配送先住所選択を表示]
    H --> J[callBackで親画面に通知]
    I --> J
    D --> K[ユーザーが住所入力]
    K --> J
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-37-01 | デフォルト住所 | isDefault=trueの住所を初期選択 | 住所取得時 |
| BR-37-02 | 住所なし時 | 登録住所がない場合は最初の住所を選択 | 住所取得時 |
| BR-37-03 | 同一住所 | 「請求先と同じ」チェック時、配送先に請求先をコピー | チェック変更時 |
| BR-37-04 | ゲスト必須項目 | ゲストは全住所項目が必須 | ゲストフォーム時 |

### 計算ロジック

特になし。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 住所取得 | addresses | SELECT | 登録済み住所一覧取得 |

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

#### addresses

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | customer_id | 現在のユーザーID | バックエンドで処理 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | graphqlErrors | API通信失敗 | エラーメッセージ表示 |
| - | バリデーションエラー | 必須項目未入力 | 警告通知表示 |

### リトライ仕様

自動リトライなし。

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

読み取り専用のため、トランザクション管理は不要。

## パフォーマンス要件

- API応答時間: 2秒以内

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

- 認証トークンでユーザー識別
- 自身の住所のみ取得可能

## 備考

- 住所編集機能は住所管理画面で別途提供

---

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

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

### 推奨読解順序

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

住所データのモデル構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | address_model.dart | `lib/data_model/address_model.dart` | AddressModel、AddressDataクラスの構造 |

**読解のコツ**: AddressDataにisDefaultフィールドがあり、これでデフォルト住所を判定。

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

住所選択ビューの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | checkout_address_view.dart | `lib/screens/checkout/checkout_addres/view/checkout_address_view.dart` | メインビュー |

**主要処理フロー**:
- **56-63行目**: initStateでイベント発火、初期設定
- **75-92行目**: BlocConsumerのlistenerで住所自動選択
- **105-114行目**: デフォルト住所の判定ロジック
- **132-205行目**: 住所リストUI構築
- **207-236行目**: callAddressCallbackメソッド

#### Step 3: サブウィジェットを理解する

請求先・配送先選択の詳細UIを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | billing_shipping_address_view.dart | `lib/screens/checkout/checkout_addres/view/widget/billing_shipping_address_view.dart` | 住所選択ウィジェット |
| 3-2 | checkout_address_list.dart | `lib/screens/checkout/checkout_addres/view/widget/checkout_address_list.dart` | 住所リストウィジェット |

#### Step 4: Bloc/Repositoryを理解する

API呼び出しの流れを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | checkout_address_bloc.dart | `lib/screens/checkout/checkout_addres/bloc/checkout_address_bloc.dart` | 状態管理Bloc |
| 4-2 | checkout_address_repository.dart | `lib/screens/checkout/checkout_addres/bloc/checkout_address_repository.dart` | リポジトリ層 |

**主要処理フロー**:
- checkout_address_repository.dart **20-28行目**: getAddressData呼び出し

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

```
CheckoutAddressView (UI)
    │
    ├─ initState: CheckOutBloc.add(CheckOutAddressEvent)
    │      │
    │      └─ CheckOutRepository.callCheckoutAddressApi()
    │             │
    │             └─ ApiClient.getAddressData()
    │                    │
    │                    └─ GraphQL query: accountAddresses
    │
    ├─ UI描画
    │      ├─ BillingAndShippingAddressView（請求先）
    │      ├─ Checkbox（配送先同一）
    │      └─ BillingAndShippingAddressView（配送先）
    │
    └─ callAddressCallback()
           └─ 親画面へ住所情報を通知
```

### データフロー図

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

（初期化）────────▶ CheckOutBloc ───────────▶ 住所一覧表示
                         │
                   CheckOutRepository
                         │
                   ApiClient
                         │
                   GraphQL Server

住所選択 ───────────▶ setState ─────────────▶ callBack呼び出し
                         │                      │
                   billingAddress             親画面へ通知
                   shippingAddress
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| checkout_address_view.dart | `lib/screens/checkout/checkout_addres/view/checkout_address_view.dart` | ソース | 住所選択メインビュー |
| billing_shipping_address_view.dart | `lib/screens/checkout/checkout_addres/view/widget/billing_shipping_address_view.dart` | ソース | 住所選択ウィジェット |
| checkout_address_list.dart | `lib/screens/checkout/checkout_addres/view/widget/checkout_address_list.dart` | ソース | 住所リストウィジェット |
| checkout_address_loader_view.dart | `lib/screens/checkout/checkout_addres/view/widget/checkout_address_loader_view.dart` | ソース | ローディング表示 |
| checkout_address_bloc.dart | `lib/screens/checkout/checkout_addres/bloc/checkout_address_bloc.dart` | ソース | 状態管理Bloc |
| checkout_address_event.dart | `lib/screens/checkout/checkout_addres/bloc/checkout_address_event.dart` | ソース | イベント定義 |
| checkout_address_state.dart | `lib/screens/checkout/checkout_addres/bloc/checkout_address_state.dart` | ソース | 状態定義 |
| checkout_address_repository.dart | `lib/screens/checkout/checkout_addres/bloc/checkout_address_repository.dart` | ソース | リポジトリ層 |
| guest_add_address_form.dart | `lib/screens/checkout/guest_add_address/view/guest_add_address_form.dart` | ソース | ゲスト住所フォーム |
