# 通知設計書 6-注文エクスポート成功通知

## 概要

本ドキュメントは、Medusa ECプラットフォームにおける注文エクスポート完了時の管理者向けフィード通知機能について、その仕様と実装詳細を記述する。

### 本通知の処理概要

本通知は、管理者が注文データをCSVファイルにエクスポートする際、エクスポート処理が正常に完了したことを管理画面のフィード（通知一覧）に表示する機能を提供する。exportOrdersWorkflowが正常終了した際にsendNotificationsStepが実行され、ダウンロードリンク付きの成功通知を管理者に送信する。

**業務上の目的・背景**：注文エクスポートはバックグラウンドで非同期実行されるため、管理者は処理の完了を即座に確認できない。この通知により、管理者は注文エクスポートが正常に完了したことを知り、すぐにダウンロードリンクからCSVファイルを取得できる。売上分析、会計処理、他システム連携などの業務において、大量の注文データを効率的にエクスポートすることを支援する。

**通知の送信タイミング**：注文エクスポートワークフロー（exportOrdersWorkflow）がexportOrdersStep、useRemoteQueryStepを含むすべてのステップを正常に完了し、ファイルのアップロードとURL取得が完了した後、sendNotificationsStepが実行される時点で送信される。

**通知の受信者**：管理者全般。現在の実装では特定の受信者を指定せず（to: ""）、管理画面のフィードに表示される形式となっている。将来的には特定ユーザーへのプッシュ通知も検討されている（コードコメントより）。

**通知内容の概要**：エクスポート成功メッセージとともに、ダウンロード用のファイル情報（ファイル名、URL、MIMEタイプ）が含まれる。管理者は通知から直接CSVファイルをダウンロードできる。

**期待されるアクション**：管理者は通知を確認し、ダウンロードリンクからCSVファイルを取得する。必要に応じて、ファイルの内容を確認し、会計システムへの取り込みや売上分析に使用する。

## 通知種別

管理画面フィード（feed）/ アプリ内通知

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（ワークフロー内ステップ） |
| 優先度 | 中 |
| リトライ | 無（ワークフロー補償処理なし） |

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

現在の実装では、送信先（to）は空文字列に設定されており、特定の受信者を指定しない。管理画面のフィード機能により、全管理者が閲覧可能な形式で表示される。

```typescript
to: ""  // 特定受信者なし
```

## 通知テンプレート

### フィード通知の場合

| 項目 | 内容 |
|-----|------|
| チャネル | feed |
| テンプレートID | admin-ui |
| タイトル | Order export |
| 説明 | Order export completed successfully! |

### 本文テンプレート

```
タイトル: Order export
説明: Order export completed successfully!
ファイル情報:
  - filename: {タイムスタンプ}-order-exports.csv
  - url: {ファイルダウンロードURL}
  - mimeType: text/csv

例:
タイトル: Order export
説明: Order export completed successfully!
ファイル:
  - filename: 1708800000000-order-exports.csv
  - url: https://storage.example.com/exports/...
  - mimeType: text/csv
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| {タイムスタンプ}-order-exports.csv | CSV | 常時 | 注文エクスポートデータ（ダウンロードリンクとして提供） |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| title | 通知タイトル | 固定値 "Order export" | Yes |
| description | 通知説明文 | 固定値 "Order export completed successfully!" | Yes |
| file.filename | ファイル名 | exportOrdersStep出力 | Yes |
| file.url | ダウンロードURL | useRemoteQueryStep（fileエンティティ） | Yes |
| file.mimeType | MIMEタイプ | 固定値 "text/csv" | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ワークフロー | exportOrdersWorkflow正常完了 | exportOrdersStep、useRemoteQueryStep成功後 | 注文エクスポート処理成功時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| ワークフロー失敗 | 途中のステップでエラーが発生した場合、成功通知は送信されない |
| feedプロバイダー未設定 | feedチャネルに対応するNotification Providerが未設定の場合 |
| ファイルURL取得失敗 | useRemoteQueryStepでファイル情報が取得できない場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[注文エクスポートAPI呼び出し] --> B[exportOrdersWorkflow開始]
    B --> C[exportOrdersStep: CSV生成・アップロード]
    C --> D{エクスポート成功?}
    D -->|失敗| E[notifyOnFailureStep補償実行]
    D -->|成功| F[notifyOnFailureStep登録]
    F --> G[useRemoteQueryStep: ファイル情報取得]
    G --> H[transform: 成功通知データ構築]
    H --> I[sendNotificationsStep実行]
    I --> J[notificationService.createNotifications]
    J --> K[フィードにダウンロードリンク付き通知表示]
    K --> L[ワークフロー完了]
    E --> M[失敗通知送信]
    M --> N[終了]
    L --> N
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| order | 注文データ取得 | エクスポート対象注文の取得 |
| customer | 顧客情報取得 | 注文に紐づく顧客情報 |
| shipping_address | 配送先情報取得 | 注文に紐づく配送先 |
| payment_collections | 決済情報取得 | 支払いステータス算出用 |
| fulfillments | フルフィルメント情報取得 | 配送ステータス算出用 |
| file | ファイル情報取得 | アップロードされたCSVファイルのURL取得 |
| notification_provider | プロバイダー情報取得 | feedチャネルに対応するプロバイダーを検索 |

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

#### order

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| id | 注文ID | フィルター条件に基づく、status != 'draft' |
| display_id | 表示用注文ID | エクスポートデータ |
| status | 注文ステータス | エクスポートデータ |
| created_at | 作成日時 | エクスポートデータ |
| subtotal, shipping_total等 | 金額情報 | エクスポートデータ |

#### file

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| id | ファイルID | exportOrdersStep出力のfileKey |
| url | ダウンロードURL | 通知に含めるリンク |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| file | INSERT | CSVファイルのアップロード |
| notification | INSERT | 通知レコードの作成 |

#### ファイルテーブル（file）

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | id | fileKey | ファイルモジュールが生成 |
| INSERT | filename | {timestamp}-order-exports.csv | タイムスタンプ付きファイル名 |
| INSERT | mime_type | text/csv | CSVファイル |

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

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | id | noti_xxx形式で自動生成 | - |
| INSERT | to | "" | 空文字列（全体通知） |
| INSERT | channel | "feed" | 固定値 |
| INSERT | template | "admin-ui" | テンプレートID |
| INSERT | data | {title, description, file} | 通知内容（ダウンロードリンク含む） |
| INSERT | status | "success" | 送信結果 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| エクスポート失敗 | exportOrdersStepでエラー | notifyOnFailureStepの補償処理で失敗通知 |
| ファイルURL取得失敗 | useRemoteQueryStepでファイル情報なし | ワークフロー失敗、補償処理実行 |
| プロバイダー未設定 | feedチャネルのプロバイダーなし | MedusaError発生、通知作成失敗 |
| プロバイダー無効 | プロバイダーのis_enabled=false | MedusaError発生、通知作成失敗 |

### リトライ仕様

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

※ 失敗時はexportOrdersStepの補償処理でファイルが削除される

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし（feed通知のため） |
| 1日あたり上限 | なし |

### 配信時間帯

制限なし（エクスポート完了時に即時通知）

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

- 通知は管理者向けであり、顧客の個人情報は直接含まれない
- ダウンロードURLは認証が必要な管理画面内でのみアクセス可能
- ファイルアクセス権限はファイルモジュールの設定に依存
- エクスポートされるデータには顧客の個人情報（メールアドレス、住所等）が含まれるため、ダウンロードしたファイルの取り扱いに注意が必要

## 備考

- エクスポートはバックグラウンド実行（backgroundExecution: true）されるため、APIレスポンスは即座に返却される
- ファイル名にはタイムスタンプが含まれ、一意性が保証される
- デフォルトのバッチサイズは50件で、ページネーション処理で大量データにも対応
- 失敗時の補償処理でアップロードされたファイルは削除される
- ファイルURLはuseRemoteQueryStepで取得され、fileエンティティから動的に解決される
- draft状態の注文は除外される（status != 'draft'）
- エクスポートデータには支払いステータス、配送ステータスの集計値が含まれる

---

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

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

### 推奨読解順序

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

まず、エクスポート入力とファイル出力の構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | export-orders.ts (workflow) | `packages/core/core-flows/src/order/workflows/export-orders.ts` 行14-25 | ExportOrdersDTOの構造を確認 |
| 1-2 | export-orders.ts (steps) | `packages/core/core-flows/src/order/steps/export-orders.ts` | ステップの入出力を確認 |

**読解のコツ**: ファイルID（fileKey）がどのように生成され、後続でどう使用されるかを追跡する。

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

ワークフロー定義が処理の起点。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | export-orders.ts (workflow) | `packages/core/core-flows/src/order/workflows/export-orders.ts` | ワークフロー全体の流れを把握 |

**主要処理フロー (export-orders.ts)**:
1. **行89-142**: createWorkflowでワークフロー定義
2. **行92-95**: exportOrdersStep実行（async: true, backgroundExecution: true）
3. **行97-110**: transform - 失敗通知データ構築
4. **行111**: notifyOnFailureStep - 失敗時通知登録
5. **行113-118**: useRemoteQueryStep - ファイル情報取得
6. **行120-138**: transform - 成功通知データ構築（ダウンロードリンク含む）
7. **行140**: sendNotificationsStep - 成功通知送信

#### Step 3: エクスポートステップを理解する

CSVファイル生成の詳細を理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | export-orders.ts (steps) | `packages/core/core-flows/src/order/steps/export-orders.ts` | CSV生成とアップロード処理 |

**主要処理フロー**:
- **行67-178**: exportOrdersStep定義
- **行73**: ファイル名生成（{Date.now()}-order-exports.csv）
- **行74-77**: ファイルアップロードストリーム取得
- **行103-155**: ページネーション処理でデータ取得・CSV変換
- **行127-128**: 支払いステータス、配送ステータスの算出
- **行165-168**: StepResponse(id: fileKey, filename)
- **行170-177**: 補償処理（ファイル削除）

#### Step 4: データ正規化を理解する

注文データの正規化処理を理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | export-orders.ts (steps) | `packages/core/core-flows/src/order/steps/export-orders.ts` 行32-65 | normalizeOrderForExport関数 |

**主要処理フロー**:
- **行32-65**: normalizeOrderForExport関数
- **行39-63**: エクスポート用にフィールド名を変換（Order_ID, Display_ID等）

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

```
[注文エクスポートAPI]
    │
    └─ exportOrdersWorkflow
           │   行89-142
           │
           ├─ exportOrdersStep
           │      │   行92-95 (async: true, backgroundExecution: true)
           │      │
           │      ├─ query.graph (注文データ取得)
           │      │      行104-117
           │      │
           │      ├─ getLastPaymentStatus / getLastFulfillmentStatus
           │      │      行127-128
           │      │
           │      ├─ normalizeOrderForExport (データ正規化)
           │      │      行134
           │      │
           │      ├─ json2csv (CSV変換)
           │      │      行137-145
           │      │
           │      ├─ writeStream.write (ファイル書き込み)
           │      │      行147-150
           │      │
           │      └─ StepResponse({id: fileKey, filename})
           │             行165-168
           │
           ├─ transform (失敗通知データ)
           │      行97-110
           │
           ├─ notifyOnFailureStep
           │      行111
           │
           ├─ useRemoteQueryStep
           │      │   行113-118
           │      │
           │      └─ ファイル情報取得 (id, url)
           │
           ├─ transform (成功通知データ)
           │      │   行120-138
           │      │
           │      └─ ダウンロードリンク情報を含む通知データ生成
           │
           └─ sendNotificationsStep
                  行140
```

### データフロー図

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

ExportOrdersDTO          ───▶  exportOrdersWorkflow
  │                                   │
  ├─ select                           │
  └─ filter                           │
                                      │
                                      ▼
                               exportOrdersStep
                                      │
                                      ├─ 注文データ取得 (query.graph)
                                      │   - customer, shipping_address
                                      │   - payment_collections, fulfillments
                                      │
                                      ├─ ステータス算出
                                      │   - payment_status
                                      │   - fulfillment_status
                                      │
                                      ├─ データ正規化 (normalizeOrderForExport)
                                      │
                                      ├─ CSV変換 (json2csv)
                                      │
                                      └─ ファイルアップロード
                                             │
                                             ▼
                                      {id: fileKey, filename}
                                             │
                                             ▼
                               useRemoteQueryStep
                                      │
                                      └─ ファイルURL取得
                                             │
                                             ▼
                               transform (成功通知データ)
                                      │
                                      ├─ title: "Order export"
                                      ├─ description: "...completed successfully!"
                                      └─ file:
                                           ├─ filename
                                           ├─ url
                                           └─ mimeType: "text/csv"
                                             │
                                             ▼
                               sendNotificationsStep
                                      │
                                      ▼
                               [管理画面フィード]
                               (ダウンロードリンク付き)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| export-orders.ts (workflow) | `packages/core/core-flows/src/order/workflows/export-orders.ts` | ソース | 注文エクスポートワークフロー定義 |
| export-orders.ts (steps) | `packages/core/core-flows/src/order/steps/export-orders.ts` | ソース | CSV生成・アップロードステップ |
| aggregate-status.ts | `packages/core/core-flows/src/order/utils/aggregate-status.ts` | ソース | 支払い・配送ステータス算出ユーティリティ |
| send-notifications.ts | `packages/core/core-flows/src/notification/steps/send-notifications.ts` | ソース | 通知送信ステップ |
| notify-on-failure.ts | `packages/core/core-flows/src/notification/steps/notify-on-failure.ts` | ソース | 失敗時通知ステップ |
| notification-module-service.ts | `packages/modules/notification/src/services/notification-module-service.ts` | ソース | 通知モジュールサービス |
