# 機能設計書 48-メモ・ノート管理

## 概要

本ドキュメントは、InvenTreeシステムにおけるメモ・ノート管理機能の設計仕様を定義する。この機能は、各種オブジェクトに対してMarkdown形式のメモを作成・編集し、メモ内で使用する画像のアップロードを管理する。

### 本機能の処理概要

**業務上の目的・背景**：
在庫管理業務では、部品に関する補足情報、製造指示への注意事項、発注に関するメモなど、フリーテキストでの情報記録が必要である。本機能は、各種オブジェクトに対してMarkdown形式でリッチテキストのメモを記録でき、画像の埋め込みもサポートする。これにより、テキストだけでなく図や写真を含む詳細なドキュメントを各オブジェクトに紐づけて管理できる。

**機能の利用シーン**：
- 部品に製造上の注意事項をメモとして追加する
- 在庫アイテムに品質検査結果の写真付きメモを記録する
- 発注書に打ち合わせ内容をメモとして残す
- 製造指示に作業手順の図解を追加する

**主要な処理内容**：
1. オブジェクトのnotesフィールドへのMarkdownテキスト保存
2. メモ用画像のアップロード（NotesImage）
3. 画像URLの生成とMarkdownへの埋め込み

**関連システム・外部連携**：
- ファイルストレージ（画像保存）
- Markdownレンダリング（フロントエンド）

**権限による制御**：
- メモの閲覧は対象オブジェクトの閲覧権限に依存
- メモの編集は対象オブジェクトの変更権限が必要
- 画像アップロードは認証済みユーザーで可能

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 14 | 部品詳細画面 | 主機能 | notesフィールドの編集 |
| 16 | 在庫アイテム詳細画面 | 主機能 | notesフィールドの編集 |
| 26 | 発注書詳細画面 | 主機能 | notesフィールドの編集 |
| 27 | 受注詳細画面 | 主機能 | notesフィールドの編集 |

## 機能種別

CRUD操作 / テキスト編集 / 画像管理

## 入力仕様

### 入力パラメータ（ノート編集）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| notes | string | No | Markdown形式のメモテキスト | |

### 入力パラメータ（画像アップロード）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| image | file | Yes | 画像ファイル | 画像形式チェック |
| model_type | string | No | 対象モデルタイプ | |
| model_id | integer | No | 対象モデルID | 正の整数 |

### 入力データソース

- 詳細画面のノートタブ
- APIリクエスト（マルチパートフォーム）

## 出力仕様

### 出力データ（ノート）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| notes | string | Markdownテキスト |

### 出力データ（画像）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| pk | integer | 画像ID |
| image | string | 画像URL |
| user | object | アップロードユーザー |
| date | datetime | アップロード日時 |

### 出力先

- APIレスポンス（JSON形式）
- 詳細画面のノートセクション

## 処理フロー

### 処理シーケンス（ノート編集）

```
1. ノート編集リクエスト
   └─ PATCH /api/{model}/{pk}/
2. 権限チェック
   └─ 対象モデルの変更権限確認
3. notesフィールド更新
   └─ モデルのnotesフィールドを更新
4. レスポンス返却
```

### 処理シーケンス（画像アップロード）

```
1. 画像アップロードリクエスト
   └─ POST /api/notes-image/
2. 画像バリデーション
   └─ 画像形式チェック
3. 画像保存
   └─ メディアストレージに保存
4. NotesImageレコード作成
   └─ common_notesimage テーブルにINSERT
5. 画像URLを返却
```

### フローチャート

```mermaid
flowchart TD
    A[画像アップロードリクエスト] --> B[画像バリデーション]
    B --> C{画像形式OK?}
    C -->|No| D[エラーレスポンス]
    C -->|Yes| E[ファイル名生成]
    E --> F[画像保存]
    F --> G[DBレコード作成]
    G --> H[画像URL返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-48-01 | Markdownサポート | notesフィールドはMarkdown形式をサポート | 全てのnotesフィールド |
| BR-48-02 | 画像形式制限 | アップロード可能なのは画像ファイルのみ | 画像アップロード時 |
| BR-48-03 | ユーザー記録 | アップロードユーザーを自動記録 | 画像アップロード時 |
| BR-48-04 | モデル参照任意 | model_type/model_idは任意（画像の関連付け） | 画像アップロード時 |

### 計算ロジック

画像ファイル名の生成：
```python
def rename_notes_image(instance, filename):
    return f'notes_files/{instance.model_type}/{instance.model_id}/{filename}'
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ノート取得 | 各モデルテーブル | SELECT | notesフィールド取得 |
| ノート更新 | 各モデルテーブル | UPDATE | notesフィールド更新 |
| 画像一覧取得 | common_notesimage | SELECT | 画像リスト取得 |
| 画像アップロード | common_notesimage | INSERT | 画像レコード作成 |

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

#### common_notesimage

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | image | ファイルパス | ImageField |
| INSERT | user | 現在ユーザー | ForeignKey |
| INSERT | date | 現在日時 | auto_now_add |
| INSERT | model_type | モデルタイプ | 任意 |
| INSERT | model_id | モデルID | 任意 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 400 | ValidationError | 無効な画像形式 | 画像ファイルをアップロード |
| 403 | PermissionDenied | 変更権限なし | 管理者に権限付与を依頼 |

### リトライ仕様

アップロード失敗時は再試行可能。

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

ノート編集は単一フィールドの更新のため、通常のトランザクションで実行。

## パフォーマンス要件

- ノート取得：50ms以内
- ノート更新：100ms以内
- 画像アップロード：ファイルサイズ依存

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

- 認証済みユーザーのみ画像アップロード可能
- アップロード画像は画像形式のみに制限
- ノート編集は対象オブジェクトの変更権限が必要

## 備考

- フロントエンドでMarkdownのプレビュー表示をサポート
- 画像はMarkdown記法でノートに埋め込み可能

---

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

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

### 推奨読解順序

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

メモ用画像のデータモデルを理解する。

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

**読解のコツ**:
- `image`フィールドがImageFieldで画像ファイルを保存
- `user`フィールドでアップロードユーザーを記録
- `date`フィールドがauto_now_addで日時自動記録
- `model_type`と`model_id`で対象オブジェクトとの関連付け（任意）

#### Step 2: APIエンドポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | api.py | `src/backend/InvenTree/common/api.py` | NotesImageListクラス（459-474行目） |

**主要処理フロー**:
- `get_queryset()`: 全画像を返却
- `perform_create()`: upload_userの自動設定

#### Step 3: シリアライザを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | serializers.py | `src/backend/InvenTree/common/serializers.py` | NotesImageSerializerクラス（387-398行目） |

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

```
NotesImageList.create()
    │
    ├─ NotesImageSerializer.is_valid()
    │      │
    │      └─ InvenTreeImageSerializerField
    │             └─ 画像バリデーション
    │
    └─ perform_create()
           │
           ├─ serializer.save()
           │      │
           │      └─ NotesImage.save()
           │             │
           │             └─ rename_notes_image()
           │                    └─ ファイルパス生成
           │
           └─ image.user = request.user
                  └─ ユーザー記録
```

### データフロー図

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

multipart/form  ───▶ NotesImageList       ───▶ JSON Response
  image: (file)       POST                     pk, image URL
  model_type:
  model_id:               │
                          ▼
                   画像バリデーション
                          │
                          ▼                   [ストレージ]
                   ファイル保存        ───▶ notes_files/
                          │                   {model_type}/{model_id}/
                          ▼
                   DBレコード作成      ───▶ common_notesimage
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| models.py | `src/backend/InvenTree/common/models.py` | ソース | NotesImageモデル |
| api.py | `src/backend/InvenTree/common/api.py` | ソース | NotesImageList API |
| serializers.py | `src/backend/InvenTree/common/serializers.py` | ソース | NotesImageSerializer |
| validators.py | `src/backend/InvenTree/common/validators.py` | ソース | validate_notes_model_type |
