# 機能設計書 38-配送方法選択

## 概要

本ドキュメントは、チェックアウト時の配送方法選択と保存機能の設計を記述する。

### 本機能の処理概要

本機能は、チェックアウト画面のステップ2で、利用可能な配送方法の一覧を表示し、ユーザーが希望する配送方法を選択する機能である。

**業務上の目的・背景**：ECサイトにおいて、配送方法はユーザーの利便性とコストに直接影響する。本機能により、複数の配送オプション（通常配送、速達、店舗受取など）から選択でき、配送料金と配送時間のトレードオフを考慮した選択が可能になる。

**機能の利用シーン**：チェックアウト画面のステップ2（配送方法選択）で本機能が使用される。住所選択完了後に自動的に配送方法が取得される。

**主要な処理内容**：
1. 住所情報をもとにGraphQL APIで住所保存と配送方法一覧取得
2. 利用可能な配送方法をラジオボタンリストで表示
3. ユーザーが配送方法を選択
4. 選択した配送方法IDをcallBackで親画面に渡す
5. ダウンロード商品のみの場合はステップをスキップ

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

**権限による制御**：ログインユーザー・ゲストユーザー共に利用可能

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 14 | チェックアウト画面 | 主画面 | 配送方法の選択と保存 |

## 機能種別

データ取得・選択・保存処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| billingCompanyName | String? | No | 請求先会社名 | - |
| billingFirstName | String? | No | 請求先名（姓） | - |
| billingLastName | String? | No | 請求先名（名） | - |
| billingAddress | String? | No | 請求先住所 | - |
| billingEmail | String? | No | 請求先メール | - |
| billingCountry | String? | No | 請求先国コード | - |
| billingState | String? | No | 請求先都道府県 | - |
| billingCity | String? | No | 請求先市区町村 | - |
| billingPostCode | String? | No | 請求先郵便番号 | - |
| billingPhone | String? | No | 請求先電話番号 | - |
| shippingCompanyName | String? | No | 配送先会社名 | - |
| shippingFirstName | String? | No | 配送先名（姓） | - |
| shippingLastName | String? | No | 配送先名（名） | - |
| shippingAddress | String? | No | 配送先住所 | - |
| shippingEmail | String? | No | 配送先メール | - |
| shippingCountry | String? | No | 配送先国コード | - |
| shippingState | String? | No | 配送先都道府県 | - |
| shippingCity | String? | No | 配送先市区町村 | - |
| shippingPostCode | String? | No | 配送先郵便番号 | - |
| shippingPhone | String? | No | 配送先電話番号 | - |
| billingId | int | Yes | 請求先住所ID | - |
| shippingId | int | Yes | 配送先住所ID | - |
| useForShipping | bool | No | 請求先を配送先として使用 | - |
| callBack | Function | Yes | 選択完了時のコールバック | - |
| isDownloadable | bool | No | ダウンロード商品フラグ | - |

### 入力データソース

- 親画面（CheckoutScreen）から渡される住所情報

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| shippingMethods | List<ShippingMethod> | 配送方法一覧 |
| shippingMethods[].title | String | 配送方法名 |
| shippingMethods[].methods.code | String | 配送方法コード |
| shippingMethods[].methods.formattedPrice | String | 配送料金（フォーマット済み） |

### 出力先

- 画面表示: 配送方法ラジオボタンリスト
- 親画面への callBack: 選択した配送方法コード

## 処理フロー

### 処理シーケンス

```
1. 配送ビュー表示時にCheckOutFetchShippingEvent発火
   └─ build内でBloc.add実行
2. Blocがリポジトリを通じてAPI呼び出し
   └─ CheckOutShippingRepository.saveCheckoutShippingAddress
3. ApiClient.saveAddressでGraphQL通信
   └─ saveCheckoutAddresses mutationを実行
4. 住所保存と同時に配送方法一覧を取得
   └─ SaveCheckoutAddressesレスポンスにshippingMethods含む
5. 配送方法をラジオボタンリストで表示
   └─ RadioButtonGroupウィジェット使用
6. ユーザーが配送方法を選択
   └─ onChange callbackで選択検知
7. callBackで親画面に配送方法コードを渡す
```

### フローチャート

```mermaid
flowchart TD
    A[配送ビュー表示] --> B[住所保存API呼び出し]
    B --> C{API成功?}
    C -->|Yes| D{配送方法あり?}
    C -->|No| E[エラー表示]
    D -->|Yes| F[配送方法リスト表示]
    D -->|No| G[配送方法なし通知]
    F --> H[ユーザーが配送方法選択]
    H --> I[callBackで親画面に通知]
    I --> J[次ステップへ]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-38-01 | 住所保存 | 配送方法取得時に住所も保存される | API呼び出し時 |
| BR-38-02 | 配送方法なし | 配送方法が取得できない場合は警告表示 | API成功時 |
| BR-38-03 | ダウンロード商品 | ダウンロード商品のみの場合、配送不要のため支払方法へスキップ | isDownloadable=true時 |
| BR-38-04 | 支払方法スキップ | jumpToSection="payment"の場合、支払方法選択へジャンプ | API応答時 |

### 計算ロジック

- 配送料金は各methodsのformattedPriceを表示

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 住所保存 | cart_addresses | INSERT/UPDATE | カートの配送先住所保存 |

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

#### cart_addresses

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT/UPDATE | cart_id, address_type, address... | カートID、住所情報 | バックエンドで処理 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | graphqlErrors | API通信失敗 | エラーメッセージ表示 |
| - | 配送方法なし | 対象地域配送不可 | 「配送方法がありません」通知 |

### リトライ仕様

自動リトライなし。

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

バックエンドAPIでトランザクション管理。

## パフォーマンス要件

- API応答時間: 3秒以内

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

- 住所情報の暗号化通信（HTTPS）
- セッション/トークンで注文の紐付け

## 備考

- 配送方法選択は必須（未選択では次ステップ不可）

---

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

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

### 推奨読解順序

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

配送方法データのモデル構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | checkout_save_address_model.dart | `lib/screens/checkout/data_model/checkout_save_address_model.dart` | SaveCheckoutAddresses、ShippingMethodsクラスの構造 |

**読解のコツ**: SaveCheckoutAddressesにshippingMethodsリストが含まれ、各要素にtitleとmethods（code, formattedPrice）がある。

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

配送方法選択ビューの実装を確認する。

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

**主要処理フロー**:
- **91-120行目**: build内でCheckOutFetchShippingEvent発火
- **121-143行目**: BlocConsumerでlistener/builder設定
- **147-173行目**: 状態に応じたUI構築
- **175-212行目**: _shippingMethodsメソッドで配送方法リスト表示

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

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

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

**主要処理フロー**:
- checkout_shipping_repository.dart **20-42行目**: saveAddress呼び出し

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

```
CheckoutShippingPageView (UI)
    │
    ├─ build: CheckOutShippingBloc.add(CheckOutFetchShippingEvent)
    │      │
    │      └─ CheckOutShippingRepository.saveCheckoutShippingAddress(...)
    │             │
    │             └─ ApiClient.saveAddress(...)
    │                    │
    │                    └─ GraphQL mutation: saveCheckoutAddresses
    │
    ├─ UI描画
    │      └─ RadioButtonGroup（配送方法リスト）
    │
    └─ onChange callback
           └─ 親画面へ配送方法コードを通知
```

### データフロー図

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

住所情報 ──────────────▶ CheckOutShippingBloc ────▶ 配送方法リスト
                              │
                        CheckOutShippingRepository
                              │
                        ApiClient.saveAddress
                              │
                        GraphQL Server

配送選択 ──────────────▶ callBack ─────────────▶ 親画面へ通知
                                                    │
                                              shippingId更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| checkout_shipping_view.dart | `lib/screens/checkout/checkout_shipping/view/checkout_shipping_view.dart` | ソース | 配送方法選択メインビュー |
| checkout_shipping_bloc.dart | `lib/screens/checkout/checkout_shipping/bloc/checkout_shipping_bloc.dart` | ソース | 状態管理Bloc |
| checkout_shipping_event.dart | `lib/screens/checkout/checkout_shipping/bloc/checkout_shipping_event.dart` | ソース | イベント定義 |
| checkout_shipping_state.dart | `lib/screens/checkout/checkout_shipping/bloc/checkout_shipping_state.dart` | ソース | 状態定義 |
| checkout_shipping_repository.dart | `lib/screens/checkout/checkout_shipping/bloc/checkout_shipping_repository.dart` | ソース | リポジトリ層 |
| checkout_save_address_model.dart | `lib/screens/checkout/data_model/checkout_save_address_model.dart` | ソース | データモデル |
| api_client.dart | `lib/services/api_client.dart` | ソース | API通信クライアント |
