# 機能設計書 45-通知表示

## 概要

本ドキュメントは、InvenTreeシステムにおける通知表示機能の設計仕様を定義する。この機能は、ユーザーへの通知メッセージを一覧表示し、既読/未読の管理、削除操作を提供する。

### 本機能の処理概要

**業務上の目的・背景**：
在庫管理業務では、在庫不足アラート、発注状況の変更、製造指示の更新など、様々なイベントがリアルタイムでユーザーに通知される。本機能は、これらの通知を一覧表示し、ユーザーが効率的に情報を確認・管理できる基盤を提供する。未読通知の把握、既読への切り替え、不要な通知の削除など、日常的な通知管理を支援する。

**機能の利用シーン**：
- ログイン後に未読通知を確認する
- 通知を既読にマークして整理する
- 古い通知を削除する
- すべての通知を一括で既読にする

**主要な処理内容**：
1. ユーザーの通知メッセージ一覧取得（NotificationMessage）
2. 未読/既読フィルタリング
3. 既読/未読ステータスの更新
4. 通知メッセージの削除
5. 一括既読処理

**関連システム・外部連携**：
- 通知設定管理機能（機能No.44）と連携
- フロントエンドのリアルタイム更新
- 通知カウントバッジの更新

**権限による制御**：
- 自分宛ての通知のみ表示・操作可能
- 他ユーザーの通知へのアクセスは不可

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 13 | 通知一覧画面 | 主機能 | 通知一覧表示、既読/未読切替、削除 |

## 機能種別

データ表示 / CRUD操作

## 入力仕様

### 入力パラメータ（一覧取得）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| read | boolean | No | 既読フラグでフィルタ | |
| ordering | string | No | ソート順（creation等） | |
| limit | integer | No | 取得件数 | 1以上 |
| offset | integer | No | オフセット | 0以上 |

### 入力パラメータ（更新）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| read | boolean | Yes | 既読フラグ | |

### 入力データソース

- 通知一覧画面からのAPIリクエスト
- ナビゲーションバーの通知アイコン

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| pk | integer | 通知ID |
| category | string | 通知カテゴリ |
| name | string | 通知名 |
| message | string | 通知メッセージ |
| creation | datetime | 作成日時 |
| read | boolean | 既読フラグ |
| age_human | string | 経過時間（人間可読形式） |
| target | object | 通知対象オブジェクト情報 |

### 出力先

- 通知一覧画面（テーブル形式）
- ナビゲーションバーの通知バッジ（未読数）

## 処理フロー

### 処理シーケンス

```
1. 通知一覧取得リクエスト
   └─ GET /api/notifications/
2. ユーザーフィルタリング
   └─ user=request.user
3. 既読/未読フィルタ適用
   └─ read=true/false
4. ソート・ページネーション適用
   └─ ordering, limit, offset
5. シリアライズしてレスポンス
```

### フローチャート

```mermaid
flowchart TD
    A[通知一覧リクエスト] --> B[認証ユーザー確認]
    B --> C{認証OK?}
    C -->|No| D[401エラー]
    C -->|Yes| E[ユーザーでフィルタ]
    E --> F{readパラメータ?}
    F -->|あり| G[既読/未読フィルタ]
    F -->|なし| H[全件取得]
    G --> I[ソート・ページネーション]
    H --> I
    I --> J[シリアライズ]
    J --> K[レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-45-01 | ユーザースコープ | 自分宛ての通知のみ表示 | 全ての通知操作 |
| BR-45-02 | 一括既読 | 全未読通知を一括で既読にできる | 一括既読API呼び出し時 |
| BR-45-03 | 削除権限 | 既読の通知のみ削除可能 | 削除操作時 |
| BR-45-04 | 作成日時ソート | デフォルトは作成日時の降順 | 一覧取得時 |

### 計算ロジック

経過時間の計算（age_human）：
```python
from django.contrib.humanize.templatetags.humanize import naturaltime
age_human = naturaltime(notification.creation)
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 通知一覧取得 | common_notificationmessage | SELECT | ユーザーの通知取得 |
| 既読更新 | common_notificationmessage | UPDATE | readフラグ更新 |
| 通知削除 | common_notificationmessage | DELETE | 通知メッセージ削除 |
| 一括既読 | common_notificationmessage | UPDATE | 全未読を既読に更新 |

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

#### common_notificationmessage

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | user_id | user=current_user | ユーザーフィルタ |
| SELECT | read | read=true/false | 既読フィルタ |
| UPDATE | read | true/false | 既読ステータス変更 |
| DELETE | pk | pk=指定値 | 通知削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | Unauthorized | 未認証 | ログインを実行 |
| 404 | NotFound | 通知が存在しない | 正しい通知IDを指定 |
| 403 | PermissionDenied | 他ユーザーの通知へのアクセス | 自分の通知のみ操作 |

### リトライ仕様

通知操作は冪等であり、再試行が可能。

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

一括既読処理は単一トランザクションで実行される。

## パフォーマンス要件

- 通知一覧取得：100ms以内
- 既読更新：50ms以内

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

- 認証済みユーザーのみアクセス可能
- ユーザーは自分の通知のみ操作可能
- IDOR（Insecure Direct Object Reference）対策としてユーザーチェック必須

## 備考

- 通知の定期的なクリーンアップはシステム設定に依存
- 通知対象オブジェクト（target_object）へのリンクを提供

---

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

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

### 推奨読解順序

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

通知メッセージのデータモデルを理解する。

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

**読解のコツ**:
- `target_content_type`と`target_object_id`でジェネリックリレーション
- `source_content_type`と`source_object_id`で通知ソースを参照
- `read`フラグでデフォルトはFalse（未読）
- `creation`でauto_now_addにより作成日時を自動記録

#### Step 2: フロントエンドの通知表示を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Notifications.tsx | `src/frontend/src/pages/Notifications.tsx` | NotificationsPageコンポーネント（22-134行目） |
| 2-2 | NotificationTable.tsx | `src/frontend/src/tables/notifications/NotificationTable.tsx` | NotificationTableコンポーネント |

**主要処理フロー**:
1. **24-25行目**: unreadTableとreadTableで未読/既読を分離
2. **27-38行目**: markAllAsRead()で一括既読処理
3. **41-78行目**: 未読通知パネル（mark as read アクション付き）
4. **81-125行目**: 既読通知パネル（mark as unread, delete アクション付き）

#### Step 3: バックエンドAPIを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | api.py | `src/backend/InvenTree/common/api.py` | NotificationList, NotificationDetail, NotificationReadAll |

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

```
NotificationsPage
    │
    ├─ useTable('unreadnotifications')
    │      └─ 未読通知テーブル状態管理
    │
    ├─ useTable('readnotifications')
    │      └─ 既読通知テーブル状態管理
    │
    ├─ markAllAsRead()
    │      │
    │      └─ GET /api/notifications/readall/
    │             └─ 全未読を既読に更新
    │
    └─ NotificationTable
           │
           ├─ GET /api/notifications/?read=false
           │      └─ 未読通知一覧取得
           │
           ├─ GET /api/notifications/?read=true
           │      └─ 既読通知一覧取得
           │
           ├─ PATCH /api/notifications/{pk}/
           │      └─ 既読/未読切替
           │
           └─ DELETE /api/notifications/{pk}/
                  └─ 通知削除
```

### データフロー図

```
[フロントエンド]         [バックエンド]              [データベース]

NotificationsPage  ───▶ GET /api/notifications/ ───▶ SELECT
       │                                              common_notificationmessage
       │
       ▼
NotificationTable  ───▶ PATCH/DELETE            ───▶ UPDATE/DELETE
  (未読/既読タブ)         /api/notifications/{pk}/     common_notificationmessage
       │
       ▼
markAllAsRead()    ───▶ GET /api/notifications/ ───▶ UPDATE
                        /readall/                     read=true (全件)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| models.py | `src/backend/InvenTree/common/models.py` | ソース | NotificationMessage |
| api.py | `src/backend/InvenTree/common/api.py` | ソース | 通知API |
| serializers.py | `src/backend/InvenTree/common/serializers.py` | ソース | 通知シリアライザ |
| Notifications.tsx | `src/frontend/src/pages/Notifications.tsx` | ソース | 通知一覧ページ |
| NotificationTable.tsx | `src/frontend/src/tables/notifications/NotificationTable.tsx` | ソース | 通知テーブルコンポーネント |
