# 通知設計書 28-Order Transaction State (Refunded Partially)

## 概要

本ドキュメントは、Shopwareの注文決済ステータスが「一部返金完了（Refunded Partially）」に変更された際に送信されるメール通知の設計書である。

### 本通知の処理概要

本通知は、顧客への一部返金処理が完了した際に、返金状況を通知するメール送信機能を提供する。

**業務上の目的・背景**：ECサイトにおいて、注文の一部商品のみの返品や、部分的な値引き対応など、注文金額の一部のみを返金するケースがある。このような場合に顧客へ一部返金完了を通知し、返金金額と残りの注文について認識してもらう。取引の透明性を確保し、顧客からの問い合わせを減らす効果がある。

**通知の送信タイミング**：注文決済（OrderTransaction）エンティティのステートマシンにおいて、決済ステータスが`refunded_partially`に遷移した時点でイベント`state_enter.order_transaction.state.refunded_partially`が発火し、Flowによってメール送信がトリガーされる。

**通知の受信者**：注文を行った顧客（OrderCustomer）のメールアドレス宛に送信される。顧客の氏名・敬称情報も取得し、パーソナライズされた宛名で送信する。

**通知内容の概要**：決済ステータスの変更通知として、注文番号、注文日時、新しい決済ステータス名（Refunded Partially/一部返金完了）、および注文詳細確認用のディープリンクURLが含まれる。

**期待されるアクション**：顧客は通知を受け取り、一部返金処理が完了したことを認識する。必要に応じて提供されたリンクから注文詳細を確認し、返金金額と残りの注文状況を把握する。

## 通知種別

メール通知

## 送信仕様

### 基本情報

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

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

`OrderStateMachineStateChangeEvent`クラスの`getMailStruct()`メソッドにより、注文に紐づく顧客（`order.orderCustomer`）のメールアドレスと氏名を取得して送信先とする。

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | SalesChannelの設定による |
| 送信元名称 | SalesChannelの設定による |
| 件名 | テンプレートで定義（デフォルト: 決済ステータス変更通知） |
| 形式 | HTML/テキスト両対応 |

### 本文テンプレート

```twig
{% if order.orderCustomer.salutation %}{{ order.orderCustomer.salutation.translated.letterName ~ ' ' }}{% endif %}{{ order.orderCustomer.firstName }} {{ order.orderCustomer.lastName }},

the status of your order at {{ salesChannel.translated.name }} (Number: {{ order.orderNumber }}) on {{ order.orderDateTime|format_datetime('medium', 'short', locale='en-GB') }} has changed.
The new status is as follows: {{ order.transactions.first.stateMachineState.translated.name }}.

You can check the current status of your order on our website under "My account" - "My orders" anytime: {{ rawUrl('frontend.account.order.single.page', { 'deepLinkCode': order.deepLinkCode }, salesChannel.domains|first.url) }}
However, in case you have purchased without a registration or a customer account, you do not have this option.

{% if a11yDocuments %}
For better accessibility we also provide an HTML version of the documents here:
{% for a11y in a11yDocuments %}
- {{ rawUrl('frontend.account.order.single.document.a11y', {...}, salesChannel.domains|first.url) }}
{% endfor %}
{% endif %}
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| - | - | - | 基本的に添付ファイルなし（Flowで設定可能） |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| order | 注文エンティティ | order テーブル | Yes |
| order.orderCustomer | 注文顧客情報 | order_customer テーブル | Yes |
| order.orderNumber | 注文番号 | order.order_number | Yes |
| order.orderDateTime | 注文日時 | order.order_date_time | Yes |
| order.transactions | 決済情報コレクション | order_transaction テーブル | Yes |
| order.transactions.first.stateMachineState | 決済ステータス | state_machine_state テーブル | Yes |
| order.deepLinkCode | ディープリンクコード | order.deep_link_code | Yes |
| salesChannel | 販売チャネル情報 | sales_channel テーブル | Yes |
| a11yDocuments | アクセシビリティドキュメント | コンテキストから | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ステートマシン遷移 | state_enter.order_transaction.state.refunded_partially | Flowで設定 | 決済ステータスがrefunded_partiallyに変更された時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| Flowが無効 | 対応するFlowアクションが無効化されている場合 |
| メールテンプレート未設定 | テンプレートIDが設定されていない場合 |
| 受信者メールアドレスなし | 顧客のメールアドレスが取得できない場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[決済ステータス変更トリガー] --> B[StateMachineRegistry::transition]
    B --> C[StateMachineStateChangeEvent発火]
    C --> D[OrderStateChangeEventListener::onOrderTransactionStateChange]
    D --> E[OrderStateMachineStateChangeEvent発火]
    E --> F[Flow処理開始]
    F --> G[SendMailAction::handleFlow]
    G --> H{メールテンプレート存在?}
    H -->|Yes| I[テンプレート展開]
    H -->|No| J[処理終了]
    I --> K[AbstractMailService::send]
    K --> L{送信結果}
    L -->|成功| M[送信完了]
    L -->|失敗| N[エラーログ記録]
    M --> O[終了]
    N --> O
    J --> O
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| order | 注文情報取得 | |
| order_customer | 顧客情報取得 | メール宛先 |
| order_transaction | 決済情報取得 | ステータス確認 |
| state_machine_state | ステータス名取得 | 多言語対応 |
| sales_channel | 販売チャネル情報 | 送信元情報 |
| mail_template | メールテンプレート | 本文・件名 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| state_machine_history | INSERT | ステータス遷移履歴 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 送信失敗 | SMTPエラー等 | ログ記録、リトライはFlow設定依存 |
| テンプレートエラー | Twig構文エラー | ログ記録、送信中断 |
| 宛先不正 | メールアドレス形式不正 | MailEventConfigurationException |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Flowの遅延アクション設定に依存 |
| リトライ間隔 | Flowの遅延アクション設定に依存 |
| リトライ対象エラー | 一時的な送信失敗 |

## 配信設定

### レート制限

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

### 配信時間帯

特に制限なし（イベント発生時に即時送信）

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

- 顧客のメールアドレス、氏名等の個人情報を扱うため、適切なアクセス制御が必要
- 返金額等の金銭に関わる情報が含まれる可能性があるため、メール送信先の正確性が重要
- ディープリンクコードにより、ログインなしで注文詳細にアクセス可能なため、URLの漏洩に注意

## 備考

- メールテンプレートタイプ: `order_transaction.state.refunded_partially`
- MailTemplateTypes定数: `MAILTYPE_STATE_ENTER_ORDER_TRANSACTION_STATE_REFUNDED_PARTIALLY`
- OrderTransactionStateHandlerのrefundPartially()メソッド（行173-184）でもトリガー可能
- 一部返品完了（order_delivery.state.returned_partially）と連動して発生することがある

---

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | OrderTransactionStates.php | `src/Core/Checkout/Order/Aggregate/OrderTransaction/OrderTransactionStates.php` | STATE_PARTIALLY_REFUNDED = 'refunded_partially'（行15） |
| 1-2 | MailTemplateTypes.php | `src/Core/Content/MailTemplate/MailTemplateTypes.php` | MAILTYPE_STATE_ENTER_ORDER_TRANSACTION_STATE_REFUNDED_PARTIALLY（行54） |
| 1-3 | OrderTransactionStateHandler.php | `src/Core/Checkout/Order/Aggregate/OrderTransaction/OrderTransactionStateHandler.php` | refundPartially()メソッド（行173-184） |

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

```
管理画面 / API / OrderTransactionStateHandler::refundPartially()
    │
    └─ StateMachineRegistry::transition()
           │
           └─ OrderStateChangeEventListener::onOrderTransactionStateChange()
                  └─ Flow Dispatcher
                         └─ SendMailAction::handleFlow()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| OrderTransactionStates.php | `src/Core/Checkout/Order/Aggregate/OrderTransaction/OrderTransactionStates.php` | ソース | 決済ステータス定数 |
| OrderTransactionStateHandler.php | `src/Core/Checkout/Order/Aggregate/OrderTransaction/OrderTransactionStateHandler.php` | ソース | 決済ステータス遷移ハンドラー |
| en-html.html.twig | `src/Core/Migration/Fixtures/mails/order_transaction.state.refunded_partially/en-html.html.twig` | テンプレート | 英語HTMLテンプレート |
