# 通知設計書 20-UI通知メッセージ

## 概要

本ドキュメントは、InvenTreeシステムにおける「UI通知メッセージ」の設計仕様を定義する。ユーザーインターフェース上で表示される通知メッセージを作成・管理するプラグイン機能について詳述する。

### 本通知の処理概要

UI通知メッセージは、InvenTreeUINotificationsプラグインによって提供される機能であり、システム内で発生した各種通知をユーザーインターフェース上に表示するための通知メッセージを生成する。

**業務上の目的・背景**：ユーザーがシステムにログインしている間、重要な通知をリアルタイムでUIに表示することで、メールを確認せずとも重要な情報を即座に把握できる。これにより、業務の効率化と情報の見落とし防止に寄与する。また、通知の既読/未読管理により、ユーザーは処理済みの通知と未処理の通知を区別できる。

**通知の送信タイミング**：InvenTreeの各通知機能（返品受領、製造指示、在庫不足など）がtrigger_notificationを呼び出した際に、InvenTreeUINotificationsプラグインのsend_notification()メソッドが実行され、NotificationMessageレコードが作成される。

**通知の受信者**：各通知のターゲットユーザーリストに含まれるユーザーが受信対象となる。各ユーザーに対して個別のNotificationMessageレコードが作成される。

**通知内容の概要**：通知カテゴリ、通知名、メッセージ本文、対象オブジェクトへの参照を含む。UIからは通知一覧として表示され、各通知をクリックすると対象オブジェクトの詳細ページに遷移できる。

**期待されるアクション**：ユーザーはUI上の通知を確認し、必要に応じて対象オブジェクトの詳細ページに遷移して対応を行う。確認後は通知を既読としてマークする。

## 通知種別

- UI通知（ブラウザ上での表示）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（trigger_notification処理内で直接作成） |
| 優先度 | - |
| リトライ | 無 |

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

1. trigger_notificationで決定されたユーザーリストを受け取る
2. 各ユーザーに対してNotificationMessageレコードを作成
3. ユーザーリストが空の場合はFalseを返して処理終了

## 通知テンプレート

### UI表示の場合

| 項目 | 内容 |
|-----|------|
| 表示形式 | 通知リスト |
| 表示項目 | カテゴリ、名前、メッセージ、作成日時、対象オブジェクトリンク |

### データ構造

NotificationMessageモデルに保存される情報：

| フィールド | 説明 | データ型 |
|----------|------|---------|
| target_content_type | 対象オブジェクトのContentType | ForeignKey |
| target_object_id | 対象オブジェクトのID | PositiveIntegerField |
| target_object | 対象オブジェクトへのGenericForeignKey | GenericForeignKey |
| source_content_type | ソースオブジェクトのContentType | ForeignKey |
| source_object_id | ソースオブジェクトのID | PositiveIntegerField |
| source_object | ソースオブジェクトへのGenericForeignKey | GenericForeignKey |
| user | 通知を受け取るユーザー | ForeignKey |
| category | 通知カテゴリ | CharField |
| name | 通知名 | CharField |
| message | 通知メッセージ | CharField |
| creation | 作成日時 | DateTimeField |
| read | 既読フラグ | BooleanField |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| name | 通知名 | context['name'] | Yes |
| message | 通知メッセージ | context['message'] | No |
| category | 通知カテゴリ | category引数 | Yes |
| target | 対象オブジェクト | target引数 | Yes |
| users | 通知対象ユーザーリスト | users引数 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | trigger_notification | users.length > 0 | 各種通知イベント時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| ユーザーリストが空 | users引数が空リストまたはNoneの場合はFalseを返す |
| ターゲットオブジェクトがNone | targetがNoneの場合、プラグイン設定をターゲットとして使用 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[trigger_notification呼び出し] --> B[InvenTreeUINotifications.send_notification]
    B --> C{users存在?}
    C -->|No| D[return False]
    C -->|Yes| E{target存在?}
    E -->|No| F[target = plugin_config]
    E -->|Yes| G[target使用]
    F --> G
    G --> H[各ユーザーに対してループ]
    H --> I[NotificationMessageインスタンス作成]
    I --> J[entries配列に追加]
    J --> K[次のユーザーへ]
    K --> H
    K --> L[NotificationMessage.objects.bulk_create]
    L --> M[return True]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| django_content_type | ContentType取得 | GenericForeignKey用 |
| plugin_pluginconfig | プラグイン設定 | ターゲットなし時のフォールバック |
| auth_user | ユーザー情報 | 通知対象ユーザー |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| common_notificationmessage | INSERT | 通知メッセージ作成 |

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

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | target_content_type | ContentType of target | 対象オブジェクト種別 |
| INSERT | target_object_id | target.pk | 対象オブジェクトID |
| INSERT | source_content_type | ContentType of user | ソースユーザー種別 |
| INSERT | source_object_id | user.pk | ソースユーザーID |
| INSERT | user | User instance | 通知対象ユーザー |
| INSERT | category | category引数 | 通知カテゴリ |
| INSERT | name | context['name'] | 通知名 |
| INSERT | message | context['message'] | 通知メッセージ |
| INSERT | creation | auto_now_add | 作成日時 |
| INSERT | read | False | 未読状態 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| bulk_create失敗 | DB制約違反など | 例外がスローされ、呼び出し元で処理 |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし（各通知イベントごとに作成） |

### 配信時間帯

制限なし（リアルタイム作成）

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

- 各ユーザーは自分宛の通知のみ閲覧可能（userフィールドでフィルタリング）
- API経由での通知アクセスは認証が必要
- 通知メッセージには対象オブジェクトへのリンクを含むが、オブジェクトの詳細情報は含まない

## 備考

- InvenTreeUINotificationsは組み込みプラグインとして提供
- bulk_createにより複数ユーザーへの通知を効率的に作成
- targetがNoneの場合のフォールバック処理（plugin_configをターゲットとして使用）は、GitHub Issue #10435への対応

---

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

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

### 推奨読解順序

#### Step 1: プラグイン構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | core_notifications.py | `src/backend/InvenTree/plugin/builtin/integration/core_notifications.py` | InvenTreeUINotificationsクラス（行19-60） |

**読解のコツ**: InvenTreeUINotificationsはNotificationMixinを継承し、send_notification()メソッドを実装する。

#### Step 2: 通知送信処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | core_notifications.py | `src/backend/InvenTree/plugin/builtin/integration/core_notifications.py` | send_notification()（行29-60） |

**主要処理フロー**:
1. **行33-35**: contextからの値取得
2. **行37-39**: usersチェック（空の場合はFalse返却）
3. **行41-43**: targetがNoneの場合のフォールバック
4. **行46-56**: 各ユーザーに対してNotificationMessage作成
5. **行58**: bulk_createで一括挿入
6. **行60**: True返却

#### Step 3: NotificationMessageモデルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | models.py | `src/backend/InvenTree/common/models.py` | NotificationMessageクラス（行1653-1722） |

**主要フィールド**:
- target_content_type / target_object_id: GenericForeignKeyによる対象オブジェクト参照
- source_content_type / source_object_id: GenericForeignKeyによるソースオブジェクト参照
- user: 通知を受け取るユーザー
- category, name, message: 通知内容
- creation: 作成日時（auto_now_add）
- read: 既読フラグ（デフォルトFalse）

#### Step 4: API経由のアクセスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | api.py | `src/backend/InvenTree/common/api.py` | NotificationMessageViewSet |

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

```
trigger_notification() [common/notifications.py]
    │
    ├─ NotificationEntry.check_recent()
    │
    ├─ ターゲットユーザー収集
    │
    └─ for plugin in notification_plugins:
           │
           └─ InvenTreeUINotifications.send_notification()
                  │
                  ├─ ctx = context if context else {}
                  │
                  ├─ entries = []
                  │
                  ├─ [target is None] target = self.plugin_config()
                  │
                  ├─ for user in users:
                  │      │
                  │      └─ entries.append(
                  │             NotificationMessage(
                  │                 target_object=target,
                  │                 source_object=user,
                  │                 user=user,
                  │                 category=category,
                  │                 name=ctx.get('name'),
                  │                 message=ctx.get('message'),
                  │             )
                  │         )
                  │
                  └─ NotificationMessage.objects.bulk_create(entries)
```

### データフロー図

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

trigger_notification ───▶ InvenTreeUINotifications.send_notification()
        │                        │
        ├─ target               ├─ ターゲットオブジェクト設定
        ├─ category             │
        ├─ users                ├─ 各ユーザー用NotificationMessage作成
        └─ context              │
                                └─ bulk_create ───▶ common_notificationmessage
                                                          │
                                                          └─ UI表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| core_notifications.py | `src/backend/InvenTree/plugin/builtin/integration/core_notifications.py` | ソース | InvenTreeUINotificationsプラグイン |
| models.py | `src/backend/InvenTree/common/models.py` | ソース | NotificationMessageモデル |
| notifications.py | `src/backend/InvenTree/common/notifications.py` | ソース | trigger_notification関数 |
| api.py | `src/backend/InvenTree/common/api.py` | ソース | NotificationMessage API |
| serializers.py | `src/backend/InvenTree/common/serializers.py` | ソース | NotificationMessageシリアライザ |
