# 通知設計書 40-Downloads Delivery

## 概要

本ドキュメントは、Shopwareにおけるダウンロード商品（デジタルプロダクト）の配信時に送信されるメール通知の設計仕様を定義する。

### 本通知の処理概要

本通知は、注文に含まれるダウンロード商品（デジタルファイル）のダウンロードリンクを顧客にメールで送信する際に使用される通知である。決済完了後や、管理者の承認後にダウンロードが有効化された際に送信される。

**業務上の目的・背景**：デジタルプロダクト（ソフトウェア、電子書籍、音楽、動画等）の販売において、購入後の迅速なダウンロードリンクの提供は顧客満足度に直結する。本通知により、顧客は購入したデジタル商品のダウンロードリンクを受け取り、すぐにコンテンツにアクセスできる。また、ダウンロードリンクの管理と追跡も可能となる。

**通知の送信タイミング**：決済が完了し、ダウンロードが有効化された際（`accessGranted = true`）にFlowビルダーで設定されたメール送信アクションがトリガーされ、本通知が送信される。具体的には決済状態が「paid」になった際などに関連付けられる。

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

**通知内容の概要**：顧客の敬称・氏名、注文番号、ダウンロード可能な商品一覧（商品番号、商品名、ダウンロードリンク）が含まれる。各商品に対して複数のダウンロードファイルがある場合は、それぞれのリンクが表示される。

**期待されるアクション**：顧客は通知を受け取り、メール内のダウンロードリンクをクリックして購入したデジタルファイルをダウンロードする。ダウンロードリンクはディープリンクコードで保護されており、第三者がアクセスすることはできない。

## 通知種別

メール通知

## 送信仕様

### 基本情報

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

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

1. デフォルトでは注文顧客のメールアドレス（`MailRecipientStruct`）が使用される
2. Flowビルダーの設定で受信者タイプを変更可能

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | 販売チャネル設定による |
| 送信元名称 | `{{ salesChannel.name }}` |
| 件名（英語） | Your downloads from {{ salesChannel.name }} are ready |
| 件名（ドイツ語） | Ihre Dateien von {{ salesChannel.name }} stehen bereit |
| 形式 | HTML/テキスト両対応 |

### 本文テンプレート

```html
<div style="font-family:arial; font-size:12px;">

    {% if order.orderCustomer.salutation %}{{ order.orderCustomer.salutation.translated.letterName ~ ' ' }}{% endif %}{{ order.orderCustomer.firstName }} {{ order.orderCustomer.lastName }},<br>
    <br>
    Attached to this email you will find the files to the order: {{ order.orderNumber }}
    <br>
    <br>

    <table border="0" style="font-family:Arial, Helvetica, sans-serif; font-size:12px;">
        <tr>
            <td bgcolor="#F7F7F2" style="border-bottom:1px solid #cccccc;"><strong>Prod. no.</strong></td>
            <td bgcolor="#F7F7F2" style="border-bottom:1px solid #cccccc;"><strong>Product</strong></td>
            <td bgcolor="#F7F7F2" style="border-bottom:1px solid #cccccc;"><strong>Downloads</strong></td>
        </tr>

        {% for lineItem in order.lineItems %}
            {% if lineItem.downloads is defined and lineItem.downloads|length %}
                {% block lineItem %}
                    <tr>
                        <td>{% if lineItem.payload.productNumber is defined %}{{ lineItem.payload.productNumber|u.wordwrap(80) }}{% endif %}</td>
                        <td>{{ lineItem.label|u.wordwrap(80) }}</td>
                        <td>
                            {% for download in lineItem.downloads %}
                                {% if download.accessGranted %}
                                    {% set downloadLink = rawUrl('frontend.account.order.single.download', {'orderId': order.id, 'downloadId': download.id, 'deepLinkCode': order.deepLinkCode}, salesChannel.domains|first.url) %}
                                    <a href="{{ downloadLink }}" target="_blank">
                                        {{ download.media.fileName }}.{{ download.media.fileExtension }}
                                    </a><br>
                                {% endif %}
                            {% endfor %}
                        </td>
                    </tr>
                {% endblock %}
            {% endif %}
        {% endfor %}
    </table>

    <br>
</div>
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | ダウンロードリンクで提供（添付ではない） |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| order | 注文エンティティ | order テーブル | Yes |
| order.id | 注文ID | order.id | Yes |
| order.orderNumber | 注文番号 | order.order_number | Yes |
| order.deepLinkCode | ディープリンクコード | order.deep_link_code | Yes |
| order.orderCustomer | 注文顧客情報 | order_customer テーブル | Yes |
| order.lineItems | 注文明細 | order_line_item テーブル | Yes |
| order.lineItems[].downloads | ダウンロード情報 | order_line_item_download テーブル | Yes |
| order.lineItems[].downloads[].accessGranted | ダウンロード許可フラグ | order_line_item_download.access_granted | Yes |
| order.lineItems[].downloads[].media | メディア情報 | media テーブル | Yes |
| salesChannel | 販売チャネル | sales_channel テーブル | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| Flow | 決済状態変更（paid）時 | ダウンロード商品を含む注文 | Flowビルダーで設定されたトリガー |
| Flow | ダウンロード有効化時 | accessGranted = true | 管理者による手動有効化時も含む |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| ダウンロード商品なし | 注文にダウンロード商品が含まれていない場合 |
| accessGranted = false | ダウンロードがまだ有効化されていない場合 |
| Flow未設定 | Flowビルダーでメール送信アクションが設定されていない場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[決済完了/ダウンロード有効化] --> B[Flowビルダーがイベントを検知]
    B --> C{SendMailActionが設定されている?}
    C -->|Yes| D[注文データ取得]
    C -->|No| E[処理終了]
    D --> F{ダウンロード商品あり?}
    F -->|Yes| G[メールテンプレート取得]
    F -->|No| E
    G --> H[テンプレート変数展開]
    H --> I[ダウンロードリンク生成]
    I --> J[AbstractMailService.send]
    J --> K{送信結果}
    K -->|成功| L[処理完了]
    K -->|失敗| M[エラーログ記録]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| order | 注文情報取得 | 主要な注文データ |
| order_line_item | 注文明細 | ダウンロード商品情報 |
| order_line_item_download | ダウンロード情報 | アクセス許可状態 |
| media | メディア情報 | ファイル名・拡張子 |
| sales_channel | 販売チャネル | ドメイン情報 |
| mail_template | メールテンプレート | テンプレート本文 |
| mail_template_type | テンプレートタイプ | downloads_delivery |

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

#### order_line_item_download

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| id | ダウンロードID | order_line_item_id = :lineItemId |
| access_granted | アクセス許可フラグ | 同上 |
| media_id | メディア参照 | 同上 |

#### media

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| file_name | ファイル名 | media.id = :mediaId |
| file_extension | ファイル拡張子 | 同上 |

### 更新テーブル一覧

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

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 送信失敗 | SMTPサーバー接続エラー等 | エラーログ記録、例外はキャッチされ処理継続 |
| テンプレートエラー | Twigテンプレートの変数エラー | エラーログ記録 |
| メディア不存在 | ダウンロードファイルが削除されている | リンクをスキップ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | メールサービス設定による |
| リトライ間隔 | メールサービス設定による |
| リトライ対象エラー | 一時的な送信エラー |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | メールサービス設定による |
| 1日あたり上限 | メールサービス設定による |

### 配信時間帯

特に制限なし。トリガーイベント発生時に即座に送信される。

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

- ダウンロードリンクにはディープリンクコードが含まれ、注文者以外のアクセスを防止
- ダウンロードリンクは `frontend.account.order.single.download` ルートで提供される
- accessGranted = true の場合のみダウンロードリンクがメールに含まれる
- ダウンロードファイル自体は添付されず、リンク経由でのアクセスとなる

## 備考

- 本テンプレートタイプの技術名は `downloads_delivery`
- MailTemplateTypesクラスで `MAILTYPE_DOWNLOADS_DELIVERY` として定義（行48）
- Migration1657173907DownloadMailTemplateで初期テンプレートが追加された
- Migration1659257396DownloadFlowでFlowが追加された
- Migration1669316067ChangeColumnTitleInDownloadsDeliveryMailTemplateでテンプレートが更新された
- Migration1701688920FixDownloadLinkMailでダウンロードリンクの修正が行われた

---

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

### 推奨読解順序

#### Step 1: テンプレートタイプを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | MailTemplateTypes.php | `src/Core/Content/MailTemplate/MailTemplateTypes.php` | MAILTYPE_DOWNLOADS_DELIVERY = 'downloads_delivery'（行48） |

#### Step 2: マイグレーションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Migration1657173907DownloadMailTemplate.php | `src/Core/Migration/V6_4/Migration1657173907DownloadMailTemplate.php` | テンプレート追加処理 |

**主要処理フロー**:
- **行113-174**: insertMailTemplateTypeData()でテンプレートタイプを登録
- **行176-241**: insertMailTemplateData()でテンプレートデータを登録

#### Step 3: メールテンプレートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | en-html.html.twig | `src/Core/Migration/Fixtures/mails/downloads_delivery/en-html.html.twig` | HTMLテンプレートの構造 |

**主要処理フロー**:
- **行16-35**: lineItemsループでダウンロード商品を表示
- **行24-29**: accessGranted = true の場合のみダウンロードリンクを生成

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

```
決済完了イベント
    │
    └─ FlowDispatcher（Flowビルダー）
           │
           └─ SendMailAction::handleFlow()
                  │
                  ├─ getMailTemplate()
                  │      └─ 'downloads_delivery' テンプレート取得
                  │
                  └─ AbstractMailService::send()
                         │
                         └─ Twigテンプレート展開
                                │
                                └─ ダウンロードリンク生成
                                       rawUrl('frontend.account.order.single.download', ...)
```

### データフロー図

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

order                 ───▶ SendMailAction              ───▶ メール送信
order.lineItems            │
order.lineItems            ▼
  [].downloads        ───▶ Twigテンプレート展開
                           │
                           ▼
                      {% for lineItem in order.lineItems %}
                           │
                           ▼
                      {% for download in lineItem.downloads %}
                           │
                           ▼
                      {% if download.accessGranted %}  ───▶ ダウンロードリンク
                           │
                           ▼
                      rawUrl('frontend.account.order.single.download', ...)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| MailTemplateTypes.php | `src/Core/Content/MailTemplate/MailTemplateTypes.php` | ソース | テンプレートタイプ定義 |
| Migration1657173907DownloadMailTemplate.php | `src/Core/Migration/V6_4/Migration1657173907DownloadMailTemplate.php` | マイグレーション | テンプレート追加 |
| Migration1659257396DownloadFlow.php | `src/Core/Migration/V6_4/Migration1659257396DownloadFlow.php` | マイグレーション | Flow追加 |
| Migration1669316067ChangeColumnTitleInDownloadsDeliveryMailTemplate.php | `src/Core/Migration/V6_4/Migration1669316067ChangeColumnTitleInDownloadsDeliveryMailTemplate.php` | マイグレーション | テンプレート更新 |
| Migration1701688920FixDownloadLinkMail.php | `src/Core/Migration/V6_6/Migration1701688920FixDownloadLinkMail.php` | マイグレーション | リンク修正 |
| en-html.html.twig | `src/Core/Migration/Fixtures/mails/downloads_delivery/en-html.html.twig` | テンプレート | 英語HTMLテンプレート |
| en-plain.html.twig | `src/Core/Migration/Fixtures/mails/downloads_delivery/en-plain.html.twig` | テンプレート | 英語テキストテンプレート |
| de-html.html.twig | `src/Core/Migration/Fixtures/mails/downloads_delivery/de-html.html.twig` | テンプレート | ドイツ語HTMLテンプレート |
| de-plain.html.twig | `src/Core/Migration/Fixtures/mails/downloads_delivery/de-plain.html.twig` | テンプレート | ドイツ語テキストテンプレート |
