# 画面設計書 22-注文編集ページ

## 概要

本ドキュメントは、Shopware 6 Storefrontの注文編集ページ（Edit Order Page）の画面設計書である。支払いに失敗した注文や支払い方法を変更したい注文に対して、顧客が支払い方法を変更し再度支払いを実行するための画面について記載する。

### 本画面の処理概要

注文編集ページは、既存の注文に対して支払い方法を変更し、支払いを再実行するための画面である。

**業務上の目的・背景**：オンライン決済が失敗した場合や、顧客が別の支払い方法に変更したい場合に、新たに注文をやり直すことなく既存注文の支払い方法を変更できる。これにより、顧客の利便性向上とコンバージョン率の改善を実現する。注文返金機能が有効な場合は、この画面から注文キャンセルも可能。

**画面へのアクセス方法**：
- 注文履歴ページから「支払い方法を変更」ボタンをクリック
- 支払い失敗後のリダイレクト
- 注文完了ページからのエラー時リダイレクト

**主要な操作・処理内容**：
1. 注文内容の確認（商品明細、配送先、請求先）
2. 支払い方法の選択・変更
3. 支払いの再実行
4. 注文キャンセル（返金機能有効時のみ）

**画面遷移**：
- 遷移元：注文履歴ページ、注文完了ページ（支払い失敗時）
- 遷移先：注文完了ページ（成功時）、注文履歴ページ（キャンセル時）

**権限による表示制御**：
- ログインユーザー：自身の注文のみ編集可能
- ゲストユーザー：deepLinkCodeを使用してアクセス可能
- 支払い変更不可の場合：ボタンが無効化される

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 25 | 支払方法変更 | 主機能 | 注文の支払方法変更（AccountOrderController::orderChangePayment） |
| 26 | 注文更新 | 補助機能 | 支払いの再処理（AccountOrderController::updateOrder） |

## 画面種別

編集

## URL/ルーティング

| ルート名 | URL | HTTPメソッド | 説明 |
|----------|-----|--------------|------|
| frontend.account.edit-order.page | /account/order/edit/{orderId} | GET | 注文編集画面表示 |
| frontend.account.edit-order.change-payment-method | /account/order/payment/{orderId} | POST | 支払い方法変更 |
| frontend.account.edit-order.update-order | /account/order/update/{orderId} | POST | 注文更新・支払い実行 |

## 入出力項目

### 入力項目

| 項目名 | パラメータ名 | 型 | 必須 | 説明 |
|--------|-------------|-----|------|------|
| 注文ID | orderId | string(UUID) | 必須 | 編集対象の注文ID |
| ディープリンクコード | deepLinkCode | string | - | ゲスト注文確認用コード |
| 支払い方法ID | paymentMethodId | string(UUID) | - | 選択した支払い方法 |
| エラーコード | error-code | string | - | 前回のエラーコード |

### 出力項目

| 項目名 | 型 | 説明 |
|--------|-----|------|
| page | AccountEditOrderPage | 注文編集ページオブジェクト |
| page.order | OrderEntity | 編集対象の注文 |
| page.paymentMethods | PaymentMethodCollection | 選択可能な支払い方法 |
| page.paymentChangeable | bool | 支払い変更可否フラグ |

## 表示項目

### 注文情報

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| 注文番号 | order.orderNumber | 注文の識別番号 |
| 注文ステータス | order.stateMachineState.technicalName | 注文状態 |

### 配送先住所

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| 氏名 | primaryOrderDelivery.shippingOrderAddress.firstName/lastName | 配送先氏名 |
| 敬称 | primaryOrderDelivery.shippingOrderAddress.salutation | 敬称 |
| 住所 | primaryOrderDelivery.shippingOrderAddress | 住所情報 |
| 国 | primaryOrderDelivery.shippingOrderAddress.country | 国 |

### 請求先住所

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| 氏名 | order.billingAddress.firstName/lastName | 請求先氏名 |
| 住所 | order.billingAddress | 住所情報 |
| 国 | order.billingAddress.country | 国 |

### 商品明細

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| 商品名 | lineItem.label | 商品名 |
| 商品画像 | lineItem.cover | サムネイル |
| 数量 | lineItem.quantity | 数量 |
| 単価 | lineItem.unitPrice | 単価 |
| 合計 | lineItem.totalPrice | 小計 |

### 支払い方法選択

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| 支払い方法名 | paymentMethod.name | 支払い方法の名称 |
| 支払い方法説明 | paymentMethod.description | 支払い方法の説明 |
| アイコン | paymentMethod.media | 支払い方法のアイコン |

## イベント仕様

### 1-支払い方法変更

支払い方法を選択し「支払い方法を変更」ボタンをクリック。frontend.account.edit-order.change-payment-methodへPOSTし、コンテキストの支払い方法を切り替え後、同じ画面にリダイレクト。

### 2-支払い実行

「注文を更新」ボタンをクリック。frontend.account.edit-order.update-orderへPOSTし、支払い処理を実行。成功時は注文完了ページへ、失敗時はエラー表示。

### 3-注文キャンセル

「注文をキャンセル」ボタンをクリック（返金機能有効時のみ表示）。確認モーダル表示後、キャンセル処理を実行。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 支払い方法変更 | order_transaction | UPDATE | 支払い方法IDを更新 |
| 支払い実行 | order_transaction | UPDATE | 支払いステータスを更新 |
| 支払い実行 | state_machine_history | INSERT | 状態遷移履歴を記録 |
| 注文キャンセル | order | UPDATE | 注文ステータスをcancelledに更新 |

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

#### order_transaction

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | payment_method_id | 選択された支払い方法ID | 支払い方法変更時 |
| UPDATE | state_id | 新しい状態ID | 支払い実行時 |
| UPDATE | updated_at | 現在日時 | 自動更新 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| account.completePayment | 表示 | 支払いを完了する | ページヘッダー |
| account.editOrderPaymentNotChangeable | エラー | 支払い方法を変更できません | 変更不可時 |
| account.editOrderPaymentNotChangeableWithRefunds | エラー | 返金があるため支払い方法を変更できません | 返金機能有効かつ変更不可時 |
| account.externalPaymentCanceled | エラー | 外部決済がキャンセルされました | error-code=CHECKOUT__CUSTOMER_CANCELED_EXTERNAL_PAYMENT |
| account.externalPaymentExpired | エラー | 決済トークンが期限切れです | error-code=CHECKOUT__PAYMENT_TOKEN_EXPIRED |
| account.externalPaymentFailure | エラー | 外部決済に失敗しました | その他のエラーコード |
| account.editOrderUpdateButton | 表示 | 注文を更新 | 更新ボタン |
| account.editOrderCancelOrderButton | 表示 | 注文をキャンセル | キャンセルボタン |

## 例外処理

| 例外 | 原因 | 処理内容 |
|------|------|----------|
| OrderException::orderNotFound | 注文が存在しない | エラーメッセージ表示、注文履歴へリダイレクト |
| OrderException::orderCancelled | 注文がキャンセル済み | エラーメッセージ表示、注文履歴へリダイレクト |
| OrderException::orderAlreadyPaid | 注文が支払い済み | エラーメッセージ表示、注文履歴へリダイレクト |
| OrderException::paymentMethodNotChangeable | 支払い方法変更不可 | エラーメッセージ表示 |
| PaymentException | 支払い処理失敗 | 注文完了ページにエラー情報を付与して遷移 |
| InvalidUuidException | 不正な注文ID | 注文なしとして処理 |

## 備考

- 支払い方法はafterOrderEnabled=trueのもののみ表示
- 注文の通貨と現在のコンテキスト通貨が異なる場合、自動的に切り替え
- 配送方法も注文時のものに自動的に切り替え
- v6.8.0からprimaryOrderDelivery/primaryOrderTransactionを使用（deliveries/transactionsは非推奨）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AccountEditOrderPage.php | `src/Storefront/Page/Account/Order/AccountEditOrderPage.php` | order, paymentMethods, paymentChangeableプロパティ |
| 1-2 | OrderEntity.php | `src/Core/Checkout/Order/OrderEntity.php` | 注文エンティティ構造 |
| 1-3 | PaymentMethodCollection.php | `src/Core/Checkout/Payment/PaymentMethodCollection.php` | 支払い方法コレクション |

**読解のコツ**: AccountEditOrderPageはAccountOrderPageとは異なり、単一の注文と支払い方法リストを保持する構造。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AccountOrderController.php | `src/Storefront/Controller/AccountOrderController.php` | editOrder(), orderChangePayment(), updateOrder()メソッド |

**主要処理フロー**:
1. **194-281行**: editOrder() - 注文編集画面表示
2. **283-300行**: orderChangePayment() - 支払い方法変更
3. **302-379行**: updateOrder() - 注文更新・支払い実行

#### Step 3: ページローダーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AccountEditOrderPageLoader.php | `src/Storefront/Page/Account/Order/AccountEditOrderPageLoader.php` | load(), getPaymentMethods(), isPaymentChangeable() |

**主要処理フロー**:
- **63-97行**: load() - ページ読み込み、キャンセル済み/支払い済みチェック
- **167-187行**: getPaymentMethods() - 支払い方法取得（afterOrderEnabled=trueのみ）
- **226-232行**: isPaymentChangeable() - 支払い変更可否判定

#### Step 4: テンプレートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | index.html.twig | `src/Storefront/Resources/views/storefront/page/account/order/index.html.twig` | メインテンプレート |
| 4-2 | confirm-payment.html.twig | `src/Storefront/Resources/views/storefront/page/account/order/confirm-payment.html.twig` | 支払い方法選択部分 |
| 4-3 | address.html.twig | `src/Storefront/Resources/views/storefront/page/account/order/address.html.twig` | 住所表示部分 |
| 4-4 | cancel-order-modal.html.twig | `src/Storefront/Resources/views/storefront/page/account/order/cancel-order-modal.html.twig` | キャンセル確認モーダル |

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

```
AccountOrderController::editOrder()
    │
    ├─ AbstractOrderRoute::load() // 注文取得
    │
    ├─ isOrderCancelled() / isOrderPaid() チェック
    │
    ├─ contextSwitchRoute::switchContext() // 通貨・配送方法切り替え
    │
    ├─ AccountEditOrderPageLoader::load()
    │      ├─ GenericPageLoaderInterface::load()
    │      ├─ getOrder()
    │      ├─ isOrderCancelled() / isOrderPaid()
    │      ├─ getPaymentMethods()
    │      │      ├─ OrderConverter::convertToCart()
    │      │      ├─ CheckoutGatewayRoute::load()
    │      │      └─ filterByProperty('afterOrderEnabled', true)
    │      └─ isPaymentChangeable()
    │
    └─ renderStorefront()

AccountOrderController::updateOrder()
    │
    ├─ AbstractOrderRoute::load() // 注文取得
    │
    ├─ OrderService::isPaymentChangeableByTransactionState()
    │
    ├─ SetPaymentOrderRouteRequestEvent dispatch
    ├─ AbstractSetPaymentOrderRoute::setPayment()
    │
    ├─ HandlePaymentMethodRouteRequestEvent dispatch
    ├─ AbstractHandlePaymentMethodRoute::load()
    │
    └─ redirectToRoute('frontend.checkout.finish.page')
```

### データフロー図

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

Request (orderId)
         │
         ▼
 AccountOrderController::editOrder()
         │
         ├─► 注文取得・検証
         │         │
         │         ▼
         │    OrderEntity
         │
         ├─► コンテキスト調整（通貨・配送方法）
         │
         └─► AccountEditOrderPageLoader::load()
                    │
                    ├─► 支払い方法取得
                    │         │
                    │         ▼
                    │    PaymentMethodCollection
                    │
                    └─► AccountEditOrderPage ──────────────► index.html.twig
                                                                    │
                                                                    ▼
                                                              Response

Request (orderId, paymentMethodId)
         │
         ▼
 AccountOrderController::updateOrder()
         │
         ├─► SetPaymentOrderRoute::setPayment()
         │
         ├─► HandlePaymentMethodRoute::load()
         │         │
         │         ▼
         │    支払い処理実行
         │
         └─► Redirect to checkout.finish.page
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AccountOrderController.php | `src/Storefront/Controller/AccountOrderController.php` | コントローラー | リクエスト処理 |
| AccountEditOrderPageLoader.php | `src/Storefront/Page/Account/Order/AccountEditOrderPageLoader.php` | ページローダー | ページデータ組み立て |
| AccountEditOrderPage.php | `src/Storefront/Page/Account/Order/AccountEditOrderPage.php` | ページエンティティ | ページデータ型定義 |
| AbstractSetPaymentOrderRoute.php | `src/Core/Checkout/Order/SalesChannel/AbstractSetPaymentOrderRoute.php` | Store API | 支払い方法設定 |
| AbstractHandlePaymentMethodRoute.php | `src/Core/Checkout/Payment/SalesChannel/AbstractHandlePaymentMethodRoute.php` | Store API | 支払い処理実行 |
| OrderService.php | `src/Core/Checkout/Order/SalesChannel/OrderService.php` | サービス | 注文関連ロジック |
| index.html.twig | `src/Storefront/Resources/views/storefront/page/account/order/index.html.twig` | テンプレート | メイン画面 |
| confirm-payment.html.twig | `src/Storefront/Resources/views/storefront/page/account/order/confirm-payment.html.twig` | テンプレート | 支払い方法選択 |
| address.html.twig | `src/Storefront/Resources/views/storefront/page/account/order/address.html.twig` | テンプレート | 住所表示 |
| cancel-order-modal.html.twig | `src/Storefront/Resources/views/storefront/page/account/order/cancel-order-modal.html.twig` | テンプレート | キャンセルモーダル |
