# 機能設計書 6-パーツ編集

## 概要

本ドキュメントは、InvenTreeモバイルアプリにおけるパーツ編集機能の設計を記載する。パーツの各種情報を編集・更新する機能を提供する。

### 本機能の処理概要

既存のパーツ情報をAPIフォームを通じて編集・更新する機能である。パーツの基本情報（名前、説明、IPN等）やカテゴリ、各種フラグ（アクティブ、アセンブリ、コンポーネント等）を変更できる。

**業務上の目的・背景**：在庫管理業務において、パーツ情報の更新は日常的に発生する。製品仕様の変更、カテゴリの再編成、非アクティブ化など、パーツマスタの維持管理が必要である。モバイルデバイスからでも素早く情報を更新できることで、現場での即時対応が可能になる。

**機能の利用シーン**：パーツ詳細画面からの情報修正、カテゴリ変更、非アクティブ化、新規パーツ作成後の追加情報入力などで利用される。

**主要な処理内容**：
1. 編集フォームの表示（サーバーからフィールド定義を取得）
2. 現在値の表示と編集
3. バリデーション（サーバーサイド）
4. 更新APIの呼び出し
5. 成功時の画面リフレッシュ

**関連システム・外部連携**：InvenTree REST API（part/{pk}/エンドポイント、OPTIONSでフィールド定義取得、PATCHで更新）

**権限による制御**：partロールのchange権限が必要。権限がない場合は編集ボタンが表示されない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 22 | 部品詳細画面 | 主画面 | 編集ボタン押下時にパーツ情報編集フォーム表示 |

## 機能種別

CRUD操作（Update）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | String | Yes | パーツ名 | 空文字不可 |
| description | String | No | 説明 | - |
| IPN | String | No | 内部品番 | 一意性（サーバー検証） |
| revision | String | No | リビジョン | - |
| keywords | String | No | キーワード | - |
| link | String | No | 外部リンク | URL形式 |
| category | int | No | カテゴリID | 存在するカテゴリ |
| default_location | int | No | デフォルトロケーションID | 存在するロケーション |
| units | String | No | 単位 | - |
| active | bool | No | アクティブ状態 | true/false |
| assembly | bool | No | アセンブリフラグ | true/false |
| component | bool | No | コンポーネントフラグ | true/false |
| purchaseable | bool | No | 購入可能フラグ | true/false |
| salable | bool | No | 販売可能フラグ | true/false |
| trackable | bool | No | 追跡可能フラグ | true/false |
| is_template | bool | No | テンプレートフラグ | true/false |
| virtual | bool | No | 仮想パーツフラグ | true/false |

### 入力データソース

- 編集フォームのユーザー入力
- 既存パーツデータ（初期値として表示）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | Map<String, dynamic> | 更新後のパーツデータ |

### 出力先

- InvenTreeサーバー（PATCH API）
- 画面リフレッシュ（成功時）

## 処理フロー

### 処理シーケンス

```
1. 編集ボタン押下
   └─ canEditの確認

2. フォームフィールド定義取得（formFields）
   └─ name, description, IPN, revision等のフィールド定義

3. APIフォームダイアログ表示（launchApiForm）
   └─ OPTIONSリクエストでフィールド情報取得
   └─ 現在値をフォームに設定
   └─ ユーザー入力待ち

4. 送信処理
   └─ 入力値の収集
   └─ PATCHリクエスト送信

5. レスポンス処理
   └─ 成功: onSuccess呼び出し、画面リフレッシュ、成功メッセージ表示
   └─ 失敗: エラーメッセージ表示
```

### フローチャート

```mermaid
flowchart TD
    A[編集ボタン押下] --> B{canEdit?}
    B -->|No| C[操作不可]
    B -->|Yes| D[formFields取得]
    D --> E[launchApiForm]
    E --> F[OPTIONSリクエスト]
    F --> G[フィールド定義取得]
    G --> H[フォーム表示]
    H --> I{ユーザー操作}
    I -->|キャンセル| J[ダイアログ閉じる]
    I -->|保存| K[PATCHリクエスト]
    K --> L{レスポンス確認}
    L -->|成功| M[onSuccess実行]
    M --> N[refresh]
    N --> O[成功メッセージ]
    L -->|エラー| P[エラー表示]
    P --> H
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 名前必須 | パーツ名は空にできない | 保存時 |
| BR-02 | IPN一意性 | IPNはシステム内で一意 | IPN設定時 |
| BR-03 | カテゴリ存在 | 指定カテゴリは存在する必要あり | カテゴリ変更時 |
| BR-04 | ロケーション存在 | 指定ロケーションは存在する必要あり | デフォルトロケーション設定時 |

### 計算ロジック

該当なし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| パーツ更新 | - | - | サーバーAPIのみ（ローカルDB操作なし） |

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

ローカルデータベース操作なし。サーバーAPIへのPATCHリクエストのみ。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 400 | バリデーションエラー | 入力値不正 | フィールドごとのエラーメッセージ表示 |
| 401/403 | 認証/権限エラー | partロールのchange権限なし | エラーメッセージ表示 |
| 404 | 未検出エラー | パーツが存在しない | エラーメッセージ表示 |

### リトライ仕様

- 自動リトライなし
- ユーザーによる再入力・再送信が必要

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

- サーバーサイドでのトランザクション管理

## パフォーマンス要件

- OPTIONSリクエストはキャッシュ利用
- APIタイムアウト: 10秒

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

- partロールのchange権限が必要
- 認証トークンによるAPI認証

## 備考

- フォームはサーバーからのフィールド定義に基づいて動的に生成
- ロケール設定に応じてフィールドラベルが多言語化

---

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

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

### 推奨読解順序

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

まず、パーツのフォームフィールド定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | part.dart | `lib/inventree/part.dart` | formFieldsメソッド（162-187行目） |

**読解のコツ**:
- 各フィールドはMap形式で定義
- 空のMapはデフォルト設定を使用することを意味する
- サーバーからOPTIONSで追加情報（required, help_text等）を取得

#### Step 2: 編集ダイアログの呼び出しを理解する

編集ダイアログの起動処理を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | part_detail.dart | `lib/widget/part/part_detail.dart` | _editPartDialogメソッド（312-321行目） |
| 2-2 | model.dart | `lib/inventree/model.dart` | editFormメソッド |

**主要処理フロー**:
- **312-321行目**: `part.editForm`を呼び出し、成功時にrefreshと成功メッセージ表示

#### Step 3: APIフォーム処理を理解する

フォームの動的生成と送信処理を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | api_form.dart | `lib/api_form.dart` | launchApiForm関数 |

**主要処理フロー**:
- OPTIONSリクエストでフィールド定義取得
- フォームウィジェットの動的生成
- 入力値の収集とPATCHリクエスト送信

#### Step 4: 権限チェックを理解する

編集権限の確認処理を追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | model.dart | `lib/inventree/model.dart` | canEditゲッター |
| 4-2 | api.dart | `lib/api.dart` | checkRoleメソッド（763-807行目） |

**主要処理フロー**:
- `canEdit`はロールとパーミッションをチェック
- partロールのchange権限が必要

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

```
PartDetailWidget
    │
    └─ _editPartDialog(context)
           │
           └─ part.editForm(context, title, onSuccess)
                  │
                  ├─ formFields()
                  │      └─ {name, description, IPN, ...}
                  │
                  └─ launchApiForm(context, url, fields)
                         │
                         ├─ api.options(url)
                         │      └─ フィールド定義取得
                         │
                         ├─ フォームダイアログ表示
                         │
                         └─ [保存] api.patch(url, body)
                                │
                                └─ onSuccess(data)
                                       └─ refresh(context)
```

### データフロー図

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

既存パーツデータ ───▶ formFields() ───▶ フォーム定義
    │                     │                    │
    └─ 現在値            ├─ OPTIONSリクエスト   ├─ フォームUI
                        └─ フィールド定義取得    │
                                               │
ユーザー入力 ───▶ フォームUI ───▶ PATCHリクエスト
                        │                      │
                        └─ バリデーション        └─ 更新後データ
                                                      │
                                                      ▼
                                                 画面リフレッシュ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| part_detail.dart | `lib/widget/part/part_detail.dart` | ソース | 編集ダイアログ呼び出し元 |
| part.dart | `lib/inventree/part.dart` | ソース | formFieldsメソッド |
| model.dart | `lib/inventree/model.dart` | ソース | editForm基底メソッド、canEditゲッター |
| api_form.dart | `lib/api_form.dart` | ソース | launchApiForm関数、フォーム動的生成 |
| api.dart | `lib/api.dart` | ソース | options、patchメソッド、権限チェック |
| snacks.dart | `lib/widget/snacks.dart` | ソース | 成功メッセージ表示 |
