# 機能設計書 40-注文確定

## 概要

本ドキュメントは、注文の最終確定・発注処理機能の設計を記述する。

### 本機能の処理概要

本機能は、チェックアウト画面のステップ4（注文確認）を経て、最終的に注文を確定し発注処理を行う機能である。

**業務上の目的・背景**：ECサイトにおける購入フローの最終段階。ユーザーが入力した配送先、配送方法、支払方法を最終確認し、問題がなければ注文を確定する。この処理により、カート内商品が正式な注文として登録され、後続の決済・配送プロセスが開始される。

**機能の利用シーン**：チェックアウト画面で全ステップ完了後、「注文確定」ボタンをタップした際に本機能が実行される。

**主要な処理内容**：
1. 支払方法を保存し、注文確認データを取得
2. 注文確認ビュー（OrderSummary）で注文内容を表示
3. クーポンコード適用機能を提供
4. 「注文確定」ボタンタップで注文完了画面へ遷移
5. 注文完了画面でplaceOrder APIを呼び出し、注文を確定
6. PayPal等の外部決済の場合は決済フローを実行
7. 注文完了後、注文IDと確認メッセージを表示

**関連システム・外部連携**：
- GraphQL APIを介したBagistoバックエンドとの通信
- PayPal決済連携（PayPal Standard、PayPal Smart Button）
- その他決済ゲートウェイ連携（Stripe等）

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 14 | チェックアウト画面 | 主画面 | 注文の最終確定・発注処理 |
| - | 注文完了画面 | 遷移先 | 注文確定後の完了表示 |

## 機能種別

データ保存・注文確定処理（CREATE操作）

## 入力仕様

### 入力パラメータ（注文確認ビュー）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| paymentId | String | Yes | 選択された支払方法コード | - |
| callBack | Function | Yes | 価格更新用コールバック | - |
| cartDetailsModel | CartModel | No | カート詳細データ | - |
| cartScreenBloc | CartScreenBloc | No | カート画面のBloc参照 | - |

### 入力パラメータ（注文確定処理）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| cartModel | CartModel | Yes | カート情報（注文内容） | - |
| serverPayload | Map<String, dynamic>? | No | 外部決済情報（PayPal等） | - |

### 入力データソース

- 親画面（CheckoutScreen）から渡される支払方法コードとカート情報

## 出力仕様

### 出力データ（注文確認ビュー）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| cart.billingAddress | Address | 請求先住所 |
| cart.shippingAddress | Address | 配送先住所 |
| cart.selectedShippingRate | ShippingRate | 選択された配送方法 |
| cart.payment | Payment | 選択された支払方法 |
| cart.formattedPrice.grandTotal | String | 合計金額 |

### 出力データ（注文確定処理）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| order.id | int | 注文ID |
| order.incrementId | String | 注文番号（表示用） |
| redirectUrl | String? | 外部決済リダイレクトURL |

### 出力先

- 注文確認ビュー: 注文内容サマリー表示
- 注文完了画面: 注文確定後の完了メッセージ

## 処理フロー

### 処理シーケンス（注文確認ビュー）

```
1. 注文確認ビュー表示時にCheckOutReviewSavePaymentEvent発火
   └─ initState内でBloc.add実行
2. Blocがリポジトリを通じてAPI呼び出し
   └─ CheckOutReviewRepository.savePaymentReview
3. ApiClient.saveAndReviewでGraphQL通信
   └─ savePayment mutationを実行
4. 支払方法保存と同時に注文確認データを取得
   └─ SavePaymentレスポンスにcart情報含む
5. 注文確認UIを表示
   └─ 住所、配送方法、支払方法、合計金額を表示
6. クーポン適用機能を提供
   └─ ApplyCouponCodeウィジェット
```

### 処理シーケンス（注文確定処理）

```
1. 「注文確定」ボタンタップ
   └─ CheckoutScreenからorderPlacedScreenへ遷移
2. 注文完了画面でSaveOrderFetchDataEvent発火
   └─ initState内でBloc.add実行
3. Blocがリポジトリを通じてAPI呼び出し
   └─ SaveOrderRepository.savePaymentReview
4. ApiClient.placeOrderでGraphQL通信
   └─ placeOrder mutationを実行
5. 支払方法に応じた処理分岐
   └─ PayPal: 決済フロー実行後にAPI呼び出し
   └─ その他: 直接API呼び出し
6. 注文確定成功後、完了画面表示
   └─ 注文番号、確認メッセージ表示
```

### フローチャート

```mermaid
flowchart TD
    A[注文確認ビュー表示] --> B[支払方法保存API]
    B --> C[注文確認データ取得]
    C --> D[注文内容サマリー表示]
    D --> E{クーポン適用?}
    E -->|Yes| F[クーポンAPI呼び出し]
    E -->|No| G[「注文確定」ボタンタップ]
    F --> D
    G --> H[注文完了画面へ遷移]
    H --> I{支払方法?}
    I -->|PayPal| J[PayPal決済フロー]
    I -->|その他| K[placeOrder API呼び出し]
    J --> L{決済成功?}
    L -->|Yes| K
    L -->|No| M[エラー表示、画面戻り]
    K --> N{注文成功?}
    N -->|Yes| O[注文完了表示]
    N -->|No| P[エラー表示]
    O --> Q[「買い物を続ける」ボタン]
    Q --> R[ホーム画面へ遷移]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-40-01 | 支払方法保存 | 注文確認表示時に支払方法を保存 | ステップ4表示時 |
| BR-40-02 | PayPal決済 | paypal_standard/paypal_smart_buttonの場合は決済フロー実行 | 該当支払方法選択時 |
| BR-40-03 | 注文番号表示 | 注文確定後はincrementIdを表示 | 注文成功時 |
| BR-40-04 | カートクリア | 注文確定後はカートがクリアされる | 注文成功時 |
| BR-40-05 | 注文詳細リンク | ログインユーザーは注文詳細画面へリンク可能 | ログインユーザー時 |

### 計算ロジック

- 合計金額はcart.formattedPrice.grandTotalを使用
- クーポン適用後は金額が再計算される

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 支払方法保存 | cart_payment | INSERT/UPDATE | カートの支払方法保存 |
| 注文確定 | orders | INSERT | 注文データ作成 |
| 注文確定 | order_items | INSERT | 注文明細データ作成 |
| 注文確定 | order_addresses | INSERT | 注文住所データ作成 |
| 注文確定 | cart_items | DELETE | カートアイテムクリア |

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

#### orders

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | customer_id, status, grand_total, ... | 注文情報 | バックエンドで処理 |

#### order_items

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | order_id, product_id, qty, price, ... | カートアイテムからコピー | バックエンドで処理 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | graphqlErrors | API通信失敗 | エラーメッセージ表示 |
| - | 在庫不足 | 注文確定時に在庫切れ | エラーメッセージ表示、カート再確認促す |
| - | 決済エラー | PayPal決済失敗 | エラー通知、画面戻り |

### リトライ仕様

自動リトライなし。ユーザーが再度注文確定を試みる必要がある。

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

バックエンドAPIでトランザクション管理。注文作成は単一トランザクションで処理。

## パフォーマンス要件

- API応答時間: 5秒以内（決済処理含む）
- 外部決済: 決済プロバイダの応答に依存

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

- 決済情報は外部決済プロバイダで処理（PCI DSS準拠）
- PayPalのClient ID/Secretはサーバーサイドで管理
- 注文確定APIは認証済みリクエストのみ受付

## 備考

- PayPal Smart ButtonはNative連携（MethodChannel使用）
- PayPal Standardはflutter_paypal_paymentパッケージ使用

---

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

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

### 推奨読解順序

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

注文確認・注文確定データのモデル構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | save_payment_model.dart | `lib/screens/checkout/data_model/save_payment_model.dart` | SavePaymentクラスの構造 |
| 1-2 | save_order_model.dart | `lib/screens/checkout/data_model/save_order_model.dart` | SaveOrderModelクラスの構造 |

**読解のコツ**: SavePaymentにはcart情報が、SaveOrderModelにはorder情報とredirectUrlが含まれる。

#### Step 2: 注文確認ビューを理解する

注文確認画面の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | checkout_order_review_view.dart | `lib/screens/checkout/checkout_review/view/checkout_order_review_view.dart` | 注文確認メインビュー |
| 2-2 | order_summary.dart | `lib/screens/checkout/checkout_review/view/widget/order_summary.dart` | 注文サマリーウィジェット |
| 2-3 | apply_coupon_code.dart | `lib/screens/checkout/checkout_review/view/widget/apply_coupon_code.dart` | クーポン適用ウィジェット |

**主要処理フロー**:
- checkout_order_review_view.dart **44-48行目**: initStateでイベント発火
- checkout_order_review_view.dart **91-229行目**: _reviewOrderメソッドでUI構築

#### Step 3: 注文確定処理を理解する

注文完了画面と確定処理の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | save_order.dart | `lib/screens/checkout/checkout_save_order/view/save_order.dart` | 注文完了画面 |
| 3-2 | save_order_bloc.dart | `lib/screens/checkout/checkout_save_order/bloc/save_order_bloc.dart` | 状態管理Bloc |
| 3-3 | save_order_repositroy.dart | `lib/screens/checkout/checkout_save_order/bloc/save_order_repositroy.dart` | リポジトリ層 |

**主要処理フロー**:
- save_order.dart **36-73行目**: initStateでの初期化とPayPal分岐
- save_order.dart **176-199行目**: buildUIメソッドで状態に応じたUI構築
- save_order.dart **201-314行目**: _orderPlacedViewで完了表示
- save_order.dart **316-354行目**: paypalViewでPayPal決済処理

#### Step 4: Repository層を理解する

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | checkout_review_repository.dart | `lib/screens/checkout/checkout_review/bloc/checkout_review_repository.dart` | 支払方法保存リポジトリ |
| 4-2 | save_order_repositroy.dart | `lib/screens/checkout/checkout_save_order/bloc/save_order_repositroy.dart` | 注文確定リポジトリ |

**主要処理フロー**:
- checkout_review_repository.dart **21-30行目**: saveAndReview呼び出し
- save_order_repositroy.dart **23-32行目**: placeOrder呼び出し

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

```
CheckoutOrderReviewView (注文確認)
    │
    ├─ initState: CheckOutReviewBloc.add(CheckOutReviewSavePaymentEvent)
    │      │
    │      └─ CheckOutReviewRepository.savePaymentReview(paymentMethod)
    │             │
    │             └─ ApiClient.saveAndReview(paymentMethod)
    │                    │
    │                    └─ GraphQL mutation: savePayment
    │
    └─ UI描画
           ├─ 住所表示
           ├─ 配送方法表示
           ├─ 支払方法表示
           ├─ OrderSummary
           └─ ApplyCouponCode


CheckOutSaveOrder (注文完了)
    │
    ├─ initState分岐
    │      ├─ PayPal: PayPal決済フロー
    │      └─ その他: SaveOrderFetchDataEvent
    │
    ├─ SaveOrderBloc.add(SaveOrderFetchDataEvent)
    │      │
    │      └─ SaveOrderRepository.savePaymentReview(serverPayload)
    │             │
    │             └─ ApiClient.placeOrder(serverPayload)
    │                    │
    │                    └─ GraphQL mutation: placeOrder
    │
    └─ UI描画
           ├─ 注文番号表示
           ├─ 確認メッセージ
           └─ 「買い物を続ける」ボタン
```

### データフロー図

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

支払方法 ──────────────▶ CheckOutReviewBloc ─────▶ 注文確認表示
                              │
                        CheckOutReviewRepository
                              │
                        ApiClient.saveAndReview
                              │
                        GraphQL Server

「注文確定」タップ ────▶ orderPlacedScreen遷移 ──▶ 注文完了画面
                              │
                        SaveOrderBloc
                              │
                        SaveOrderRepository
                              │
                        ApiClient.placeOrder
                              │
                        GraphQL Server ──────────▶ 注文番号表示
                                                  カートクリア
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| checkout_order_review_view.dart | `lib/screens/checkout/checkout_review/view/checkout_order_review_view.dart` | ソース | 注文確認メインビュー |
| order_summary.dart | `lib/screens/checkout/checkout_review/view/widget/order_summary.dart` | ソース | 注文サマリー |
| apply_coupon_code.dart | `lib/screens/checkout/checkout_review/view/widget/apply_coupon_code.dart` | ソース | クーポン適用 |
| checkout_review_bloc.dart | `lib/screens/checkout/checkout_review/bloc/checkout_review_bloc.dart` | ソース | 確認Bloc |
| checkout_review_repository.dart | `lib/screens/checkout/checkout_review/bloc/checkout_review_repository.dart` | ソース | 確認リポジトリ |
| save_order.dart | `lib/screens/checkout/checkout_save_order/view/save_order.dart` | ソース | 注文完了画面 |
| payment_web_view.dart | `lib/screens/checkout/checkout_save_order/view/payment_web_view.dart` | ソース | 外部決済WebView |
| save_order_bloc.dart | `lib/screens/checkout/checkout_save_order/bloc/save_order_bloc.dart` | ソース | 注文Bloc |
| save_order_repositroy.dart | `lib/screens/checkout/checkout_save_order/bloc/save_order_repositroy.dart` | ソース | 注文リポジトリ |
| save_payment_model.dart | `lib/screens/checkout/data_model/save_payment_model.dart` | ソース | 支払保存モデル |
| save_order_model.dart | `lib/screens/checkout/data_model/save_order_model.dart` | ソース | 注文確定モデル |
| api_client.dart | `lib/services/api_client.dart` | ソース | API通信クライアント |
