# 通知設計書 2-商品インポート成功通知

## 概要

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

### 本通知の処理概要

本通知は、管理者が商品データをCSVファイルからインポートする際、インポート処理が正常に完了したことを管理画面のフィード（通知一覧）に表示する機能を提供する。ワークフロー（importProductsWorkflow、importProductsAsChunksWorkflow）が正常終了した際にsendNotificationsStepが実行され、管理者に成功を通知する。

**業務上の目的・背景**：商品インポートはバックグラウンドで非同期実行されるため、管理者は処理の完了を即座に確認できない。この通知により、管理者は商品インポートが正常に完了したことを知り、次のアクションに移ることができる。また、一括登録作業の効率化と、作業完了の確実な把握を支援する。

**通知の送信タイミング**：商品インポートワークフロー（importProductsWorkflow または importProductsAsChunksWorkflow）が全てのステップを正常に完了した後、sendNotificationsStepが実行される時点で送信される。バックグラウンド実行が完了した後に発火する。

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

**通知内容の概要**：インポートしたファイル名を含む成功メッセージが表示される。「Product import of file {filename} completed successfully!」という形式で、どのファイルのインポートが完了したかを明示する。

**期待されるアクション**：管理者は通知を確認し、インポートされた商品が正しく登録されているかを商品一覧画面で確認することが期待される。必要に応じて、商品情報の編集や追加設定を行う。

## 通知種別

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

## 送信仕様

### 基本情報

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

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

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

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

## 通知テンプレート

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

| 項目 | 内容 |
|-----|------|
| チャネル | feed |
| テンプレートID | admin-ui |
| タイトル | Product import |
| 説明 | Product import of file {filename} completed successfully! |

### 本文テンプレート

```
タイトル: Product import
説明: Product import of file {ファイル名} completed successfully!

例:
タイトル: Product import
説明: Product import of file products.csv completed successfully!
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | 成功通知には添付ファイルなし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| title | 通知タイトル | 固定値 "Product import" | Yes |
| description | 通知説明文 | ワークフロー入力のfilename | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ワークフロー | importProductsWorkflow正常完了 | batchProductsWorkflow成功後 | CSVからのインポート処理成功時 |
| ワークフロー | importProductsAsChunksWorkflow正常完了 | processImportChunksStep成功後 | チャンク分割インポート処理成功時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| ワークフロー失敗 | 途中のステップでエラーが発生した場合、成功通知は送信されない |
| ユーザーキャンセル | 確認待ちステップでキャンセルされた場合 |
| feedプロバイダー未設定 | feedチャネルに対応するNotification Providerが未設定の場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[商品インポートAPI呼び出し] --> B[importProductsWorkflow開始]
    B --> C[normalizeCsvStep: CSV解析]
    C --> D[waitConfirmationProductImportStep: 確認待ち]
    D --> E{ユーザー確認}
    E -->|キャンセル| F[処理終了]
    E -->|確認| G[notifyOnFailureStep登録]
    G --> H[batchProductsWorkflow実行]
    H --> I{インポート成功?}
    I -->|失敗| J[notifyOnFailureStep補償実行]
    I -->|成功| K[成功通知データ構築]
    K --> L[sendNotificationsStep実行]
    L --> M[notificationService.createNotifications]
    M --> N[フィードに通知表示]
    N --> O[WorkflowResponse返却]
    J --> P[失敗通知送信]
    F --> Q[終了]
    O --> Q
    P --> Q
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| notification_provider | プロバイダー情報取得 | feedチャネルに対応するプロバイダーを検索 |
| notification | 重複チェック | idempotency_keyによる既存通知確認（設定時） |

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

#### notification_provider

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

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| notification | INSERT | 通知レコードの作成 |

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

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

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| プロバイダー未設定 | feedチャネルのプロバイダーが見つからない | MedusaError発生、通知作成失敗 |
| プロバイダー無効 | プロバイダーのis_enabled=false | MedusaError発生、通知作成失敗 |
| 送信ステップ失敗 | sendNotificationsStepでエラー | ワークフローは補償処理なしで失敗 |

### リトライ仕様

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

※ sendNotificationsStepには補償処理が定義されていないため、失敗時のリトライは行われない

## 配信設定

### レート制限

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

### 配信時間帯

制限なし（インポート完了時に即時通知）

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

- 通知は管理者向けであり、顧客の個人情報は含まれない
- ファイル名のみが通知内容に含まれるため、機密情報の漏洩リスクは低い
- 管理画面へのアクセスには認証が必要

## 備考

- インポートはバックグラウンド実行（backgroundExecution: true）されるため、APIレスポンスは即座に返却される
- waitConfirmationProductImportStepでユーザー確認を待つ設計により、誤ったインポートを防止
- 同一ワークフロー内にnotifyOnFailureStepが登録されており、失敗時は別途失敗通知が送信される
- 将来的に特定ユーザーへの通知対応も検討されている（コードコメント）

---

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

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

### 推奨読解順序

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

まず、ワークフロー入力と通知データの構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | import-products.ts (types) | `packages/core/types/src/workflow/product/import-products.ts` | ImportProductsDTOの構造を確認 |
| 1-2 | send-notifications.ts | `packages/core/core-flows/src/notification/steps/send-notifications.ts` | SendNotificationsStepInput型を確認 |

**読解のコツ**: ワークフロー入力からどのようなデータが通知に渡されるかを追跡する。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | import-products.ts | `packages/core/core-flows/src/product/workflows/import-products.ts` | ワークフロー全体の流れを把握 |
| 2-2 | import-products-as-chunks.ts | `packages/core/core-flows/src/product/workflows/import-products-as-chunks.ts` | チャンク版ワークフローとの違いを確認 |

**主要処理フロー (import-products.ts)**:
1. **行88-143**: createWorkflowでワークフロー定義
2. **行93**: normalizeCsvStep - CSVを解析
3. **行95-100**: transform - サマリー生成
4. **行102**: waitConfirmationProductImportStep - 確認待ち
5. **行105-118**: transform - 失敗通知データ構築
6. **行120**: notifyOnFailureStep - 失敗時通知登録
7. **行122-124**: batchProductsWorkflow実行（バックグラウンド）
8. **行126-139**: transform - 成功通知データ構築
9. **行140**: sendNotificationsStep - 成功通知送信

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

通知の送信処理を理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | send-notifications.ts | `packages/core/core-flows/src/notification/steps/send-notifications.ts` | 送信ステップの実装 |

**主要処理フロー**:
- **行12-75**: SendNotificationsStepInput型定義
- **行81-94**: sendNotificationsStep実装
- **行84-86**: INotificationModuleServiceの解決
- **行87**: createNotifications呼び出し

#### Step 4: 失敗通知ステップを理解する

失敗時の補償処理を理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | notify-on-failure.ts | `packages/core/core-flows/src/notification/steps/notify-on-failure.ts` | 失敗通知ステップの仕組み |

**主要処理フロー**:
- **行74-90**: notifyOnFailureStep定義
- **行76-77**: mainAction - 何もせずデータを補償に渡す
- **行80-89**: compensateAction - 失敗時に通知を送信

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

```
[商品インポートAPI]
    │
    └─ importProductsWorkflow
           │   行88-143
           │
           ├─ normalizeCsvStep
           │      行93
           │
           ├─ transform (サマリー生成)
           │      行95-100
           │
           ├─ waitConfirmationProductImportStep
           │      行102
           │
           ├─ transform (失敗通知データ)
           │      行105-118
           │
           ├─ notifyOnFailureStep
           │      │   行120
           │      │
           │      └─ [補償時] notificationService.createNotifications
           │
           ├─ batchProductsWorkflow.runAsStep
           │      │   行122-124 (async: true, backgroundExecution: true)
           │      │
           │      └─ [内部処理]
           │
           ├─ transform (成功通知データ)
           │      行126-139
           │
           └─ sendNotificationsStep
                  │   行140
                  │
                  └─ notificationService.createNotifications
```

### データフロー図

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

ImportProductsDTO        ───▶  importProductsWorkflow     ───▶  管理画面フィード
  │                                   │                              │
  ├─ fileContent                      │                              │
  └─ filename ─────────────────▶ transform ──────────────────▶ 通知データ
                                      │                              │
                                      │                              ├─ title: "Product import"
                                      │                              │
                                      │                              └─ description:
                                      │                                 "Product import of file
                                      │                                  {filename} completed
                                      │                                  successfully!"
                                      │
                                      ▼
                               sendNotificationsStep
                                      │
                                      ▼
                               NotificationModuleService
                                .createNotifications
                                      │
                                      ▼
                               [notification テーブル]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| import-products.ts | `packages/core/core-flows/src/product/workflows/import-products.ts` | ソース | 商品インポートワークフロー定義 |
| import-products-as-chunks.ts | `packages/core/core-flows/src/product/workflows/import-products-as-chunks.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` | ソース | 通知モジュールサービス |
| import-products.ts (types) | `packages/core/types/src/workflow/product/import-products.ts` | 型定義 | ワークフロー入力型 |
