# 機能設計書 47-添付ファイル管理

## 概要

本ドキュメントは、InvenTreeシステムにおける添付ファイル管理機能の設計仕様を定義する。この機能は、各種オブジェクト（部品、発注、在庫アイテム等）に対してファイルやリンクを添付・管理する。

### 本機能の処理概要

**業務上の目的・背景**：
在庫管理業務では、部品のデータシート、図面、仕様書、証明書など、様々なドキュメントを関連付けて管理する必要がある。本機能は、InvenTreeの各種オブジェクトにファイル（画像、PDF、CADファイル等）や外部URLリンクを添付し、関連情報へのアクセスを容易にする。これにより、部品情報と技術ドキュメントの一元管理が実現できる。

**機能の利用シーン**：
- 部品にデータシートPDFを添付する
- 在庫アイテムに検査証明書を添付する
- 発注書に契約書のリンクを追加する
- 製造指示に作業手順書を添付する

**主要な処理内容**：
1. ファイルアップロード（Attachmentモデル）
2. 外部URLリンクの登録
3. 添付ファイルの一覧取得・ダウンロード
4. 添付ファイルの削除
5. タグによる分類

**関連システム・外部連携**：
- ファイルストレージ（Djangoデフォルトストレージ）
- メディアURL配信

**権限による制御**：
- 添付ファイルの閲覧は対象オブジェクトの閲覧権限に依存
- 添付ファイルの追加・削除は対象オブジェクトの変更権限が必要

## 関連画面

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

## 機能種別

CRUD操作 / ファイル管理

## 入力仕様

### 入力パラメータ（ファイルアップロード）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| attachment | file | Yes（linkと排他） | アップロードファイル | ファイル拡張子チェック |
| link | string | Yes（attachmentと排他） | 外部URL | URL形式 |
| comment | string | No | コメント | 最大250文字 |
| model_type | string | Yes | 対象モデルタイプ | |
| model_id | integer | Yes | 対象モデルID | 正の整数 |

### 入力データソース

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

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| pk | integer | 添付ファイルID |
| attachment | string | ファイルパス |
| link | string | 外部URL |
| comment | string | コメント |
| upload_user | object | アップロードユーザー |
| upload_date | date | アップロード日 |
| file_size | integer | ファイルサイズ（バイト） |

### 出力先

- APIレスポンス（JSON形式）
- 詳細画面の添付ファイル一覧

## 処理フロー

### 処理シーケンス

```
1. 添付ファイルアップロードリクエスト
   └─ POST /api/attachment/
2. 権限チェック
   └─ 対象モデルの変更権限確認
3. ファイルバリデーション
   └─ 拡張子、サイズチェック
4. ファイル保存
   └─ メディアストレージに保存
5. Attachmentレコード作成
   └─ common_attachment テーブルにINSERT
```

### フローチャート

```mermaid
flowchart TD
    A[アップロードリクエスト] --> B{file or link?}
    B -->|file| C[ファイルバリデーション]
    B -->|link| D[URLバリデーション]
    C --> E{検証OK?}
    D --> E
    E -->|No| F[エラーレスポンス]
    E -->|Yes| G[権限チェック]
    G --> H{権限OK?}
    H -->|No| I[403エラー]
    H -->|Yes| J[ファイル保存]
    J --> K[DBレコード作成]
    K --> L[レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-47-01 | ファイル/リンク排他 | attachmentとlinkは同時に設定不可 | 添付作成・更新時 |
| BR-47-02 | 拡張子制限 | 許可されたファイル拡張子のみアップロード可能 | ファイルアップロード時 |
| BR-47-03 | モデル権限連動 | 添付の権限は対象モデルの権限に連動 | 全ての添付操作 |
| BR-47-04 | ユーザー記録 | アップロードユーザーを自動記録 | ファイルアップロード時 |

### 計算ロジック

ファイル名の正規化：
```python
def rename_attachment(instance, filename):
    path = f'attachment_files/{instance.model_type}/{instance.model_id}/'
    return path + filename
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 添付一覧取得 | common_attachment | SELECT | モデルの添付ファイル取得 |
| 添付作成 | common_attachment | INSERT | 新規添付レコード作成 |
| 添付更新 | common_attachment | UPDATE | コメント等の更新 |
| 添付削除 | common_attachment | DELETE | 添付レコード削除 |

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

#### common_attachment

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | model_type | ContentType FK | 対象モデルタイプ |
| INSERT | model_id | 対象オブジェクトID | |
| INSERT | attachment | ファイルパス | メディアストレージ |
| INSERT | link | 外部URL | attachmentと排他 |
| INSERT | comment | ユーザー入力 | 最大250文字 |
| INSERT | upload_user | 現在ユーザー | ForeignKey |
| INSERT | upload_date | 現在日付 | auto_now_add |
| INSERT | file_size | ファイルサイズ | バイト単位 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 400 | ValidationError | 無効なファイル形式 | 許可された拡張子のファイルを使用 |
| 400 | ValidationError | ファイルサイズ超過 | ファイルサイズを削減 |
| 403 | PermissionDenied | 対象モデルの変更権限なし | 管理者に権限付与を依頼 |
| 404 | NotFound | 対象モデルが存在しない | 正しいモデルIDを指定 |

### リトライ仕様

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

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

ファイルアップロードとDBレコード作成は非トランザクション（ファイル保存はストレージ依存）。ファイル保存後にDBエラーが発生した場合、孤立ファイルが残る可能性あり。

## パフォーマンス要件

- ファイルアップロード：ファイルサイズ依存
- 添付一覧取得：100ms以内

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

- アップロードファイルの拡張子チェック必須
- SVGファイルはサニタイズ処理
- ファイルパスはUUID等で難読化を検討
- 対象モデルの権限チェック必須

## 備考

- タグ管理（TaggableManager）をサポート
- fully_qualified_url()でフルURLを取得可能

---

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

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

### 推奨読解順序

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

添付ファイルのデータモデルを理解する。

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

**読解のコツ**:
- `model_type`と`model_id`でGenericForeignKey（ポリモーフィック）
- `attachment`と`link`は排他（一方のみ設定可能）
- `rename_attachment()`でファイルパスを生成
- `clean()`でファイル/リンクの排他バリデーション
- `fully_qualified_url()`でフルURL取得

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

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

**主要処理フロー**:
- `AttachmentList.get_queryset()`: モデルタイプでフィルタ
- `AttachmentList.perform_create()`: upload_userの自動設定
- `AttachmentDetail.check_object_permissions()`: モデル権限チェック

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

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

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

```
AttachmentList.create()
    │
    ├─ AttachmentSerializer.is_valid()
    │      │
    │      ├─ ファイルバリデーション
    │      │      └─ 拡張子チェック
    │      │
    │      └─ model_type/model_id検証
    │
    ├─ check_object_permissions()
    │      └─ 対象モデルの変更権限チェック
    │
    └─ perform_create()
           │
           ├─ upload_user設定
           │
           └─ Attachment.save()
                  │
                  ├─ rename_attachment()
                  │      └─ ファイルパス生成
                  │
                  └─ default_storage.save()
```

### データフロー図

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

multipart/form  ───▶ AttachmentList       ───▶ JSON Response
  attachment:          POST                     pk, attachment, etc.
  (file)
  model_type:             │
  model_id:               ▼
                   バリデーション
                         │
                         ▼
                   権限チェック
                         │
                         ▼                    [ストレージ]
                   ファイル保存        ───▶ attachment_files/
                         │                    {model_type}/{model_id}/
                         ▼
                   DBレコード作成      ───▶ common_attachment
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| models.py | `src/backend/InvenTree/common/models.py` | ソース | Attachmentモデル |
| api.py | `src/backend/InvenTree/common/api.py` | ソース | 添付ファイルAPI |
| serializers.py | `src/backend/InvenTree/common/serializers.py` | ソース | 添付ファイルシリアライザ |
| validators.py | `src/backend/InvenTree/common/validators.py` | ソース | ファイル拡張子バリデーション |
