# 通知設計書 12-新規製造指示通知

## 概要

本ドキュメントは、InvenTreeシステムにおける「新規製造指示通知」の設計仕様を定義する。新しい製造指示（Build Order）が作成され担当者に割り当てられた際に通知を送信する機能について詳述する。

### 本通知の処理概要

新規製造指示通知は、新しいBuild Orderが作成された際に、責任者および関連するパーツの購読者に自動的に通知を送信する機能である。

**業務上の目的・背景**：製造指示は製造業務の起点となる重要なオブジェクトである。新しい製造指示が作成されたことを担当者に即座に通知することで、製造準備の開始、資材の確認、スケジュール調整などの業務を迅速に開始できる。また、関連パーツの購読者に通知することで、サプライチェーン全体での情報共有が促進される。

**通知の送信タイミング**：Buildモデルのpost_saveシグナルが発火した際、created=Trueの場合にトリガーされる。具体的には、Build Orderが初めてデータベースに保存された直後に通知処理が実行される。

**通知の受信者**：製造指示の責任者（responsible）フィールドに設定されたユーザーまたはグループ、および製造対象パーツの購読者（subscribers）が受信対象となる。製造指示を発行したユーザー（issued_by）は除外される。

**通知内容の概要**：新しい製造指示が作成され割り当てられたことを通知する。InvenTreeNotificationBodies.NewOrderテンプレートを使用し、製造指示の詳細へのリンクを含む。

**期待されるアクション**：受信者は製造指示の内容を確認し、必要な資材の在庫確認、製造スケジュールの調整、作業者の割り当てなどの準備作業を開始する。

## 通知種別

- メール通知（InvenTreeEmailNotifications経由）
- UI通知（InvenTreeUINotifications経由）
- Slack通知（InvenTreeSlackNotifications経由、設定時）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（post_saveシグナル内で直接呼び出し） |
| 優先度 | 中 |
| リトライ | 無（通知送信失敗時はログ記録のみ） |

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

1. `notify_responsible()`関数により送信先を決定
2. Build Orderの`responsible`フィールドに設定されたOwner（ユーザーまたはグループ）
3. `extra_users`として製造対象パーツに購読しているユーザー（`instance.part.get_subscribers()`）
4. 製造指示を発行したユーザー（issued_by）は`exclude`パラメータにより除外

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | システム設定による |
| 送信元名称 | [INVENTREE_INSTANCE] |
| 件名 | New Build Order（動的に生成） |
| 形式 | HTML |

### 本文テンプレート

```html
{% extends "email/email.html" %}

{% block title %}
{{ message }}
{% if link %}
<p>Click on the following link to view this order: <a href="{{ link }}">{{ link }}</a></p>
{% endif %}
{% endblock title %}
```

### 添付ファイル

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

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| name | 通知名（"New {verbose_name}"） | InvenTreeNotificationBodies.NewOrder | Yes |
| message | 通知メッセージ | InvenTreeNotificationBodies.NewOrder | Yes |
| link | 製造指示詳細ページへのリンク | construct_absolute_url(build.get_absolute_url()) | No |
| slug | 通知カテゴリスラッグ | 'build.new_build' | Yes |
| verbose_name | モデル表示名 | Build._meta.verbose_name | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| シグナル | Build post_save | created=True | 新規Build Order作成時 |
| API | POST /api/build/ | 新規作成成功時 | REST API経由でのBuild Order作成 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| データインポート中 | isImportingData()がTrueの場合は通知をスキップ |
| データベース未準備 | canAppAccessDatabase()がFalseの場合はスキップ |
| 更新時 | created=Falseの場合は新規作成通知は送信されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[Build.save呼び出し] --> B[post_saveシグナル発火]
    B --> C{canAppAccessDatabase?}
    C -->|No| D[処理終了]
    C -->|Yes| E{isImportingData?}
    E -->|Yes| D
    E -->|No| F{created?}
    F -->|No| G[update_build_line_items]
    F -->|Yes| H[create_build_line_items]
    H --> I[notify_responsible呼び出し]
    I --> J[送信先ユーザー収集]
    J --> K[trigger_notification呼び出し]
    K --> L[各通知プラグインで送信]
    L --> M[NotificationEntry記録]
    M --> N[終了]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| build_build | 製造指示情報取得 | 責任者、発行者情報 |
| part_part | パーツ情報 | 購読者取得用 |
| users_owner | 責任者情報 | 通知先決定 |
| auth_user | ユーザー情報 | 送信先ユーザー |

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

#### build_build

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| responsible | 責任者取得 | 製造指示に紐づく |
| issued_by | 除外対象ユーザー | 発行者 |
| part | 製造対象パーツ | 購読者取得用 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| common_notificationentry | INSERT/UPDATE | 通知送信記録 |
| common_notificationmessage | INSERT | UI通知メッセージ |

#### 送信ログテーブル

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT/UPDATE | key | 'build.new_build' | 通知カテゴリ |
| INSERT/UPDATE | uid | Build.pk | 対象オブジェクトID |
| INSERT/UPDATE | updated | 現在日時 | 最終送信日時 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 送信失敗 | メール送信エラー | ログ記録、処理続行 |
| テンプレートエラー | テンプレート変数不正 | ログ記録、処理続行 |
| 宛先不正 | 宛先ユーザーが無効 | 該当ユーザーをスキップ |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 同一カテゴリ・オブジェクトに対し1回（check_recent機能） |

### 配信時間帯

制限なし（リアルタイム送信）

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

- 通知を受信できるのは、該当する権限（view権限）を持つユーザーのみ
- メール本文には機密情報を含まないよう、リンクのみを提供
- NOTIFY_BY_EMAILユーザー設定によりメール通知の受信可否を制御可能

## 備考

- NewOrder通知ボディは`common/notifications.py`で定義され、汎用的なオーダー作成通知として使用
- 動的なスラッグ生成（'{app_label}.new_{model_name}'）により、Build Order固有のカテゴリが設定される
- プラグインベースの通知システムにより、拡張可能な設計

---

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

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

### 推奨読解順序

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

まず、通知に関連するデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | notifications.py | `src/backend/InvenTree/common/notifications.py` | NotificationBody、InvenTreeNotificationBodies.NewOrder（行56-62） |
| 1-2 | models.py | `src/backend/InvenTree/build/models.py` | Buildモデルの構造（行76-111） |

**読解のコツ**: NewOrderはf-string形式のテンプレートを使用し、'{verbose_name}'が実行時に置換される。Buildモデルの場合は"Build Order"となる。

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

処理の起点となるファイル・関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | models.py | `src/backend/InvenTree/build/models.py` | after_save_buildシグナルハンドラ（行1556-1583） |

**主要処理フロー**:
1. **行1560-1563**: データインポート中・DB未準備時のスキップ
2. **行1565-1578**: created=Trueの場合の処理
3. **行1570**: create_build_line_items()呼び出し
4. **行1573-1578**: notify_responsible()呼び出し

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | helpers_model.py | `src/backend/InvenTree/InvenTree/helpers_model.py` | notify_responsible関数の実装 |
| 3-2 | notifications.py | `src/backend/InvenTree/common/notifications.py` | trigger_notification関数（行87-218） |

**主要処理フロー**:
- notify_responsibleはBuildの責任者とパーツ購読者に通知を送信
- content引数にInvenTreeNotificationBodies.NewOrderを渡す

#### Step 4: 通知プラグインを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | core_notifications.py | `src/backend/InvenTree/plugin/builtin/integration/core_notifications.py` | 各通知プラグインの実装 |

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

```
Build.save() [build/models.py]
    │
    └─ post_save signal [after_save_build]
           │
           ├─ canAppAccessDatabase() チェック
           │
           ├─ isImportingData() チェック
           │
           ├─ [created=True] create_build_line_items()
           │
           └─ [created=True] notify_responsible() [InvenTree/helpers_model.py]
                  │
                  ├─ Build.responsible → 責任者取得
                  │
                  ├─ Build.part.get_subscribers() → 購読者取得
                  │
                  └─ trigger_notification() [common/notifications.py]
                         │
                         └─ plugin.send_notification() [各プラグイン]
```

### データフロー図

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

Build作成リクエスト ───▶ Build.save() ───▶ post_saveシグナル
                              │                        │
                              └───── after_save_build() ───▶ BuildLine作成
                                           │                     │
                                           └─ notify_responsible() ───▶ NotificationMessage
                                                       │                     │
                                                       ├──────────────▶ Email送信
                                                       │                     │
                                                       └──────────────▶ Slack送信
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| models.py | `src/backend/InvenTree/build/models.py` | ソース | Buildモデル、post_saveシグナル |
| notifications.py | `src/backend/InvenTree/common/notifications.py` | ソース | 通知基盤、NewOrder定義 |
| helpers_model.py | `src/backend/InvenTree/InvenTree/helpers_model.py` | ソース | notify_responsible関数 |
| core_notifications.py | `src/backend/InvenTree/plugin/builtin/integration/core_notifications.py` | ソース | 通知プラグイン実装 |
| new_order_assigned.html | `src/backend/InvenTree/templates/email/new_order_assigned.html` | テンプレート | メール本文テンプレート |
