# 機能設計書: 製造元部品管理

## 1. 機能概要

### 1.1 機能の目的
製造元部品管理機能は、部品の製造元情報を管理するための機能である。内部部品（Part）と製造元固有の情報（MPN: Manufacturer Part Number）を紐付け、部品のトレーサビリティと調達業務を支援する。

### 1.2 機能の範囲
- 製造元部品の登録・更新・削除・参照
- MPN（製造元品番）管理
- 製造元部品とサプライヤー部品の紐付け
- 製造元部品のフィルタリング・検索

### 1.3 関連画面
| 画面ID | 画面名 | 関連操作 |
|--------|--------|----------|
| SCR-MANUFACTURERPART-LIST | 製造元部品一覧 | 検索・フィルタリング |
| SCR-MANUFACTURERPART-DETAIL | 製造元部品詳細 | 編集・削除 |
| SCR-PART-DETAIL | 部品詳細 | 製造元部品の参照 |

## 2. 機能仕様

### 2.1 製造元部品のデータ項目

| フィールド名 | 型 | 必須 | 説明 |
|-------------|------|------|------|
| part | ForeignKey | Yes | 内部部品への参照 |
| manufacturer | ForeignKey | Yes | 製造元（is_manufacturer=True）への参照 |
| MPN | String | Yes | 製造元品番（Manufacturer Part Number） |
| description | String | No | 説明 |
| link | URL | No | データシート等へのリンク |
| tags | TaggableManager | No | タグ |

### 2.2 製造元部品一覧API

#### 2.2.1 エンドポイント
- **URL**: `GET /api/company/part/manufacturer/`
- **メソッド**: GET（一覧取得）, POST（新規作成）, DELETE（一括削除）
- **シリアライザ**: `ManufacturerPartSerializer`

#### 2.2.2 フィルタパラメータ
| パラメータ名 | 型 | 説明 |
|-------------|------|------|
| manufacturer | Integer | 製造元ID |
| MPN | String | 製造元品番 |
| part | Integer | 内部部品ID |
| part_active | Boolean | 内部部品が有効/無効 |
| manufacturer_active | Boolean | 製造元が有効/無効 |
| tags__name | String | タグ名 |
| tags__slug | String | タグスラッグ |

#### 2.2.3 検索フィールド
- manufacturer__name
- description
- MPN
- part__IPN
- part__name
- part__description
- tags__name
- tags__slug

### 2.3 出力オプション

`ManufacturerOutputOptions`により以下の詳細情報を選択的に含めることが可能：

| オプション | 説明 |
|-----------|------|
| part_detail | 内部部品の詳細情報 |
| manufacturer_detail | 製造元の詳細情報 |
| pretty | 読みやすい形式での出力 |

### 2.4 サプライヤー部品との関係

製造元部品は複数のサプライヤー部品と紐付け可能。これにより、同一の製造元部品を複数のサプライヤーから調達できる。

```
ManufacturerPart (1) ←── (N) SupplierPart
```

## 3. データモデル

### 3.1 ManufacturerPartモデル
```python
class ManufacturerPart(InvenTree.models.InvenTreeMetadataModel):
    part = models.ForeignKey(
        'part.Part',
        on_delete=models.CASCADE,
        related_name='manufacturer_parts',
        ...
    )
    manufacturer = models.ForeignKey(
        'Company',
        on_delete=models.CASCADE,
        limit_choices_to={'is_manufacturer': True},
        related_name='manufactured_parts',
        ...
    )
    MPN = models.CharField(max_length=100, ...)
    description = models.CharField(max_length=250, blank=True)
    link = models.URLField(blank=True)
    tags = TaggableManager(blank=True)
```

### 3.2 関連エンティティ
```
ManufacturerPart
├── Part (内部部品: N:1)
├── Company (製造元: N:1, is_manufacturer=True)
└── SupplierPart (サプライヤー部品: 1:N)
```

## 4. API仕様

### 4.1 一覧取得
```
GET /api/company/part/manufacturer/
```

### 4.2 詳細情報付き一覧取得
```
GET /api/company/part/manufacturer/?part_detail=true&manufacturer_detail=true
```

### 4.3 製造元でフィルタリング
```
GET /api/company/part/manufacturer/?manufacturer=1
```

### 4.4 有効な部品のみ
```
GET /api/company/part/manufacturer/?part_active=true
```

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

### 5.1 推奨読解順序

1. **モデル定義**
   - `src/backend/InvenTree/company/models.py`
     - **ManufacturerPart**: 製造元部品モデル

2. **フィルタ定義**
   - `src/backend/InvenTree/company/api.py`
     - **130-146行目**: `ManufacturerPartFilter` - フィルタ定義
     - **140-142行目**: `part_active` - 部品有効フィルタ
     - **144-146行目**: `manufacturer_active` - 製造元有効フィルタ

3. **出力オプション**
   - `src/backend/InvenTree/company/api.py`
     - **149-168行目**: `ManufacturerOutputOptions` - 出力オプション定義

4. **APIエンドポイント**
   - `src/backend/InvenTree/company/api.py`
     - **171-184行目**: `ManufacturerPartMixin` - 共通クエリセット
     - **186-212行目**: `ManufacturerPartList` - 一覧API
     - **215-223行目**: `ManufacturerPartDetail` - 詳細API
     - **479-493行目**: `manufacturer_part_api_urls` - URLルーティング

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

```
[API Request: GET /api/company/part/manufacturer/]
    │
    ▼
ManufacturerPartList.get()
    │
    ├── ManufacturerPartMixin.get_queryset() [177-183行目]
    │   └── prefetch_related('supplier_parts')
    │
    ├── ManufacturerPartFilter [130-146行目]
    │   ├── part_active フィルタ
    │   └── manufacturer_active フィルタ
    │
    └── ManufacturerPartSerializer.to_representation()
        └── 出力オプションに応じた詳細情報付与
```

### 5.3 データフロー図

```
[製造元部品登録]
    │
    ▼
┌─────────────────────────────────────┐
│ ManufacturerPartSerializer          │
│ ・part: 内部部品ID                 │
│ ・manufacturer: 製造元ID           │
│ ・MPN: 製造元品番                  │
│ ・description: 説明                │
└─────────────────────────────────────┘
    │
    ├── バリデーション
    │   ├── 製造元がis_manufacturer=True
    │   └── MPNの一意性（manufacturer+MPN）
    │
    ▼
┌─────────────────────────────────────┐
│ ManufacturerPart Model              │
│ ・データベースへの永続化           │
└─────────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────────┐
│ 関連エンティティ                    │
│ ・Part.manufacturer_parts（逆参照）│
│ ・Company.manufactured_parts       │
│ ・SupplierPart.manufacturer_part   │
└─────────────────────────────────────┘
```

### 5.4 関連ファイル一覧

| ファイルパス | 種別 | 役割 |
|-------------|------|------|
| `src/backend/InvenTree/company/models.py` | Model | ManufacturerPartモデル定義 |
| `src/backend/InvenTree/company/serializers.py` | Serializer | ManufacturerPartSerializer定義 |
| `src/backend/InvenTree/company/api.py` | API | RESTful APIエンドポイント定義 |
| `src/backend/InvenTree/part/models.py` | Model | Part（内部部品）モデル定義 |

## 6. 例外処理

### 6.1 バリデーションエラー
| エラー条件 | エラーメッセージ |
|-----------|-----------------|
| partが未指定 | "This field is required" |
| manufacturerが未指定 | "This field is required" |
| MPNが未指定 | "This field is required" |
| manufacturerがis_manufacturer=False | "Company is not a manufacturer" |
| MPNが重複（同一manufacturer内） | "MPN already exists for this manufacturer" |

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

- APIアクセスには認証が必要
- 製造元部品の変更は適切な権限を持つユーザーのみ可能
