# 機能設計書 69-アイテム位置特定

## 概要

本ドキュメントは、InvenTreeモバイルアプリにおけるアイテム位置特定機能の設計を記述するものである。プラグインを使用して在庫アイテムや在庫ロケーションの物理的な位置を特定する機能の仕様を定義する。

### 本機能の処理概要

本機能は、InvenTreeサーバーに登録されているプラグイン（locate mixinをサポートするもの）を使用して、在庫アイテムまたは在庫ロケーションの物理的な位置を特定（照射、点滅等）する機能を提供する。倉庫内のLED照明システムやピッキングシステムと連携し、ユーザーが目的のアイテムを素早く見つけられるようにする。

**業務上の目的・背景**：大規模な倉庫や複雑な棚配置を持つ環境では、目的のアイテムを見つけるのに時間がかかることがある。位置特定機能により、サーバー側のプラグインと連携して物理的なインジケーター（LED等）を制御し、ピッキング効率を大幅に向上させることができる。

**機能の利用シーン**：
- 倉庫でのピッキング作業時に目的のアイテムを素早く見つけたい場合
- 在庫棚卸し時にアイテムの位置を確認したい場合
- 新しい作業者に棚の位置を示したい場合

**主要な処理内容**：
1. locateミキシンをサポートするプラグイン一覧の取得
2. 複数プラグインがある場合はユーザーに選択ダイアログを表示
3. サーバーのlocate APIエンドポイントにリクエストを送信
4. 成功/失敗のフィードバックをユーザーに表示

**関連システム・外部連携**：
- InvenTreeサーバー：/api/locate/ エンドポイント
- InvenTreeプラグイン：locate mixinをサポートするプラグイン
- 外部ハードウェア：LED照明システム、ピッキングシステム等（プラグイン経由）

**権限による制御**：locateミキシンをサポートするプラグインがサーバーに登録・有効化されている必要がある。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 25 | 在庫アイテム詳細画面 | 補助機能 | 位置特定ボタン押下時にアイテムの物理的位置を特定 |

## 機能種別

API連携 / 外部プラグイン連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| item | int | No | 在庫アイテムID | itemまたはlocationのいずれか必須 |
| location | int | No | 在庫ロケーションID | itemまたはlocationのいずれか必須 |
| plugin | String | Yes | 使用するプラグインのキー | 空文字列不可 |

### 入力データソース

- 画面操作：在庫アイテム詳細画面の位置特定ボタン
- サーバー：利用可能なプラグイン一覧

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| success | bool | リクエスト成功/失敗 |

### 出力先

- InvenTreeサーバー：/api/locate/ エンドポイント
- 外部ハードウェア：プラグイン経由で制御される物理デバイス
- 画面表示：成功/失敗のスナックバー通知

## 処理フロー

### 処理シーケンス

```
1. 位置特定ボタン押下
   └─ locateItemOrLocation()呼び出し
2. プラグイン取得
   └─ getPlugins(mixin: "locate")でlocate対応プラグイン一覧取得
3. プラグイン選択
   └─ プラグインが1つ: 自動選択
   └─ プラグインが複数: ダイアログでユーザー選択
   └─ プラグインなし: 処理終了
4. APIリクエスト送信
   └─ POST /api/locate/ にplugin, item/locationを送信
5. 結果表示
   └─ 成功: 成功通知を表示
   └─ 失敗: エラー通知を表示
```

### フローチャート

```mermaid
flowchart TD
    A[位置特定ボタン押下] --> B[getPlugins locate]
    B --> C{プラグインあり?}
    C -->|No| D[終了]
    C -->|Yes| E{プラグイン数}
    E -->|1つ| F[自動選択]
    E -->|複数| G[選択ダイアログ表示]
    G --> H{選択?}
    H -->|Yes| F
    H -->|No| D
    F --> I[POST /api/locate/]
    I --> J{成功?}
    J -->|Yes| K[成功通知表示]
    J -->|No| L[エラー通知表示]
    K --> D
    L --> D
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-69-01 | プラグイン必須 | locate mixinをサポートするプラグインが必要 | 機能使用時 |
| BR-69-02 | 単一プラグイン自動選択 | プラグインが1つの場合は自動選択 | プラグイン数=1 |
| BR-69-03 | 複数プラグイン選択 | プラグインが複数の場合はユーザーが選択 | プラグイン数>1 |
| BR-69-04 | 排他パラメータ | itemまたはlocationのいずれかを指定 | API呼び出し時 |

### 計算ロジック

該当なし

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

本機能ではローカルデータベース操作は発生しない。

### API操作

| 操作 | エンドポイント | メソッド | 概要 |
|-----|---------------|---------|------|
| 位置特定リクエスト | /api/locate/ | POST | プラグインにアイテム/ロケーションの位置特定を依頼 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | プラグインなし | locate対応プラグインが未登録 | 処理終了（エラー表示なし） |
| - | APIエラー | サーバー通信エラー | エラー通知表示 |
| - | プラグインエラー | プラグイン側でエラー発生 | サーバーからのエラー応答を表示 |

### リトライ仕様

リトライは実装されていない。ユーザーが再度ボタンを押下することで再試行可能。

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

本機能ではトランザクションは発生しない。

## パフォーマンス要件

- プラグイン取得：500ms以内
- API応答：外部ハードウェアに依存（通常1-3秒）

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

- プラグインキーとアイテム/ロケーションIDのみを送信
- サーバー側の権限チェックに依存
- 物理デバイスの制御はサーバー側プラグインの責任

## 備考

- InvenTreePluginモデルでプラグイン情報を管理
- supportsMixinメソッドでlocate対応を確認
- launchApiFormでプラグイン選択ダイアログを表示

---

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

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

### 推奨読解順序

#### Step 1: プラグイン管理を理解する

InvenTreeAPIでのプラグイン管理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | api.dart | `lib/api.dart` | プラグイン関連メソッド |

**読解のコツ**:
- **361行目**: `_plugins`リストでプラグインをキャッシュ
- **365-381行目**: `getPlugins`メソッドでmixinでフィルタリングしたプラグイン一覧を取得
- **384行目**: `supportsMixin`メソッドで特定mixinのサポートを確認
- **738-757行目**: `_fetchPlugins`メソッドでサーバーからプラグイン情報を取得

#### Step 2: 位置特定処理を理解する

locateItemOrLocationメソッドの実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | api.dart | `lib/api.dart` | locateItemOrLocationメソッド |

**主要処理フロー**:
- **1660-1726行目**: `locateItemOrLocation`メソッド
- **1665行目**: `getPlugins(mixin: "locate")`でlocate対応プラグインを取得
- **1667-1669行目**: プラグインがない場合は終了
- **1671-1675行目**: プラグインが1つの場合は自動選択
- **1677-1706行目**: プラグインが複数の場合は選択ダイアログを表示
- **1709-1717行目**: リクエストボディを構築
- **1719-1725行目**: POST /api/locate/を呼び出し、成功時に通知表示

#### Step 3: プラグイン選択ダイアログを理解する

launchApiFormによるダイアログ表示を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | api.dart | `lib/api.dart` | ダイアログ構築部分 |

**主要処理フロー**:
- **1678-1685行目**: プラグインオプションをMap形式で構築
- **1687-1695行目**: フォームフィールド定義（choice型）
- **1697-1706行目**: `launchApiForm`でダイアログを表示し、選択結果を取得

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

```
在庫アイテム詳細画面
    │
    └─ 位置特定ボタン押下
           │
           └─ InvenTreeAPI().locateItemOrLocation()
                  │
                  ├─ getPlugins(mixin: "locate")
                  │      └─ _plugins.filter(supportsMixin("locate"))
                  │
                  ├─ [プラグイン数確認]
                  │      │
                  │      ├─ [0個] → 終了
                  │      ├─ [1個] → 自動選択
                  │      └─ [複数] → launchApiForm()
                  │                      └─ 選択ダイアログ表示
                  │
                  └─ post("/api/locate/", body: {plugin, item/location})
                         │
                         └─ [成功] → showSnackIcon("成功")
```

### データフロー図

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

                      ┌─────────────────────┐
プラグインリスト ────▶│ getPlugins("locate")│
(_plugins)            └──────────┬──────────┘
                                 │
                                 ▼
                      ┌─────────────────────┐
                      │ プラグイン数判定    │
                      │ - 0: 終了           │
                      │ - 1: 自動選択       │
                      │ - n: ダイアログ     │
                      └──────────┬──────────┘
                                 │
                                 ▼
                      ┌─────────────────────┐
アイテムID/          │ post("/api/locate/")│
ロケーションID ─────▶│ - plugin            │──────▶ InvenTreeサーバー
                      │ - item/location     │              │
                      └─────────────────────┘              │
                                                           ▼
                                                    プラグイン実行
                                                    (LED点灯等)
                                                           │
                      ┌─────────────────────┐              │
                      │ showSnackIcon()     │◀─────────────┘
                      │ "成功" or "失敗"    │──────▶ ユーザー通知
                      └─────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| api.dart | `lib/api.dart` | ソース | locateItemOrLocation実装、プラグイン管理 |
| api_form.dart | `lib/api_form.dart` | ソース | launchApiForm（選択ダイアログ） |
| model.dart | `lib/inventree/model.dart` | ソース | InvenTreePluginモデル定義 |
| l10.dart | `lib/l10.dart` | ソース | 多言語テキスト取得ヘルパー |
| snacks.dart | `lib/widget/snacks.dart` | ソース | showSnackIcon（通知表示） |
