# 機能設計書 1-部品カテゴリ管理

## 概要

本ドキュメントは、InvenTreeシステムにおける部品カテゴリ管理機能の設計を記述する。部品カテゴリは部品を階層的に組織化するためのコア機能であり、効率的な部品検索と在庫管理の基盤となる。

### 本機能の処理概要

**業務上の目的・背景**：
製造業や在庫管理において、膨大な数の部品を効率的に管理するためには、論理的な分類体系が不可欠である。部品カテゴリ管理機能は、部品をツリー構造で階層化し、デフォルトの保管場所やキーワードを設定することで、部品の検索性向上と在庫管理の効率化を実現する。これにより、部品の探索時間短縮、在庫配置の最適化、新規部品登録時の分類作業の標準化が可能となる。

**機能の利用シーン**：
- 新規部品の登録時に、適切なカテゴリを選択・割り当てる場面
- 部品を検索する際に、カテゴリツリーを辿って目的の部品群を絞り込む場面
- カテゴリ単位でデフォルトの保管場所を設定し、在庫配置ルールを標準化する場面
- カテゴリに紐づくパラメータテンプレートを設定し、部品の仕様入力を効率化する場面
- ユーザーが特定のカテゴリを購読し、変更通知を受け取る場面

**主要な処理内容**：
1. カテゴリの作成・編集・削除（階層構造の維持）
2. カテゴリに属する部品の一覧取得と件数集計
3. デフォルト保管場所・キーワードの設定
4. パラメータテンプレートの関連付け
5. ユーザーの購読（スター）管理
6. 構造的カテゴリ（部品を直接配置不可）の設定

**関連システム・外部連携**：
- StockLocation（在庫ロケーション）との連携によるデフォルト保管場所設定
- ParameterTemplate（パラメータテンプレート）との連携
- ユーザー通知システムとの連携（購読機能）

**権限による制御**：
- カテゴリの閲覧は一般ユーザーでも可能
- カテゴリの作成・編集・削除にはpart.change_partcategory権限が必要
- 管理者はすべてのカテゴリ操作が可能

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 13 | 部品カテゴリ一覧・詳細画面 | 主機能 | 部品カテゴリの一覧表示、編集、削除処理 |
| 14 | 部品詳細画面 | 参照画面 | カテゴリ内部品一覧から部品詳細への遷移 |

## 機能種別

CRUD操作 / 階層データ管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | string | Yes | カテゴリ名 | 最大100文字、空文字不可 |
| parent | integer | No | 親カテゴリID | 有効なPartCategoryのID |
| description | string | No | カテゴリ説明 | 最大250文字 |
| default_location | integer | No | デフォルト保管場所ID | 有効なStockLocationのID |
| default_keywords | string | No | デフォルトキーワード | 最大250文字 |
| structural | boolean | No | 構造的カテゴリフラグ | 既存部品がある場合はtrue設定不可 |
| icon | string | No | アイコン | 最大100文字、バリデーション済みアイコン形式 |

### 入力データソース

- 画面入力（カテゴリ作成・編集フォーム）
- REST API（api-part-category-list）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| pk | integer | カテゴリの主キー |
| name | string | カテゴリ名 |
| pathstring | string | 階層パス文字列 |
| description | string | 説明 |
| parent | integer | 親カテゴリID |
| level | integer | 階層レベル |
| part_count | integer | 含まれる部品数 |
| default_location | integer | デフォルト保管場所ID |
| default_keywords | string | デフォルトキーワード |
| structural | boolean | 構造的カテゴリフラグ |
| icon | string | アイコン |
| starred | boolean | ユーザーの購読状態 |

### 出力先

- 画面表示（カテゴリツリー、カテゴリ詳細）
- REST API レスポンス

## 処理フロー

### 処理シーケンス

```
1. カテゴリ作成
   └─ 親カテゴリの検証 → バリデーション実行 → MPTT構造更新 → DB保存

2. カテゴリ編集
   └─ 構造的フラグ変更時の部品存在チェック → バリデーション → 保存

3. カテゴリ削除
   ├─ delete_child_categories=True の場合
   │      └─ 子カテゴリも再帰的に削除
   └─ delete_parts=True の場合
          └─ 配下の部品も削除

4. 部品数取得
   └─ cascade=True でサブカテゴリを含む集計 / False で直下のみ
```

### フローチャート

```mermaid
flowchart TD
    A[カテゴリ操作開始] --> B{操作種別}
    B -->|作成| C[親カテゴリ検証]
    C --> D[バリデーション実行]
    D --> E[MPTT構造更新]
    E --> F[DB保存]

    B -->|編集| G{structural変更?}
    G -->|Yes| H{配下に部品あり?}
    H -->|Yes| I[ValidationError]
    H -->|No| D
    G -->|No| D

    B -->|削除| J{削除オプション確認}
    J --> K[子カテゴリ処理]
    K --> L[配下部品処理]
    L --> M[MPTT構造更新]
    M --> N[DB削除]

    F --> O[終了]
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 構造的カテゴリ制約 | 構造的カテゴリには部品を直接配置できない | structural=True のカテゴリ |
| BR-002 | 既存部品制約 | 部品が既に配置されているカテゴリはstructural=Trueに変更不可 | partcount > 0 の場合 |
| BR-003 | 階層継承 | デフォルトロケーションは親カテゴリから継承可能 | 自身にdefault_locationが未設定の場合 |
| BR-004 | 購読継承 | 親カテゴリの購読者は子カテゴリの変更通知も受け取る | include_parents=True |

### 計算ロジック

```python
# 部品数の計算（cascade=True の場合）
def partcount(self, cascade=True, active=False):
    query = self.get_parts(cascade=cascade)
    if active:
        query = query.filter(active=True)
    return query.count()

# アイコン取得ロジック
@property
def icon(self):
    if self._icon:
        return self._icon
    if default_icon := get_global_setting('PART_CATEGORY_DEFAULT_ICON', cache=True):
        return default_icon
    return ''
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| カテゴリ作成 | part_partcategory | INSERT | 新規カテゴリレコード挿入 |
| カテゴリ編集 | part_partcategory | UPDATE | カテゴリ情報更新 |
| カテゴリ削除 | part_partcategory | DELETE | カテゴリレコード削除 |
| 購読追加 | part_partcategorystar | INSERT | ユーザー購読レコード挿入 |
| 購読解除 | part_partcategorystar | DELETE | ユーザー購読レコード削除 |
| パラメータテンプレート関連付け | part_partcategoryparametertemplate | INSERT/UPDATE/DELETE | テンプレート関連操作 |

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

#### part_partcategory

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name, description, parent_id, default_location_id, default_keywords, structural, icon, lft, rght, tree_id, level | フォーム入力値、MPTT自動計算値 | MPTTによる階層管理 |
| UPDATE | 上記カラム | フォーム入力値 | structuralの変更は部品存在チェック後 |
| DELETE | - | pk指定 | MPTT構造の再構築を伴う |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ValidationError | バリデーションエラー | 構造的カテゴリに部品が存在する状態でstructural=Trueに変更 | エラーメッセージ表示、変更を拒否 |
| ValidationError | バリデーションエラー | 親カテゴリに自身を指定（循環参照） | エラーメッセージ表示 |
| IntegrityError | 整合性エラー | 重複するカテゴリ名（同一階層内） | エラーメッセージ表示 |

### リトライ仕様

特になし（トランザクション管理による整合性確保）

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

- カテゴリ削除時はtransaction.atomic()内で実行
- MPTT構造の更新は自動的にトランザクション管理される
- 子カテゴリ・部品の一括削除は単一トランザクション内で実行

## パフォーマンス要件

- カテゴリツリーの取得: 1000カテゴリで1秒以内
- 部品数集計: cascade=True でも2秒以内
- MPTTによる効率的な階層クエリを活用

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

- アイコンフィールドはvalidate_iconバリデータで検証
- ユーザー権限に基づくアクセス制御
- APIエンドポイントは認証必須

## 備考

- MPTTライブラリ（django-mptt）を使用した階層構造管理
- パス文字列（pathstring）はInvenTreeTreeモデルで自動生成

---

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

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

### 推奨読解順序

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

まず、PartCategoryモデルの構造とMPTT階層管理の仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | models.py | `src/backend/InvenTree/part/models.py` | PartCategoryクラスの定義（71-333行目） |
| 1-2 | models.py | `src/backend/InvenTree/InvenTree/models.py` | InvenTreeTreeベースクラスの理解 |

**読解のコツ**:
- PartCategoryはInvenTreeTreeを継承しており、MPTTによる階層管理機能を持つ
- `ITEM_PARENT_KEY = 'category'` は部品との関連を定義
- `TreeForeignKey` はMPTT用の外部キー

**主要処理フロー**:
- **71-76行目**: クラス定義とミックスイン継承
- **96-104行目**: deleteメソッドのオーバーライド（子カテゴリ・部品の処理オプション）
- **106-114行目**: default_locationフィールド定義（StockLocationへの外部キー）
- **116-123行目**: structuralフィールド（構造的カテゴリフラグ）
- **143-163行目**: iconプロパティ（デフォルトアイコンのフォールバック処理）
- **174-186行目**: cleanメソッド（構造的カテゴリの部品存在チェック）
- **188-205行目**: get_partsメソッド（配下部品の取得、cascade対応）

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

APIエンドポイントとシリアライザを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | api.py | `src/backend/InvenTree/part/api.py` | CategoryListとCategoryDetailビュー |
| 2-2 | serializers.py | `src/backend/InvenTree/part/serializers.py` | PartCategorySerializerの定義 |

**主要処理フロー**:
- APIエンドポイント `api-part-category-list` がPartCategoryのCRUD操作を処理
- シリアライザがモデルとJSONの変換を担当

#### Step 3: パラメータテンプレート関連を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | models.py | `src/backend/InvenTree/part/models.py` | PartCategoryParameterTemplateクラス（351-428行目） |

**主要処理フロー**:
- **351-360行目**: クラス定義とドキュメント
- **384-407行目**: cleanメソッド（デフォルト値のバリデーション）
- **409-428行目**: フィールド定義（category, template, default_value）

#### Step 4: 購読機能を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | models.py | `src/backend/InvenTree/part/models.py` | get_subscribers, is_starred_by, set_starredメソッド（293-332行目） |
| 4-2 | models.py | `src/backend/InvenTree/part/models.py` | PartCategoryStarクラス（3597-3622行目） |

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

```
REST API Request
    │
    ├─ PartCategoryList (api.py)
    │      ├─ PartCategorySerializer
    │      │      └─ PartCategory.save()
    │      │             ├─ clean()
    │      │             │      └─ partcount() - 部品存在チェック
    │      │             └─ super().save() - MPTT更新
    │      │
    │      └─ PartCategory.delete()
    │             └─ super().delete() - 子カテゴリ・部品処理
    │
    └─ PartCategoryDetail (api.py)
           └─ 同上
```

### データフロー図

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

フォーム入力 ───▶ PartCategorySerializer ───▶ JSONレスポンス
                        │
                        ▼
                 PartCategory.clean()
                        │
                        ▼
                 PartCategory.save()
                        │
                        ▼
                 part_partcategory テーブル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| models.py | `src/backend/InvenTree/part/models.py` | ソース | PartCategory, PartCategoryParameterTemplate, PartCategoryStarモデル定義 |
| api.py | `src/backend/InvenTree/part/api.py` | ソース | REST APIビュー定義 |
| serializers.py | `src/backend/InvenTree/part/serializers.py` | ソース | シリアライザ定義 |
| models.py | `src/backend/InvenTree/InvenTree/models.py` | ソース | InvenTreeTreeベースクラス |
| CategoryDetail.tsx | `src/frontend/src/pages/part/CategoryDetail.tsx` | ソース | フロントエンド詳細画面 |
| admin.py | `src/backend/InvenTree/part/admin.py` | ソース | 管理画面設定 |
