# 機能設計書: サプライヤー部品管理

## 1. 機能概要

### 1.1 機能の目的
サプライヤー部品管理機能は、サプライヤーから供給される部品情報を管理するための機能である。内部部品（Part）とサプライヤー固有の情報（SKU、価格等）を紐付け、調達業務を支援する。

### 1.2 機能の範囲
- サプライヤー部品の登録・更新・削除・参照
- SKU（サプライヤー品番）管理
- 価格ブレイク（数量割引）管理
- 在庫状況の追跡
- サプライヤー部品のフィルタリング・検索

### 1.3 関連画面
| 画面ID | 画面名 | 関連操作 |
|--------|--------|----------|
| SCR-SUPPLIERPART-LIST | サプライヤー部品一覧 | 検索・フィルタリング |
| SCR-SUPPLIERPART-DETAIL | サプライヤー部品詳細 | 編集・削除 |
| SCR-PART-DETAIL | 部品詳細 | サプライヤー部品の参照 |

## 2. 機能仕様

### 2.1 サプライヤー部品のデータ項目

| フィールド名 | 型 | 必須 | 説明 |
|-------------|------|------|------|
| part | ForeignKey | Yes | 内部部品への参照 |
| supplier | ForeignKey | Yes | サプライヤー（is_supplier=True）への参照 |
| SKU | String | Yes | サプライヤー品番 |
| manufacturer_part | ForeignKey | No | 製造元部品への参照 |
| description | String | No | 説明 |
| link | URL | No | 製品ページへのリンク |
| note | Text | No | 備考 |
| pack_quantity | Decimal | No | パック数量 |
| packaging | String | No | 包装形態 |
| active | Boolean | No | 有効フラグ（デフォルト: true） |
| tags | TaggableManager | No | タグ |

### 2.2 サプライヤー部品一覧API

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

#### 2.2.2 フィルタパラメータ
| パラメータ名 | 型 | 説明 |
|-------------|------|------|
| supplier | Integer | サプライヤーID |
| part | Integer | 内部部品ID |
| manufacturer_part | Integer | 製造元部品ID |
| SKU | String | サプライヤー品番 |
| active | Boolean | 有効/無効 |
| part_active | Boolean | 内部部品が有効/無効 |
| supplier_active | Boolean | サプライヤーが有効/無効 |
| MPN | String | 製造元品番（manufacturer_part経由） |
| manufacturer | Integer | 製造元ID（manufacturer_part経由） |
| company | Integer | 会社ID（サプライヤーまたは製造元） |
| has_stock | Boolean | 在庫あり/なし |
| tags__name | String | タグ名 |
| tags__slug | String | タグスラッグ |

#### 2.2.3 検索フィールド
- SKU
- supplier__name
- manufacturer_part__manufacturer__name
- description
- manufacturer_part__MPN
- part__IPN, part__name, part__description, part__keywords
- tags__name, tags__slug

#### 2.2.4 ソートフィールド
- SKU
- part
- supplier
- manufacturer
- active
- MPN
- packaging
- pack_quantity
- in_stock
- updated

### 2.3 出力オプション

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

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

### 2.4 価格ブレイク管理

#### 2.4.1 データ項目
| フィールド名 | 型 | 必須 | 説明 |
|-------------|------|------|------|
| part | ForeignKey | Yes | サプライヤー部品への参照 |
| quantity | Decimal | Yes | 適用数量 |
| price | Decimal | Yes | 単価 |
| price_currency | String | No | 通貨コード |

#### 2.4.2 価格ブレイクAPI
- **一覧**: `GET /api/company/price-break/`
- **詳細**: `GET /api/company/price-break/{pk}/`

## 3. データモデル

### 3.1 SupplierPartモデル
```python
class SupplierPart(InvenTree.models.InvenTreeBarcodeMixin):
    part = models.ForeignKey('part.Part', ...)
    supplier = models.ForeignKey('company.Company', ...)
    SKU = models.CharField(max_length=100, ...)
    manufacturer_part = models.ForeignKey(
        'ManufacturerPart',
        related_name='supplier_parts',
        ...
    )
    description = models.CharField(...)
    link = models.URLField(...)
    note = models.TextField(...)
    pack_quantity = models.DecimalField(...)
    packaging = models.CharField(...)
    active = models.BooleanField(default=True)
```

### 3.2 SupplierPriceBreakモデル
```python
class SupplierPriceBreak(InvenTree.models.InvenTreeModel):
    part = models.ForeignKey('SupplierPart', ...)
    quantity = models.DecimalField(...)
    price = InvenTreeModelMoneyField(...)
```

### 3.3 関連エンティティ
```
SupplierPart
├── Part (内部部品: N:1)
├── Company (サプライヤー: N:1, is_supplier=True)
├── ManufacturerPart (製造元部品: N:1, optional)
├── SupplierPriceBreak (価格ブレイク: 1:N)
└── StockItem (在庫品目: 1:N)
```

## 4. API仕様

### 4.1 一覧取得（詳細情報あり）
```
GET /api/company/part/?part_detail=true&supplier_detail=true
```

### 4.2 会社によるフィルタリング
```
GET /api/company/part/?company=1
```
※ サプライヤーまたは製造元のいずれかにマッチ

### 4.3 在庫ありでフィルタリング
```
GET /api/company/part/?has_stock=true
```

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

### 5.1 推奨読解順序

1. **モデル定義**
   - `src/backend/InvenTree/company/models.py`
     - **SupplierPart**: サプライヤー部品モデル
     - **SupplierPriceBreak**: 価格ブレイクモデル

2. **フィルタ定義**
   - `src/backend/InvenTree/company/api.py`
     - **226-288行目**: `SupplierPartFilter` - フィルタ定義
     - **273-277行目**: `filter_company()` - 会社フィルタ
     - **283-288行目**: `filter_has_stock()` - 在庫フィルタ

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

4. **APIエンドポイント**
   - `src/backend/InvenTree/company/api.py`
     - **323-336行目**: `SupplierPartMixin` - 共通クエリセット
     - **339-389行目**: `SupplierPartList` - 一覧API
     - **392-403行目**: `SupplierPartDetail` - 詳細API
     - **496-506行目**: `supplier_part_api_urls` - URLルーティング

5. **価格ブレイクAPI**
   - `src/backend/InvenTree/company/api.py`
     - **405-423行目**: `SupplierPriceBreakFilter`
     - **449-472行目**: `SupplierPriceBreakList`
     - **475-476行目**: `SupplierPriceBreakDetail`

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

```
[API Request: GET /api/company/part/]
    │
    ▼
SupplierPartList.get()
    │
    ├── SupplierPartMixin.get_queryset() [329-336行目]
    │   └── SupplierPartSerializer.annotate_queryset()
    │       └── in_stockアノテーション等
    │
    ├── SupplierPartFilter [226-288行目]
    │   ├── filter_company() - 会社フィルタ
    │   └── filter_has_stock() - 在庫フィルタ
    │
    └── SupplierPartSerializer.to_representation()
        └── 出力オプションに応じた詳細情報付与
```

### 5.3 データフロー図

```
[サプライヤー部品登録]
    │
    ▼
┌─────────────────────────────────────┐
│ SupplierPartSerializer              │
│ ・part: 内部部品ID                 │
│ ・supplier: サプライヤーID         │
│ ・SKU: サプライヤー品番            │
│ ・manufacturer_part: 製造元部品ID  │
└─────────────────────────────────────┘
    │
    ├── バリデーション
    │   ├── サプライヤーがis_supplier=True
    │   └── SKUの一意性（supplier+SKU）
    │
    ▼
┌─────────────────────────────────────┐
│ SupplierPart Model                  │
│ ・データベースへの永続化           │
└─────────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────────┐
│ 関連エンティティ                    │
│ ・Part.supplier_parts（逆参照）    │
│ ・Company.supplier_parts（逆参照） │
└─────────────────────────────────────┘
```

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

| ファイルパス | 種別 | 役割 |
|-------------|------|------|
| `src/backend/InvenTree/company/models.py` | Model | SupplierPart, SupplierPriceBreakモデル定義 |
| `src/backend/InvenTree/company/serializers.py` | Serializer | SupplierPartSerializer定義 |
| `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" |
| supplierが未指定 | "This field is required" |
| SKUが未指定 | "This field is required" |
| supplierがis_supplier=False | "Company is not a supplier" |
| SKUが重複（同一supplier内） | "SKU already exists for this supplier" |

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

- APIアクセスには認証が必要
- サプライヤー部品の変更は適切な権限を持つユーザーのみ可能
- データエクスポート機能は権限制御される
