# 通知設計書 1-注文作成通知

## 概要

本ドキュメントは、Medusa ECプラットフォームにおける注文作成時の顧客向けメール通知機能について、その仕様と実装詳細を記述する。

### 本通知の処理概要

本通知は、顧客がECサイトで注文を完了した際に、注文確認メールを自動送信する機能を提供する。注文作成イベント（order.created）が発生すると、イベントサブスクライバーがこれを検知し、設定に基づいて顧客のメールアドレス宛に通知を送信する。

**業務上の目的・背景**：ECサイトにおいて、顧客が注文を完了した際に注文確認メールを送信することは、顧客体験において極めて重要である。顧客は注文が正常に受け付けられたことを確認でき、注文内容の記録としても機能する。また、顧客からの問い合わせ削減にも寄与する。

**通知の送信タイミング**：注文が作成された時点（order.created イベント発行時）に送信される。具体的には、チェックアウト完了後、システムが注文レコードを生成し、order.created イベントを発行したタイミングでサブスクライバーが起動する。

**通知の受信者**：注文を行った顧客本人。受信先のメールアドレスは注文データ（order.email）から動的に取得される。顧客が注文時に入力したメールアドレスに送信される。

**通知内容の概要**：注文ID、注文明細、配送先情報、支払い情報など、注文に関する主要情報がテンプレートに基づいて展開される。具体的なテンプレート内容は外部プロバイダー（SendGrid等）で管理される。

**期待されるアクション**：顧客は受信したメールで注文内容を確認し、誤りがあれば速やかにカスタマーサポートに連絡することが期待される。また、注文追跡や今後の参照のために保存しておくことが推奨される。

## 通知種別

メール（email）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（イベントドリブン） |
| 優先度 | 中 |
| リトライ | 無（エラーはログ出力のみ） |

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

注文オブジェクト（order）のemailフィールドから送信先を取得する。configurable-notifications.ts内でpickValueFromObject関数を使用し、"order.email"パスから値を抽出する。

```typescript
to: pickValueFromObject("order.email", payload)
```

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | プロバイダー設定による |
| 送信元名称 | プロバイダー設定による |
| 件名 | テンプレート（order-created-template）による |
| 形式 | テンプレート（order-created-template）による |

### 本文テンプレート

テンプレートID: `order-created-template`

本文の詳細は外部通知プロバイダー（SendGrid、Mailchimp等）で管理される。Medusa側からはテンプレートIDとデータのみを渡す。

```
テンプレート変数:
- order_id: 注文ID

※実際の本文は外部プロバイダーで設定
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | 標準では添付ファイルなし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| order_id | 注文ID | order.id | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| イベント | order.created | handlerConfig配列内にマッチするイベント設定が存在すること | 注文作成時にイベントバスから発行されるイベント |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| メールアドレス未設定 | order.emailが空または取得できない場合 |
| プロバイダー未設定 | emailチャネルに対応するNotification Providerが設定されていない場合 |
| プロバイダー無効 | 対応するNotification Providerがis_enabled=falseの場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[order.created イベント発生] --> B[configurableNotifications サブスクライバー起動]
    B --> C[configAsMap からハンドラー設定取得]
    C --> D{ハンドラー設定存在?}
    D -->|No| E[処理終了]
    D -->|Yes| F[通知データ構築]
    F --> G[pickValueFromObject で宛先・リソースID取得]
    G --> H[notificationService.createNotifications 呼び出し]
    H --> I[NotificationModuleService.createNotifications_]
    I --> J[プロバイダー取得]
    J --> K{プロバイダー存在 & 有効?}
    K -->|No| L[ステータス: FAILURE, エラーログ]
    K -->|Yes| M[プロバイダー経由で送信]
    M --> N{送信成功?}
    N -->|Yes| O[ステータス: SUCCESS, 通知レコード更新]
    N -->|No| P[ステータス: FAILURE, エラースロー]
    O --> Q[処理完了]
    L --> Q
    P --> Q
    E --> Q
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| order | 注文情報取得 | イベントペイロードから取得 |
| notification_provider | プロバイダー情報取得 | チャネルに対応するプロバイダーを検索 |
| notification | 重複チェック | idempotency_keyによる既存通知確認 |

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

#### order（イベントペイロード経由）

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| id | 注文ID、resource_id | イベントペイロードから |
| email | 送信先メールアドレス | イベントペイロードから |

#### notification_provider

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| id | プロバイダーID | channels配列に"email"を含む |
| is_enabled | 有効フラグ | - |
| channels | 対応チャネル | - |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| notification | INSERT/UPDATE | 通知レコードの作成・ステータス更新 |

#### 送信ログテーブル（notification）

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | id | noti_xxx形式で自動生成 | generateEntityId使用 |
| INSERT | to | order.email | 送信先 |
| INSERT | channel | "email" | 固定値 |
| INSERT | template | "order-created-template" | テンプレートID |
| INSERT | data | {order_id: order.id} | テンプレート変数 |
| INSERT | trigger_type | "order.created" | イベント名 |
| INSERT | resource_id | order.id | 注文ID |
| INSERT | provider_id | プロバイダーID | 使用プロバイダー |
| INSERT | status | "pending" | 初期ステータス |
| UPDATE | status | "success" / "failure" | 送信結果 |
| UPDATE | external_id | プロバイダーからの応答ID | 成功時のみ |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 送信失敗 | プロバイダーAPI呼び出しエラー | エラーログ出力、ステータスをFAILUREに更新 |
| プロバイダー未設定 | emailチャネルのプロバイダーが見つからない | MedusaError.Types.NOT_FOUND、ステータスをFAILUREに更新 |
| プロバイダー無効 | プロバイダーのis_enabled=false | MedusaError.Types.NOT_FOUND、ステータスをFAILUREに更新 |
| 宛先不正 | order.emailが取得できない | 通知は作成されるが宛先が空になる可能性 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

※ configurable-notifications.tsではエラーをcatchしてログ出力のみ行い、他のハンドラーへの影響を防いでいる

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | プロバイダー依存 |
| 1日あたり上限 | プロバイダー依存 |

### 配信時間帯

制限なし（注文作成時に即時送信）

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

- 顧客のメールアドレスは個人情報として適切に扱う必要がある
- 通知レコードにはTTL（Time To Live）を設定し、GDPR対応として30日以内に削除することが推奨される（コード内コメントより）
- idempotency_keyによる重複送信防止機能あり
- テンプレートデータには必要最小限の情報のみを渡す設計

## 備考

- 現在の実装ではhandlerConfig配列はハードコードされているが、将来的にはmedusa-config.jsから動的にロードする計画がある（TODOコメント）
- テンプレート構文は現在シンプルだが、フィールド結合などより強力な機能を追加する予定がある（TODOコメント）
- promiseAllによる並列処理で複数ハンドラーを効率的に処理
- 各ハンドラーのエラーは個別にキャッチされ、1つのエラーが他のハンドラーに影響しない設計

---

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

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

### 推奨読解順序

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

まず、通知処理で使用されるデータ構造とインターフェースを理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | common.ts | `packages/core/types/src/notification/common.ts` | NotificationDTO、NotificationProviderDTOの構造を理解 |
| 1-2 | notification.ts | `packages/modules/notification/src/models/notification.ts` | DBモデル定義、各フィールドの用途をコメントで確認 |
| 1-3 | service.ts | `packages/core/types/src/notification/service.ts` | INotificationModuleServiceインターフェースの契約を確認 |

**読解のコツ**: TypeScriptの型定義を追うことで、データの流れと各フィールドの用途が明確になる。

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

処理の起点となるサブスクライバーを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | configurable-notifications.ts | `packages/medusa/src/subscribers/configurable-notifications.ts` | イベントサブスクライバーの実装全体 |

**主要処理フロー**:
1. **行21-32**: handlerConfig配列でイベントとテンプレートの対応を定義
2. **行34-44**: configAsMapでイベント名をキーにしたマップを構築
3. **行46-83**: configurableNotifications関数でイベント処理
4. **行55**: イベント名からハンドラー設定を取得
5. **行58-82**: promiseAllで全ハンドラーを並列実行
6. **行60-70**: 通知データ構築（pickValueFromObjectでペイロードから値を抽出）
7. **行74**: notificationService.createNotifications呼び出し
8. **行85-90**: SubscriberConfigでイベント購読設定

#### Step 3: 通知モジュールサービスを理解する

通知の作成・送信ロジックを理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | notification-module-service.ts | `packages/modules/notification/src/services/notification-module-service.ts` | 通知作成と送信の中核ロジック |

**主要処理フロー**:
- **行61-94**: createNotifications パブリックメソッド（デコレーター適用）
- **行97-234**: createNotifications_ 内部実装
- **行107-109**: idempotency_keyによる重複チェック準備
- **行112-178**: トランザクション内での通知レコード作成
- **行139-143**: プロバイダー取得
- **行182-217**: プロバイダー経由での送信実行
- **行198-207**: 送信成功/失敗時のステータス更新

#### Step 4: 通知送信ステップを理解する

ワークフローで使用される送信ステップの理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | send-notifications.ts | `packages/core/core-flows/src/notification/steps/send-notifications.ts` | ワークフロー用の送信ステップ定義 |

**主要処理フロー**:
- **行12-75**: SendNotificationsStepInput型定義（通知データの構造）
- **行81-94**: sendNotificationsStep実装

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

```
[order.created イベント発行]
    │
    └─ configurableNotifications (subscriber)
           │   行46-83
           │
           ├─ pickValueFromObject (utils)
           │      行63-67: ペイロードから値を抽出
           │
           └─ notificationService.createNotifications
                  │   行74
                  │
                  └─ NotificationModuleService.createNotifications
                         │   行61-94
                         │
                         ├─ createNotifications_ (内部メソッド)
                         │      │   行97-234
                         │      │
                         │      ├─ notificationService_.list (重複チェック)
                         │      │      行118-124
                         │      │
                         │      ├─ notificationProviderService_.getProviderForChannels
                         │      │      行141-143
                         │      │
                         │      ├─ notificationService_.create
                         │      │      行170-172
                         │      │
                         │      └─ notificationProviderService_.send
                         │             行198-207
                         │
                         └─ baseRepository_.serialize (レスポンス整形)
                                行89-91
```

### データフロー図

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

order.created         ───▶  configurable-notifications    ───▶  notificationService
イベントペイロード            サブスクライバー                    .createNotifications
  │                              │                                    │
  ├─ order.id                    │                                    │
  └─ order.email                 │                                    ▼
                                 │                           NotificationModuleService
                                 │                                    │
                                 │                                    ├─ DBに通知レコード作成
                                 │                                    │
                                 │                                    ├─ プロバイダー取得
                                 │                                    │
                                 │                                    └─ プロバイダー経由送信
                                 │                                           │
                                 │                                           ▼
                                 │                                    [外部プロバイダー]
                                 │                                    (SendGrid等)
                                 │                                           │
                                 ▼                                           ▼
                          [ログ出力]                              [顧客メールボックス]
                          (エラー時)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| configurable-notifications.ts | `packages/medusa/src/subscribers/configurable-notifications.ts` | ソース | イベントサブスクライバー、通知トリガー処理 |
| notification-module-service.ts | `packages/modules/notification/src/services/notification-module-service.ts` | ソース | 通知モジュールのメインサービス |
| notification.ts | `packages/modules/notification/src/models/notification.ts` | モデル | 通知エンティティ定義 |
| notification-provider.ts | `packages/modules/notification/src/models/notification-provider.ts` | モデル | 通知プロバイダーエンティティ定義 |
| common.ts | `packages/core/types/src/notification/common.ts` | 型定義 | 通知関連DTO定義 |
| service.ts | `packages/core/types/src/notification/service.ts` | 型定義 | INotificationModuleServiceインターフェース |
| send-notifications.ts | `packages/core/core-flows/src/notification/steps/send-notifications.ts` | ソース | ワークフロー用送信ステップ |
