# 通知設計書 15-Order Confirmation

## 概要

本ドキュメントは、Shopwareにおける注文確認通知（Order Confirmation）の設計仕様を記載したものです。顧客が注文を完了した際に送信される注文確認メールについて定義します。

### 本通知の処理概要

この通知は、ECサイトにおける最も重要なトランザクションメールの一つです。顧客が注文を確定した直後に、注文内容の詳細を含む確認メールを送信します。

**業務上の目的・背景**：注文確認メールは、顧客に対して注文が正常に処理されたことを保証し、注文内容の確認手段を提供します。法的にも、電子商取引における契約成立の証拠として重要な役割を果たします。顧客満足度の向上と、問い合わせの削減にも貢献します。

**通知の送信タイミング**：`checkout.order.placed`イベント、すなわち注文が確定した直後にメール送信がトリガーされます。カート内の商品が注文として確定され、在庫が引き当てられた後に発火します。

**通知の受信者**：注文を行った顧客のメールアドレス（`order.orderCustomer.email`）。

**通知内容の概要**：注文番号、注文日時、注文明細（商品名、数量、価格）、配送先住所、請求先住所、支払い方法、配送方法、合計金額（税込み・税別）が含まれます。

**期待されるアクション**：顧客は注文内容を確認し、問題があれば速やかにショップに連絡します。また、注文状況確認用のリンクからマイアカウントにアクセスできます。

## 通知種別

メール通知

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（Flow経由） |
| 優先度 | 高 |
| リトライ | Flowの設定に依存 |

### 送信先決定ロジック

イベント発生時に`MailRecipientStruct`が構築されます。

```php
// CheckoutOrderPlacedEvent.php 行69-78
public function getMailStruct(): MailRecipientStruct
{
    if (!$this->mailRecipientStruct instanceof MailRecipientStruct) {
        $this->mailRecipientStruct = new MailRecipientStruct([
            $this->order->getOrderCustomer()?->getEmail() => $this->order->getOrderCustomer()?->getFirstName() . ' ' . $this->order->getOrderCustomer()?->getLastName(),
        ]);
    }

    return $this->mailRecipientStruct;
}
```

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | ショップ設定に依存 |
| 送信元名称 | ショップ設定に依存 |
| 件名 | `Order Confirmation`（EN）/ `Bestellbestätigung`（DE） |
| 形式 | HTML/テキスト |

### 本文テンプレート

**英語版（HTML）抜粋**:
```html
<div style="font-family:arial; font-size:12px;">
    {% set currencyIsoCode = order.currency.isoCode %}
    {{order.orderCustomer.salutation.letterName }} {{order.orderCustomer.firstName}} {{order.orderCustomer.lastName}},<br>
    <br>
    Thank you for your order at {{ salesChannel.name }} (Number: {{order.orderNumber}}) on {{ order.orderDateTime|date }}.<br>
    <br>
    <strong>Information on your order:</strong><br>
    <br>
    <table width="80%" border="0">
        <tr>
            <td><strong>Pos.</strong></td>
            <td><strong>Description</strong></td>
            <td><strong>Quantities</strong></td>
            <td><strong>Price</strong></td>
            <td><strong>Total</strong></td>
        </tr>
        {% for lineItem in order.lineItems %}
        <tr>
            <td>{{ loop.index }}</td>
            <td>{{ lineItem.label }}</td>
            <td>{{ lineItem.quantity }}</td>
            <td>{{ lineItem.unitPrice|currency(currencyIsoCode) }}</td>
            <td>{{ lineItem.totalPrice|currency(currencyIsoCode) }}</td>
        </tr>
        {% endfor %}
    </table>
    ...
</div>
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| 請求書（オプション） | PDF | Flow設定で添付を有効にした場合 | A11y対応ドキュメント |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| `order` | 注文エンティティ | OrderEntity | Yes |
| `order.orderNumber` | 注文番号 | order.order_number | Yes |
| `order.orderDateTime` | 注文日時 | order.order_date_time | Yes |
| `order.orderCustomer` | 注文顧客情報 | order_customer | Yes |
| `order.lineItems` | 注文明細 | order_line_item | Yes |
| `order.deliveries` | 配送情報 | order_delivery | Yes |
| `order.transactions` | 決済情報 | order_transaction | Yes |
| `order.amountTotal` | 合計金額（税込） | order.amount_total | Yes |
| `order.amountNet` | 合計金額（税別） | order.amount_net | Yes |
| `order.currency` | 通貨情報 | currency | Yes |
| `order.addresses` | 住所情報 | order_address | Yes |
| `order.deepLinkCode` | 注文詳細へのディープリンクコード | order.deep_link_code | Yes |
| `salesChannel` | 販売チャネル | SalesChannelContext | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作/API | `checkout.order.placed` | 注文確定時 | カート→注文への変換完了時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| Flowが設定されていない | Flowビルダーでメール送信アクションが設定されていない場合 |
| メールテンプレートが存在しない | 対応するメールテンプレートが削除されている場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[顧客が注文を確定] --> B[カート→注文変換]
    B --> C[OrderEntity作成]
    C --> D[CheckoutOrderPlacedEvent発火]
    D --> E[Flowエンジンがイベントを検知]
    E --> F[SendMailAction実行]
    F --> G[注文データ取得]
    G --> H[メールテンプレート展開]
    H --> I{添付ファイルあり?}
    I -->|あり| J[ドキュメント生成・添付]
    I -->|なし| K[メール送信]
    J --> K
    K --> L[送信完了]
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| `order` | 注文基本情報 | 主要データソース |
| order_customer | 注文顧客情報 | メール宛先 |
| order_line_item | 注文明細 | 商品情報 |
| order_delivery | 配送情報 | 配送先、配送方法 |
| order_transaction | 決済情報 | 支払い方法 |
| order_address | 住所情報 | 請求先・配送先 |
| currency | 通貨情報 | 金額表示用 |
| payment_method | 支払い方法 | 表示名 |
| shipping_method | 配送方法 | 表示名 |
| country | 国情報 | 住所表示用 |
| salutation | 敬称 | 顧客名表示用 |

### テーブル別参照項目詳細

#### order

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| id | 注文識別 | イベントから取得 |
| order_number | 注文番号表示 | テンプレート変数 |
| order_date_time | 注文日時表示 | テンプレート変数 |
| amount_total | 税込合計 | テンプレート変数 |
| amount_net | 税別合計 | テンプレート変数 |
| currency_id | 通貨 | JOIN currency |
| billing_address_id | 請求先住所 | JOIN order_address |
| deep_link_code | マイアカウントリンク | テンプレート変数 |
| sales_channel_id | 販売チャネル | コンテキスト |
| language_id | 言語 | テンプレート言語 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | 参照のみ |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 注文顧客なし | orderCustomerがnull | CartException::orderCustomerDeleted |
| メール送信失敗 | SMTPエラー等 | ログ記録、リトライ |
| テンプレートエラー | 変数の未定義等 | ログ記録、フォールバック |
| ドキュメント生成失敗 | PDF生成エラー | ログ記録、メールは添付なしで送信 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Flowの設定に依存 |
| リトライ間隔 | Flowの設定に依存 |
| リトライ対象エラー | 一時的なネットワークエラー |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | システム設定に依存 |
| 1日あたり上限 | システム設定に依存 |

### 配信時間帯

制限なし（リアルタイム送信）

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

- 注文情報には個人情報（住所、名前）が含まれるため、メール送信時の暗号化（TLS）を推奨
- deepLinkCodeは推測困難なランダム文字列を使用
- 注文詳細ページへのアクセスにはdeepLinkCodeが必要

## 備考

- このイベントは`A11yRenderedDocumentAware`インターフェースを実装しており、アクセシビリティ対応ドキュメントの添付が可能
- `CustomerGroupAware`インターフェースにより、顧客グループ別のテンプレート切り替えが可能
- 注文確認メールは最も重要なトランザクションメールであり、送信失敗時は特に注意が必要

---

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

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

### 推奨読解順序

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

まず、イベントで扱われるデータ構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | CheckoutOrderPlacedEvent.php | `src/Core/Checkout/Cart/Event/CheckoutOrderPlacedEvent.php` | イベントクラス、実装インターフェース |
| 1-2 | OrderEntity.php | `src/Core/Checkout/Order/OrderEntity.php` | 注文エンティティの構造 |
| 1-3 | OrderDefinition.php | `src/Core/Checkout/Order/OrderDefinition.php` | 注文のアソシエーション定義 |

**読解のコツ**: `A11yRenderedDocumentAware`インターフェースにより、ドキュメント添付機能が利用可能である点に注目。

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

メールテンプレートの内容を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | MailTemplateContent.php | `src/Core/Migration/Fixtures/MailTemplateContent.php` | OrderConfirmationテンプレート（行4-301） |
| 2-2 | MailTemplateTypes.php | `src/Core/Content/MailTemplate/MailTemplateTypes.php` | テンプレートタイプ定数（行24） |

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

```
チェックアウト完了
    │
    ▼
OrderPersister / CartOrderRoute
    │
    ├─ OrderEntity作成
    │
    └─ eventDispatcher->dispatch(CheckoutOrderPlacedEvent)
           │
           └─ FlowExecutor (Subscriber)
                  │
                  └─ SendMailAction::handleFlow()
                         │
                         ├─ getMailTemplate()
                         │
                         ├─ attachmentsConfig処理
                         │      └─ [A11yドキュメント生成]
                         │
                         └─ emailService->send()
```

### データフロー図

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

カート確定               OrderPersister
(Cart) ──────────────▶ Order作成
                              │
                              ▼
                       OrderEntity
                       (全アソシエーション含む)
                              │
                              ▼
CheckoutOrderPlaced    イベント発火
Event ◀───────────────────────┘
      │
      ▼
Flow Engine           SendMailAction
      │                     │
      ▼                     ▼
MailTemplate          テンプレート展開
(order変数)                 │
      │                     ▼
      └──────────────▶ メール送信
                              │
                              ▼
                       顧客のメールボックス
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CheckoutOrderPlacedEvent.php | `src/Core/Checkout/Cart/Event/CheckoutOrderPlacedEvent.php` | ソース | イベントクラス定義 |
| OrderEntity.php | `src/Core/Checkout/Order/OrderEntity.php` | ソース | 注文エンティティ |
| SendMailAction.php | `src/Core/Content/Flow/Dispatching/Action/SendMailAction.php` | ソース | メール送信アクション |
| MailTemplateTypes.php | `src/Core/Content/MailTemplate/MailTemplateTypes.php` | ソース | テンプレートタイプ定数 |
| MailTemplateContent.php | `src/Core/Migration/Fixtures/MailTemplateContent.php` | フィクスチャ | デフォルトテンプレート内容 |
