# 画面設計書 14-チェックアウト画面

## 概要

本ドキュメントは、Bagisto eコマースモバイルアプリにおけるチェックアウト画面の設計仕様を定義するものです。チェックアウト画面は、注文確定までのステップを管理する購入フローの中核画面です。

### 本画面の処理概要

チェックアウト画面は、カートに入れた商品の購入を確定するための一連のステップ（住所選択、配送方法選択、支払方法選択、注文確認）を管理し、最終的に注文を確定させる画面です。

**業務上の目的・背景**：チェックアウトプロセスはeコマースの購買完了において最も重要な段階です。ユーザーが配送先住所、配送方法、支払方法を順番に選択し、最終的な注文内容を確認して購入を確定します。ステップ形式のUIにより、複雑な購入手続きをわかりやすく案内し、カート離脱率を下げることを目的としています。ログインユーザーとゲストユーザーで異なる住所入力フローを提供し、幅広いユーザーに対応します。

**画面へのアクセス方法**：
- カート画面の「チェックアウト」ボタンをタップ
- カートに商品がある状態でのみアクセス可能

**主要な操作・処理内容**：
1. ステップ1：配送先住所の選択/入力（ログインユーザーは既存住所選択、ゲストは新規入力）
2. ステップ2：配送方法の選択（ダウンロード商品のみの場合はスキップ）
3. ステップ3：支払方法の選択
4. ステップ4：注文内容の確認（レビュー）
5. 注文確定：注文完了画面へ遷移
6. 各ステップでの「進む」ボタンによるステップ遷移
7. ヘッダーのステップインジケーターによるナビゲーション

**画面遷移**：
- 遷移元：カート画面
- 遷移先：チェックアウト住所選択画面（住所変更時）、住所追加・編集画面、注文完了画面

**権限による表示制御**：ログインユーザーは登録済み住所から選択可能。ゲストユーザーは住所を直接入力する必要があります。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 36 | チェックアウト画面 | 主機能 | 注文確定プロセスのメイン画面（ステップ管理） |
| 37 | 配送先住所選択 | 補助機能 | チェックアウト時の配送先住所選択処理 |
| 38 | 配送方法選択 | 補助機能 | 配送方法の選択と保存処理 |
| 39 | 支払方法選択 | 補助機能 | 支払方法の選択と保存処理 |
| 40 | 注文確定 | 遷移先機能 | 注文の最終確定・発注処理 |

## 画面種別

ウィザード（ステップ形式）

## URL/ルーティング

```dart
const String checkoutScreen = 'checkoutScreen';
```

ルート定義：`Navigator.pushNamed(context, checkoutScreen, arguments: {...})`

## 入出力項目

| 項目名 | 入力/出力 | 型 | 必須 | 説明 |
|--------|----------|-----|------|------|
| total | 入力 | String? | × | カート合計金額（表示用） |
| cartScreenBloc | 入力 | CartScreenBloc? | × | カート画面のBloc |
| cartDetailsModel | 入力 | CartModel? | × | カートデータモデル |
| isDownloadable | 入力 | bool? | × | ダウンロード商品のみフラグ |

## 表示項目

| No | 項目名 | 型 | 表示条件 | 説明 |
|----|--------|-----|----------|------|
| 1 | AppBar | AppBar | 常時 | 現在のステップに応じたタイトル表示 |
| 2 | ステップヘッダー | CheckoutHeaderView | 常時 | ステップインジケーター（1-4） |
| 3 | 住所選択ビュー | CheckoutAddressView | ステップ1（ログインユーザー） | 既存住所選択UI |
| 4 | ゲスト住所入力フォーム | GuestAddAddressForm | ステップ1（ゲスト） | 住所入力フォーム |
| 5 | 配送方法選択ビュー | CheckoutShippingPageView | ステップ2 | 配送方法一覧と選択UI |
| 6 | 支払方法選択ビュー | CheckoutPaymentView | ステップ3 | 支払方法一覧と選択UI |
| 7 | 注文確認ビュー | CheckoutOrderReviewView | ステップ4 | 注文内容サマリー |
| 8 | 合計金額表示 | Card | 常時 | 支払金額と「進む」ボタン |
| 9 | 進む/注文確定ボタン | MaterialButton | 常時 | ステップ遷移または注文確定 |

## イベント仕様

### 1-ステップ1：住所選択/入力

**トリガー**：画面初期表示時（currentIndex = 1）

**処理フロー（ログインユーザー）**：
1. `CheckOutBloc`を生成し`CheckoutAddressView`を表示
2. ユーザーが請求先・配送先住所を選択
3. コールバックで住所情報を親画面に伝達
4. 「useForShipping」フラグで請求先住所を配送先にも使用するか制御

**処理フロー（ゲストユーザー）**：
1. `GuestAddressBloc`を生成し`GuestAddAddressForm`を表示
2. ユーザーが請求先・配送先住所を入力
3. コールバックで住所情報を親画面に伝達
4. バリデーション後、次のステップへ遷移

### 2-ステップ2：配送方法選択

**トリガー**：ステップ1完了後、「進む」ボタン押下

**処理フロー**：
1. `CheckOutShippingBloc`を生成し`CheckoutShippingPageView`を表示
2. 住所情報をAPIに送信し、利用可能な配送方法を取得
3. ユーザーが配送方法を選択
4. 選択した配送方法IDをコールバックで親画面に伝達
5. ダウンロード商品のみの場合は配送ステップをスキップし支払方法へ

### 3-ステップ3：支払方法選択

**トリガー**：ステップ2完了後、「進む」ボタン押下

**処理フロー**：
1. `CheckOutPaymentBloc`を生成し`CheckoutPaymentView`を表示
2. 利用可能な支払方法を表示
3. ユーザーが支払方法を選択
4. 選択した支払方法IDをコールバックで親画面に伝達
5. 金額更新をストリームで親画面に通知

### 4-ステップ4：注文確認

**トリガー**：ステップ3完了後、「進む」ボタン押下

**処理フロー**：
1. `CheckOutReviewBloc`を生成し`CheckoutOrderReviewView`を表示
2. 注文内容（商品、住所、配送方法、支払方法、金額）を表示
3. クーポン適用・削除の操作が可能
4. 金額更新をストリームで親画面に通知

### 5-注文確定

**トリガー**：ステップ4で「注文確定」ボタン押下

**処理フロー**：
1. currentIndexを5に設定
2. `Navigator.pushReplacementNamed(context, orderPlacedScreen, arguments: cartModel)`を実行
3. 注文完了画面へ遷移（カートモデルを引数として渡す）

### 6-バリデーション

**トリガー**：各ステップで「進む」ボタン押下時

**処理フロー**：
- ステップ1：住所が未入力の場合、警告メッセージを表示
- ステップ2：配送方法が未選択の場合、警告メッセージを表示
- ステップ3：支払方法が未選択の場合、警告メッセージを表示

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 住所選択/入力 | cart_addresses | INSERT/UPDATE | カートに住所情報を保存 |
| 配送方法選択 | cart | UPDATE | 選択した配送方法を保存 |
| 支払方法選択 | cart | UPDATE | 選択した支払方法を保存 |
| 注文確定 | orders, order_items, etc. | INSERT | 注文データを作成 |

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

#### cart（配送・支払情報）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | shipping_method, shipping_method_title | 選択した配送方法 | ステップ2 |
| UPDATE | payment_method | 選択した支払方法 | ステップ3 |

#### cart_addresses

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT/UPDATE | address_type, first_name, last_name, address, city, state, country, postcode, phone | 入力/選択した住所情報 | ステップ1 |

## メッセージ仕様

| No | メッセージID | メッセージ内容 | 表示タイミング | 種別 |
|----|------------|---------------|--------------|------|
| 1 | pleaseFillAddress | 住所を入力してください | 住所未入力時 | 警告 |
| 2 | pleaseFillBillingAddress | 請求先住所を入力してください | 請求先住所未入力時 | 警告 |
| 3 | pleaseFillShippingAddress | 配送先住所を入力してください | 配送先住所未入力時 | 警告 |
| 4 | pleaseSelectShipping | 配送方法を選択してください | 配送方法未選択時 | 警告 |
| 5 | pleaseSelectPayment | 支払方法を選択してください | 支払方法未選択時 | 警告 |
| 6 | addressTitle | 住所 | ステップ1タイトル | 情報 |
| 7 | shippingMethods | 配送方法 | ステップ2タイトル | 情報 |
| 8 | paymentMethods | 支払方法 | ステップ3タイトル | 情報 |
| 9 | reviewAndCheckout | 注文確認 | ステップ4タイトル | 情報 |
| 10 | proceed | 進む | 進むボタン | 情報 |
| 11 | placeOrder | 注文確定 | 注文確定ボタン | 情報 |
| 12 | cartPageAmountToBePaidLabel | お支払い金額 | 金額表示ラベル | 情報 |

## 例外処理

| No | 例外状況 | 対応処理 |
|----|---------|---------|
| 1 | 住所未入力で進もうとした | `ShowMessage.warningNotification`で警告表示 |
| 2 | 配送方法未選択で進もうとした | `ShowMessage.warningNotification`で警告表示 |
| 3 | 支払方法未選択で進もうとした | `ShowMessage.warningNotification`で警告表示 |
| 4 | API通信エラー | 各Blocでエラーハンドリング |
| 5 | 在庫切れ商品あり | 注文確定時にエラー表示 |

## 備考

- ステップヘッダー（`CheckoutHeaderView`）でステップ間のナビゲーションが可能
- ダウンロード商品のみの場合、配送ステップ（ステップ2）をスキップ
- 合計金額はStreamBuilderでリアルタイム更新
- ログインユーザーとゲストユーザーで住所入力UIが異なる
- 各ステップはBlocProviderで独立したBloc管理
- 注文確定後は`pushReplacementNamed`で注文完了画面へ遷移（戻り不可）

---

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

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

### 推奨読解順序

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

チェックアウト画面で扱うデータモデルの構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | cart_data_model.dart | `lib/screens/cart_screen/cart_model/cart_data_model.dart` | CartModel（カート情報全体）の構造 |
| 1-2 | checkout_save_address_model.dart | `lib/screens/checkout/data_model/checkout_save_address_model.dart` | 住所保存結果モデル |
| 1-3 | checkout_save_shipping_model.dart | `lib/screens/checkout/data_model/checkout_save_shipping_model.dart` | 配送方法保存結果モデル |
| 1-4 | save_payment_model.dart | `lib/screens/checkout/data_model/save_payment_model.dart` | 支払方法保存結果モデル |

**読解のコツ**: チェックアウト画面は複数のステップで構成され、各ステップで異なるBlocとモデルを使用します。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | checkout_screen.dart | `lib/screens/checkout/view/checkout_screen.dart` | CheckoutScreenクラス、ステップ管理ロジック |

**主要処理フロー**:
1. **行31-76**: State変数定義（住所情報、配送・支払ID等）
2. **行72-76**: initStateでログイン状態とメール取得
3. **行85-106**: buildメソッドでScaffold構築、動的タイトル
4. **行108-363**: `_getBody()`でステップに応じたUI切り替え
5. **行365-604**: 下部カード（金額表示と進む/注文確定ボタン）

#### Step 3: 各ステップの詳細を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | checkout_address_view.dart | `lib/screens/checkout/checkout_addres/view/checkout_address_view.dart` | ログインユーザーの住所選択 |
| 3-2 | guest_add_address_form.dart | `lib/screens/checkout/guest_add_address/view/guest_add_address_form.dart` | ゲストの住所入力 |
| 3-3 | checkout_shipping_view.dart | `lib/screens/checkout/checkout_shipping/view/checkout_shipping_view.dart` | 配送方法選択 |
| 3-4 | checkout_payment_view.dart | `lib/screens/checkout/checkout_payment/view/checkout_payment_view.dart` | 支払方法選択 |
| 3-5 | checkout_order_review_view.dart | `lib/screens/checkout/checkout_review/view/checkout_order_review_view.dart` | 注文確認 |

#### Step 4: 状態管理（BLoC）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | checkout_address_bloc.dart | `lib/screens/checkout/checkout_addres/bloc/checkout_address_bloc.dart` | 住所選択Bloc |
| 4-2 | checkout_shipping_bloc.dart | `lib/screens/checkout/checkout_shipping/bloc/checkout_shipping_bloc.dart` | 配送方法Bloc |
| 4-3 | checkout_payment_bloc.dart | `lib/screens/checkout/checkout_payment/bloc/checkout_payment_bloc.dart` | 支払方法Bloc |
| 4-4 | checkout_review_bloc.dart | `lib/screens/checkout/checkout_review/bloc/checkout_review_bloc.dart` | 注文確認Bloc |

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

```
CheckoutScreen (checkout_screen.dart)
    │
    ├─ currentIndex = 1
    │      ├─ [ログインユーザー] CheckOutBloc + CheckoutAddressView
    │      └─ [ゲスト] GuestAddressBloc + GuestAddAddressForm
    │
    ├─ currentIndex = 2
    │      └─ CheckOutShippingBloc + CheckoutShippingPageView
    │
    ├─ currentIndex = 3
    │      └─ CheckOutPaymentBloc + CheckoutPaymentView
    │
    ├─ currentIndex = 4
    │      └─ CheckOutReviewBloc + CheckoutOrderReviewView
    │
    └─ currentIndex = 5
           └─ Navigator.pushReplacementNamed → orderPlacedScreen
```

### データフロー図

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

CartScreen ──────────▶ CheckoutScreen ──────────▶ 注文完了画面
   │                        │
   │                        ├─ Step 1: 住所
   │ cartModel,             │      └─ callback → 住所情報保存
   │ total,                 │
   │ isDownloadable         ├─ Step 2: 配送
   │                        │      └─ callback → shippingId保存
   │                        │
   │                        ├─ Step 3: 支払
   │                        │      └─ callback → paymentId保存
   │                        │
   │                        └─ Step 4: 確認
   │                               └─ 注文確定 → CartModel渡し
   │
   └──────────────────────────────────────────────▶ OrderPlacedScreen
                                                         │
                                                         └─ cartModel引数
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| checkout_screen.dart | `lib/screens/checkout/view/checkout_screen.dart` | ソース | メイン画面（ステップ管理） |
| checkout_header_view.dart | `lib/screens/checkout/view/checkout_header_view.dart` | ソース | ステップヘッダー |
| checkout_address_view.dart | `lib/screens/checkout/checkout_addres/view/checkout_address_view.dart` | ソース | 住所選択（ログイン） |
| guest_add_address_form.dart | `lib/screens/checkout/guest_add_address/view/guest_add_address_form.dart` | ソース | 住所入力（ゲスト） |
| checkout_shipping_view.dart | `lib/screens/checkout/checkout_shipping/view/checkout_shipping_view.dart` | ソース | 配送方法選択 |
| checkout_payment_view.dart | `lib/screens/checkout/checkout_payment/view/checkout_payment_view.dart` | ソース | 支払方法選択 |
| checkout_order_review_view.dart | `lib/screens/checkout/checkout_review/view/checkout_order_review_view.dart` | ソース | 注文確認 |
| checkout_address_bloc.dart | `lib/screens/checkout/checkout_addres/bloc/checkout_address_bloc.dart` | ソース | 住所Bloc |
| checkout_shipping_bloc.dart | `lib/screens/checkout/checkout_shipping/bloc/checkout_shipping_bloc.dart` | ソース | 配送Bloc |
| checkout_payment_bloc.dart | `lib/screens/checkout/checkout_payment/bloc/checkout_payment_bloc.dart` | ソース | 支払Bloc |
| checkout_review_bloc.dart | `lib/screens/checkout/checkout_review/bloc/checkout_review_bloc.dart` | ソース | 確認Bloc |
| index.dart | `lib/screens/checkout/utils/index.dart` | ソース | エクスポート集約 |
| route_constants.dart | `lib/utils/route_constants.dart` | 設定 | ルート定数定義 |
