# 機能設計書 78-通知プロバイダー管理

## 概要

本ドキュメントは、Medusaコマースプラットフォームにおける外部通知プロバイダー（SendGrid、Twilio等）との連携管理機能について記載する。

### 本機能の処理概要

通知プロバイダー管理機能は、メール・SMS等の通知を送信する外部サービスとの連携を抽象化し、統一的なインターフェースを提供する機能である。プロバイダーの登録、チャネルとのマッピング、通知送信の委譲を行う。

**業務上の目的・背景**：
ECサイトでは、メール配信にSendGrid、SMS配信にTwilio等、複数の通知サービスを使い分けることが一般的である。本機能は、これらのサービスを統一的なインターフェースで操作できるようにし、サービスの切り替えや追加を容易にする。また、チャネル（email、sms等）ごとに適切なプロバイダーを自動選択する仕組みを提供する。

**機能の利用シーン**：
- SendGridを使用したメール送信
- Twilioを使用したSMS送信
- カスタム通知プロバイダーの追加
- チャネルに応じたプロバイダーの自動選択

**主要な処理内容**：
1. プロバイダーの登録・初期化
2. チャネルからプロバイダーへのマッピング
3. プロバイダーキャッシュの管理
4. 通知送信の委譲

**関連システム・外部連携**：
- SendGrid（メール送信）
- Twilio（SMS送信）
- その他カスタム通知プロバイダー

**権限による制御**：
- プロバイダー登録は起動時の設定で制御
- 通知送信は呼び出し元の認証・認可に依存

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 直接の関連画面なし（バックエンド基盤機能） |

## 機能種別

インフラ基盤 / プロバイダー抽象化

## 入力仕様

### プロバイダーインターフェース（INotificationProvider）

| メソッド名 | パラメータ | 戻り値 | 説明 |
|-----------|-----------|--------|------|
| send | ProviderSendNotificationDTO | Promise<ProviderSendNotificationResultsDTO> | 通知送信 |

### NotificationProviderモデル

| フィールド名 | 型 | 説明 |
|-------------|-----|------|
| id | string | プロバイダーID（notpro_プレフィックス） |
| handle | string | プロバイダーハンドル名 |
| name | string | プロバイダー表示名 |
| is_enabled | boolean | 有効フラグ |
| channels | string[] | サポートするチャネル配列 |

### 入力データソース

- モジュール設定（medusa-config.js）
- 通知モジュールサービスからの呼び出し

## 出力仕様

### 出力データ（send）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | string | 外部プロバイダー側の通知ID |

### 出力先

- 呼び出し元サービス
- 外部通知サービス

## 処理フロー

### 処理シーケンス

```
【プロバイダー取得】
1. チャネル指定
   └─ getProviderForChannels(channels)
2. キャッシュ確認
   └─ providersCache存在チェック
3. キャッシュ構築（未キャッシュ時）
   └─ DBから有効プロバイダー取得
   └─ チャネル→プロバイダーのマップ作成
4. プロバイダー返却
   └─ 指定チャネルに対応するプロバイダー

【通知送信】
1. プロバイダー指定
   └─ send(provider, notification)
2. プロバイダー実装取得
   └─ retrieveProviderRegistration(provider.id)
3. 送信委譲
   └─ providerHandler.send(notification)
4. 結果返却
   └─ { id: external_id }
```

### フローチャート

```mermaid
flowchart TD
    A[チャネル指定] --> B{キャッシュあり?}
    B -->|No| C[DBからプロバイダー取得]
    C --> D[キャッシュ構築]
    D --> E[チャネルからプロバイダー検索]
    B -->|Yes| E
    E --> F{プロバイダー見つかる?}
    F -->|No| G[undefined返却]
    F -->|Yes| H[プロバイダー返却]

    I[send呼び出し] --> J[プロバイダー実装取得]
    J --> K{取得成功?}
    K -->|No| L[エラー: 未登録]
    K -->|Yes| M[provider.send実行]
    M --> N{送信成功?}
    N -->|Yes| O[結果返却]
    N -->|No| P[エラー返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-78-01 | チャネルマッチング | 通知チャネルに対応するプロバイダーを使用 | 送信時 |
| BR-78-02 | 有効プロバイダーのみ | is_enabled=trueのプロバイダーのみ使用 | プロバイダー取得時 |
| BR-78-03 | キャッシュ利用 | 起動後はメモリキャッシュを使用 | プロバイダー取得時 |
| BR-78-04 | 複数チャネル対応 | 1プロバイダーが複数チャネルをサポート可能 | プロバイダー設定時 |

### 計算ロジック

該当なし

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 取得 | notification_provider | SELECT | 有効プロバイダー一覧取得 |

### テーブル別操作詳細

#### notification_provider

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | is_enabled = true | キャッシュ構築用 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Resolution Error | プロバイダー未登録 | 設定追加 |
| - | Error | プロバイダー取得失敗 | 設定確認 |
| - | Provider Error | 送信失敗 | プロバイダー設定確認 |

### リトライ仕様

プロバイダー内部のリトライ実装に依存。NotificationProviderServiceはリトライなし。

## トランザクション仕様

- プロバイダー取得はキャッシュ優先のため通常はDB操作なし
- 通知送信は外部呼び出しのためトランザクション対象外

## パフォーマンス要件

- キャッシュによる高速なプロバイダー解決
- 起動時にキャッシュ構築済み

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

- プロバイダー認証情報の安全な管理
- 外部サービスとの通信暗号化
- アクセスログの記録

## 備考

- プロバイダーキャッシュは起動後に永続化
- 実行時のプロバイダー追加・削除には再起動が必要
- カスタムプロバイダーはINotificationProviderインターフェースを実装

---

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

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

### 推奨読解順序

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

プロバイダーモデルを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | notification-provider.ts | `packages/modules/notification/src/models/notification-provider.ts` | プロバイダーモデル定義 |

**読解のコツ**:
- channelsフィールドがarray型であることに注意
- is_enabledでプロバイダーの有効/無効を制御
- notificationsとのhasMany関係を確認

#### Step 2: プロバイダーサービスを理解する

NotificationProviderServiceの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | notification-provider.ts | `packages/modules/notification/src/services/notification-provider.ts` | プロバイダーサービス |

**主要処理フロー**:
1. **35-38行目**: providersCache - メモリキャッシュ
2. **49-73行目**: retrieveProviderRegistration - コンテナからプロバイダー取得
3. **75-97行目**: getProviderForChannels - チャネルからプロバイダー特定
4. **79-88行目**: キャッシュ構築ロジック
5. **91-96行目**: チャネルからプロバイダー検索
6. **99-105行目**: send - プロバイダー呼び出し

#### Step 3: 通知サービスとの連携を理解する

NotificationModuleServiceからの呼び出しを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | notification-module-service.ts | `packages/modules/notification/src/services/notification-module-service.ts` | 通知サービス |

**主要処理フロー**:
- **139-143行目**: getProviderForChannels呼び出し
- **148-158行目**: プロバイダー情報の通知データへの設定
- **198-206行目**: NotificationProviderService.send呼び出し

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

```
NotificationModuleService
    │
    └─ NotificationProviderService
           │
           ├─ getProviderForChannels()
           │      │
           │      ├─ キャッシュ確認
           │      │
           │      ├─ DBクエリ（未キャッシュ時）
           │      │      └─ notificationProviderRepository.find()
           │      │
           │      └─ チャネルマップ検索
           │
           └─ send()
                  │
                  ├─ retrieveProviderRegistration()
                  │      └─ コンテナ解決
                  │             └─ noti_provider_xxx
                  │
                  └─ INotificationProvider.send()
                         └─ SendGrid/Twilio等
```

### データフロー図

```
[設定]                    [初期化]                            [実行時]

medusa-config.js          NotificationProviderService
  │                         │
  ├─> provider設定          ├─> コンテナ登録                   getProviderForChannels()
  │   {                     │   noti_provider_sendgrid         │
  │     channels: ["email"] │                                  ├─> キャッシュ検索
  │   }                     └─> DB登録                         │   channel → provider
  │                             notification_provider          │
  │                                                            └─> プロバイダー返却
  │
  │                                                            send()
  │                                                            │
  └─> モジュール登録  ─────────────────────────────────────>  ├─> プロバイダー実装取得
                                                               │
                                                               └─> provider.send()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| notification-provider.ts | `packages/modules/notification/src/services/notification-provider.ts` | ソース | プロバイダーサービス |
| notification-module-service.ts | `packages/modules/notification/src/services/notification-module-service.ts` | ソース | 通知サービス |
| notification-provider.ts | `packages/modules/notification/src/models/notification-provider.ts` | ソース | プロバイダーモデル |
| sendgrid.ts | `packages/modules/providers/notification-sendgrid/src/services/sendgrid.ts` | ソース | SendGridプロバイダー実装 |
| types/index.ts | `packages/modules/notification/src/types/index.ts` | ソース | 型定義 |
