# 機能設計書 41-製造元パーツ詳細表示

## 概要

本ドキュメントは、InvenTreeアプリにおける製造元パーツ（ManufacturerPart）の詳細情報を表示する機能の設計を記述する。

### 本機能の処理概要

製造元パーツ詳細表示機能は、特定の製造元パーツインスタンスの詳細情報をユーザーに提示する機能である。製造元パーツは、製造元（メーカー）が製造する部品の情報を管理するためのエンティティであり、InvenTree内部のパーツと製造元情報を紐付ける役割を持つ。

**業務上の目的・背景**：製造業や在庫管理において、部品は複数の製造元から供給されることがある。同一の部品でも製造元によって品番（MPN: Manufacturer Part Number）が異なる場合があり、これらの情報を正確に管理することは、調達・品質管理・トレーサビリティの観点から重要である。本機能は、製造元固有の情報を一元的に確認できる画面を提供することで、業務効率の向上に寄与する。

**機能の利用シーン**：
- サプライヤーから部品を調達する際に、製造元情報とMPNを確認する場面
- 品質問題が発生した際に、特定の製造元の部品を追跡する場面
- 新規部品の登録時に、既存の製造元パーツ情報を参照する場面
- バーコードスキャンにより製造元パーツを特定した後、詳細を確認する場面

**主要な処理内容**：
1. 製造元パーツデータのサーバーからの読み込み・再読み込み
2. 関連するパラメータ数および添付ファイル数のカウント取得
3. 内部パーツ情報（部品名、サムネイル画像）の表示と詳細画面への遷移
4. 製造元会社情報（会社名、サムネイル画像）の表示と詳細画面への遷移
5. 製造元品番（MPN）、説明、外部リンクの表示
6. パラメータ一覧・添付ファイル一覧への遷移リンクの提供
7. 編集フォームの起動による製造元パーツ情報の更新

**関連システム・外部連携**：InvenTree REST API（company/part/manufacturer/エンドポイント）を使用してデータを取得・更新する。

**権限による制御**：canEdit属性に基づき、編集ボタンの表示/非表示を制御する。partロールが必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 31 | 会社詳細画面 | 遷移元画面 | 会社詳細から製造元パーツ一覧経由で遷移 |
| 22 | 部品詳細画面 | 遷移先画面 | 内部パーツタップで部品詳細へ遷移 |
| 5 | バーコードスキャン画面 | 遷移元画面 | バーコード照合成功時に製造元パーツ詳細へ遷移 |

## 機能種別

データ参照 / CRUD操作（Read, Update）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| manufacturerPart | InvenTreeManufacturerPart | Yes | 表示対象の製造元パーツインスタンス | pk > 0 |

### 入力データソース

- コンストラクタ引数として渡される`InvenTreeManufacturerPart`オブジェクト
- サーバーAPI（`company/part/manufacturer/{pk}/`）からの再読み込みデータ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 内部パーツ情報 | ListTile | パーツ名、サムネイル画像、タップで詳細遷移 |
| 製造元情報 | ListTile | 製造元会社名、サムネイル画像、タップで詳細遷移 |
| 製造元品番(MPN) | ListTile | 製造元が付与した品番 |
| 説明 | ListTile | 製造元パーツの説明文（空の場合は非表示） |
| 外部リンク | ListTile | 製造元のウェブサイト等へのリンク（存在する場合のみ） |
| パラメータ数 | ListTile | 関連パラメータの件数と一覧への遷移 |
| 添付ファイル数 | ListTile | 関連添付ファイルの件数と一覧への遷移 |

### 出力先

Flutter Widget（画面表示）

## 処理フロー

### 処理シーケンス

```
1. ウィジェット初期化
   └─ 製造元パーツインスタンスを受け取る

2. request()メソッド実行（画面表示時・リフレッシュ時）
   ├─ 製造元パーツデータの再読み込み
   │   └─ pkが0以下または再読み込み失敗時は前画面に戻る
   ├─ パラメータ数のカウント取得（非同期）
   │   └─ countParameters(MODEL_TYPE, pk)
   └─ 添付ファイル数のカウント取得（非同期）
       └─ countAttachments(MODEL_TYPE, pk)

3. 画面描画（getTiles）
   ├─ 内部パーツタイルの構築
   ├─ 製造元タイルの構築
   ├─ MPN（製造元品番）タイルの構築
   ├─ 説明タイルの構築（説明文が存在する場合のみ）
   ├─ 外部リンクタイルの構築（リンクが存在する場合のみ）
   ├─ パラメータタイルの構築
   └─ 添付ファイルタイルの構築

4. 編集操作（editManufacturerPart）
   ├─ 編集フォームの表示
   └─ 保存成功時に画面をリフレッシュ
```

### フローチャート

```mermaid
flowchart TD
    A[画面開始] --> B[request実行]
    B --> C{pk > 0 かつ reload成功?}
    C -->|No| D[前画面に戻る]
    C -->|Yes| E[パラメータ数取得]
    E --> F[添付ファイル数取得]
    F --> G[画面描画]
    G --> H{ユーザー操作}
    H -->|内部パーツタップ| I[パーツ取得]
    I --> J[パーツ詳細画面へ遷移]
    H -->|製造元タップ| K[会社取得]
    K --> L[会社詳細画面へ遷移]
    H -->|外部リンクタップ| M[外部ブラウザで開く]
    H -->|編集ボタンタップ| N[編集フォーム表示]
    N --> O{保存成功?}
    O -->|Yes| P[画面リフレッシュ]
    O -->|No| H
    P --> H
    H -->|パラメータタップ| Q[パラメータ一覧画面へ遷移]
    H -->|添付ファイルタップ| R[添付ファイル画面へ遷移]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-41-01 | 表示情報の条件付き表示 | 説明文と外部リンクは、値が存在する場合のみ表示する | 常時 |
| BR-41-02 | 編集権限チェック | canEdit属性がtrueの場合のみ編集ボタンを表示する | 常時 |
| BR-41-03 | 無効データ時の画面遷移 | pkが0以下またはreload失敗時は前画面に戻る | request実行時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 詳細表示 | ManufacturerPart | SELECT | 製造元パーツ情報の取得 |
| パラメータ数取得 | Parameter | SELECT | 関連パラメータのカウント |
| 添付ファイル数取得 | Attachment | SELECT | 関連添付ファイルのカウント |
| 編集保存 | ManufacturerPart | UPDATE | 製造元パーツ情報の更新 |

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

#### ManufacturerPart

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | pk, part, manufacturer, MPN, description, link | pk = 指定値 | 詳細取得 |
| UPDATE | manufacturer, MPN, link | フォーム入力値 | 編集時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| E-41-01 | データ取得エラー | 製造元パーツの再読み込み失敗 | 前画面に自動遷移 |
| E-41-02 | 関連データ取得エラー | パーツ/会社取得失敗 | タップ操作が無視される |
| E-41-03 | 更新エラー | 編集保存失敗 | スナックバーでエラー通知 |

### リトライ仕様

プルダウンリフレッシュにより手動リトライ可能

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

REST APIベースのため、各操作は独立したHTTPリクエストとして処理される。編集保存は単一のPUT/PATCHリクエストで完結する。

## パフォーマンス要件

- 画面初期表示: 2秒以内
- データ再読み込み: 1秒以内
- パラメータ数・添付ファイル数取得: 非同期並列実行により遅延を最小化

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

- 認証トークンを使用したAPIアクセス
- partロールの権限チェック
- canEdit属性による編集機能の制御

## 備考

- 将来的にバーコード関連アクション（barcodeButtons）の実装が予定されている（TODOコメントあり）
- MODEL_TYPE定数は"manufacturerpart"

---

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

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

### 推奨読解順序

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

製造元パーツのデータモデルを把握することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | company.dart | `lib/inventree/company.dart` | InvenTreeManufacturerPartクラスの定義（234-295行目）、MODEL_TYPE、formFields、プロパティアクセサを確認 |

**読解のコツ**: InvenTreeManufacturerPartはInvenTreeModelを継承しており、jsondata経由でサーバーレスポンスのフィールドにアクセスする。getString、getIntなどのヘルパーメソッドを使用している。

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

Widgetのエントリーポイントとなるクラス構成を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | manufacturer_part_detail.dart | `lib/widget/company/manufacturer_part_detail.dart` | StatefulWidgetとStateクラスの構成（23-233行目） |

**主要処理フロー**:
1. **23-32行目**: ManufacturerPartDetailWidgetクラス定義、コンストラクタでInvenTreeManufacturerPartを受け取る
2. **34-36行目**: _ManufacturerPartDisplayStateがRefreshableStateを継承
3. **45-80行目**: request()メソッドでデータ再読み込みとカウント取得

#### Step 3: データ取得処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | manufacturer_part_detail.dart | `lib/widget/company/manufacturer_part_detail.dart` | request()メソッドの実装 |

**主要処理フロー**:
- **45-53行目**: manufacturerPartのreload()呼び出し、失敗時はNavigator.pop()
- **55-66行目**: InvenTreeParameter().countParameters()でパラメータ数を非同期取得
- **68-79行目**: InvenTreeAttachment().countAttachments()で添付ファイル数を非同期取得

#### Step 4: 画面描画処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | manufacturer_part_detail.dart | `lib/widget/company/manufacturer_part_detail.dart` | getTiles()メソッドの実装 |

**主要処理フロー**:
- **125-149行目**: 内部パーツタイル（タップでPartDetailWidgetへ遷移）
- **151-172行目**: 製造元タイル（タップでCompanyDetailWidgetへ遷移）
- **174-181行目**: MPN（製造元品番）タイル
- **183-192行目**: 説明タイル（条件付き表示）
- **194-204行目**: 外部リンクタイル（条件付き表示）
- **206-228行目**: パラメータタイル、添付ファイルタイル

#### Step 5: 編集処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | manufacturer_part_detail.dart | `lib/widget/company/manufacturer_part_detail.dart` | editManufacturerPart()とappBarActions() |

**主要処理フロー**:
- **82-91行目**: editForm()でAPI経由の編集フォーム表示、成功時にrefresh()
- **103-119行目**: appBarActions()でcanEdit時のみ編集アイコンを表示

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

```
ManufacturerPartDetailWidget
    │
    ├─ _ManufacturerPartDisplayState
    │      │
    │      ├─ request()
    │      │      ├─ manufacturerPart.reload()
    │      │      ├─ InvenTreeParameter().countParameters()
    │      │      └─ InvenTreeAttachment().countAttachments()
    │      │
    │      ├─ getTiles()
    │      │      ├─ InvenTreePart().get() [タップ時]
    │      │      │      └─ part.goToDetailPage() → PartDetailWidget
    │      │      ├─ InvenTreeCompany().get() [タップ時]
    │      │      │      └─ supplier.goToDetailPage() → CompanyDetailWidget
    │      │      ├─ ShowParametersItem()
    │      │      └─ ShowAttachmentsItem()
    │      │
    │      ├─ editManufacturerPart()
    │      │      └─ manufacturerPart.editForm()
    │      │
    │      └─ appBarActions()
    │
    └─ InvenTreeManufacturerPart
           ├─ reload() → API: GET company/part/manufacturer/{pk}/
           ├─ editForm() → API: PATCH company/part/manufacturer/{pk}/
           └─ openLink() → 外部ブラウザ起動
```

### データフロー図

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

InvenTreeManufacturerPart  ───▶ _ManufacturerPartDisplayState ───▶ 画面Widget
(コンストラクタ引数)                    │
                                       │
API Response              ◀────────────┼─ reload()
(company/part/manufacturer/{pk}/)      │
                                       │
Parameter Count           ◀────────────┼─ countParameters()
                                       │
Attachment Count          ◀────────────┼─ countAttachments()
                                       │
                                       ▼
                                 getTiles()
                                       │
                                       ▼
                               ListTile群として画面表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| manufacturer_part_detail.dart | `lib/widget/company/manufacturer_part_detail.dart` | ソース | メイン画面Widget |
| company.dart | `lib/inventree/company.dart` | ソース | InvenTreeManufacturerPartデータモデル |
| refreshable_state.dart | `lib/widget/refreshable_state.dart` | ソース | 基底State（プルダウンリフレッシュ対応） |
| parameter_widget.dart | `lib/widget/parameter_widget.dart` | ソース | パラメータ表示ウィジェット |
| attachment_widget.dart | `lib/widget/attachment_widget.dart` | ソース | 添付ファイル表示ウィジェット |
| part_detail.dart | `lib/widget/part/part_detail.dart` | ソース | 内部パーツ詳細画面（遷移先） |
| company_detail.dart | `lib/widget/company/company_detail.dart` | ソース | 会社詳細画面（遷移先） |
| api.dart | `lib/api.dart` | ソース | InvenTreeAPI（サーバー通信） |
| snacks.dart | `lib/widget/snacks.dart` | ソース | スナックバー通知 |
| progress.dart | `lib/widget/progress.dart` | ソース | ローディングオーバーレイ |
