# 画面設計書 24-在庫アイテム一覧画面

## 概要

本ドキュメントは、InvenTree Flutterアプリケーションにおける「在庫アイテム一覧画面」の設計仕様を定義する。在庫アイテムをページネーション付きで一覧表示し、検索・フィルタリング・ソート機能を提供する画面である。

### 本画面の処理概要

在庫アイテム一覧画面は、InvenTreeサーバーに登録されている在庫アイテム（StockItem）をページネーション付きの一覧形式で表示する画面である。ユーザーはこの画面から在庫を検索・フィルタリングし、目的の在庫アイテムを素早く見つけて詳細画面へ遷移できる。

**業務上の目的・背景**：在庫管理において、保有する在庫アイテムを迅速に検索・確認することは業務効率化の要である。本画面は、ロケーション、ステータス、シリアル番号など様々な条件で在庫を絞り込み、目的のアイテムを発見するためのインターフェースを提供する。ページネーションにより大量データでもパフォーマンスを維持し、ステータス別の色分けで視認性を向上させている。

**画面へのアクセス方法**：
- 在庫ロケーション画面の「在庫アイテム」タブから表示
- 部品詳細画面の「在庫」タブから表示
- 購入注文詳細画面の「受領済み」タブから表示
- 検索画面から在庫検索結果として遷移

**主要な操作・処理内容**：
1. 在庫アイテム一覧のページネーション表示（25件ずつ取得）
2. 検索ボックスによるインクリメンタルサーチ（500msデバウンス）
3. フィルタリング（利用可能、在庫あり、アクティブ、サブロケーション含む、外部、シリアル化、ステータス）
4. ソート（部品名、IPN、数量、ステータス、バッチコード、更新日、棚卸日）
5. 在庫アイテムタップで詳細画面へ遷移

**画面遷移**：
- 遷移元：在庫ロケーション画面、部品詳細画面、購入注文詳細画面、検索画面
- 遷移先：在庫アイテム詳細画面（StockDetailWidget）

**権限による表示制御**：在庫の閲覧権限（stock）がない場合、この画面にはアクセスできない。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 14 | 在庫アイテム一覧表示 | 主機能 | 在庫アイテムのページネーション付き一覧表示 |
| 15 | 在庫アイテム詳細表示 | 遷移先機能 | 在庫アイテム選択時に在庫詳細画面へ遷移 |

## 画面種別

一覧

## URL/ルーティング

Flutter Navigator によるプッシュ遷移。`StockItemList` または `PaginatedStockItemList` ウィジェットのインスタンス化時に `filters` パラメータを渡して表示内容を制御する。

## 入出力項目

| 項目名 | 入出力 | 型 | 必須 | 説明 |
|--------|--------|------|------|------|
| filters | 入力 | Map<String, String> | Yes | 一覧表示時のフィルタ条件 |

## 表示項目

| 項目名 | 表示位置 | データ型 | 説明 |
|--------|----------|----------|------|
| 部品サムネイル | ListTile.leading | Image | 紐づく部品の画像 |
| 部品名 | ListTile.title | String | 紐づく部品のフルネーム |
| ロケーションパス | ListTile.subtitle | String | 在庫アイテムのロケーションパス |
| 数量/シリアル | ListTile.trailing | String | 数量（ステータス色付き）またはシリアル番号 |
| 検索結果件数 | タイトル下 | String | "Results: N" 形式で表示 |

## イベント仕様

### 1-在庫アイテムタップ

在庫リストの各アイテムをタップすると、該当アイテムの詳細画面（StockDetailWidget）へ遷移する。

**処理フロー**：
1. `onTap` コールバックが発火
2. `item.goToDetailPage(context)` を呼び出し
3. `Navigator.push` で `StockDetailWidget(this)` へ遷移

### 2-検索ボックス入力

検索ボックスにテキストを入力すると、500msのデバウンス後にサーバーへ検索クエリを送信する。

**処理フロー**：
1. `TextFormField.onChanged` でテキスト変更を検知
2. `updateSearchTerm()` メソッドを呼び出し
3. 500msタイマー後に `_pagingController.refresh()` で再検索

### 3-フィルタリング設定

フィルタアイコンをタップすると、ソートとフィルタリングのオプションダイアログが表示される。

**処理フロー**：
1. フィルタアイコン（`Icons.filter_alt`）をタップ
2. `_setOrderingOptions(context)` を呼び出し
3. `launchApiForm` でオプションダイアログを表示
4. 設定保存後に `_pagingController.refresh()` で一覧を再取得

### 4-プルダウンリフレッシュ

画面を下に引っ張ると、データをリフレッシュする。

**処理フロー**：
1. `RefreshIndicator.onRefresh` が発火
2. `_pagingController.refresh()` を呼び出し
3. ページ0から再取得

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 一覧表示 | StockItem | SELECT | 在庫データのページネーション取得 |
| 検索 | StockItem | SELECT | 検索条件に合致する在庫の取得 |

### テーブル別更新項目詳細

#### StockItem テーブル（読み取りのみ）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | pk, part, part_detail, location, location_detail, quantity, serial, status, batch, updated, stocktake_date | フィルタ条件とページネーションパラメータに基づく | APIエンドポイント: /api/stock/ |

## メッセージ仕様

| メッセージID | メッセージ種別 | 表示条件 | メッセージ内容 |
|-------------|---------------|----------|---------------|
| MSG_NO_RESULTS | 情報 | 検索結果が0件 | "No results" |
| MSG_RESULTS | 情報 | 検索結果表示 | "Results: {件数}" |

## 例外処理

| 例外条件 | 処理内容 | ユーザーへの表示 |
|---------|---------|-----------------|
| APIエラー | エラーをSentryに報告 | 一覧表示が停止、エラー状態を表示 |
| ネットワークエラー | 再試行可能な状態を維持 | プルダウンでリフレッシュ可能 |
| 権限不足 | ウィジェット非表示 | 画面にアクセスできない |
| StockStatus未ロード | ステータスをロード | 表示前にステータスコードを取得 |

## 備考

- ページサイズは25件固定（`_pageSize = 25`）
- フィルタ・ソート設定は `InvenTreeSettingsManager` によりローカルに永続化される
- 検索のデバウンス時間は500ms
- ステータスコードはAPI取得時に `InvenTreeAPI().StockStatus.load()` で事前ロード
- ステータスによる色分け表示: `InvenTreeAPI().StockStatus.color(item.status)`
- シリアル化されたアイテムは数量ではなく "SN: {シリアル番号}" を表示

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | stock.dart | `lib/inventree/stock.dart` | InvenTreeStockItemクラス（134-574行）。partName, locationPathString, displayQuantity, statusなどのゲッター |

**読解のコツ**: `InvenTreeStockItem` は `part_detail` と `location_detail` をサブキーとして持ち、関連データをネストして保持している。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | stock_list.dart | `lib/widget/stock/stock_list.dart` | StockItemListウィジェット（11-32行）とPaginatedStockItemList（34-149行）の関係 |

**主要処理フロー**:
1. **11-18行**: `StockItemList` StatefulWidgetの定義。filtersをコンストラクタで受け取る
2. **29-31行**: `getBody()` で `PaginatedStockItemList` を返す
3. **34-43行**: `PaginatedStockItemList` がStatefulWidgetとして定義
4. **45-149行**: `_PaginatedStockItemListState` で実際のページネーションロジックを実装

#### Step 3: フィルタ・ソートオプションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | stock_list.dart | `lib/widget/stock/stock_list.dart` | orderingOptions（53-61行）とfilterOptions（63-111行）の定義 |

**主要処理フロー**:
- **53-61行**: ソートオプション（part__name, part__IPN, stock, status, batch, updated, stocktake_date）
- **66-111行**: フィルタオプション（available, in_stock, active, cascade, external, serialized, status）
- **106-108行**: ステータス選択肢は `InvenTreeAPI().StockStatus.choices` から取得

#### Step 4: リストアイテム構築を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | stock_list.dart | `lib/widget/stock/stock_list.dart` | buildItem()メソッド（131-148行）。ListTileの構築方法 |

**主要処理フロー**:
- **133行**: InvenTreeModelをInvenTreeStockItemにキャスト
- **135-147行**: ListTileを構築
- **139-143行**: trailingにステータス色付きで数量を表示
- **144-146行**: onTapで `item.goToDetailPage(context)` を呼び出し

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

```
StockItemList (StatefulWidget)
    │
    └─ _StockListState (RefreshableState)
           │
           └─ getBody() → PaginatedStockItemList
                              │
                              └─ _PaginatedStockItemListState (PaginatedSearchState)
                                     │
                                     ├─ requestPage()
                                     │      │
                                     │      ├─ InvenTreeAPI().StockStatus.load()
                                     │      └─ InvenTreeStockItem().listPaginated()
                                     │                      │
                                     │                      └─ API GET /api/stock/
                                     │
                                     └─ buildItem() → ListTile
                                                        │
                                                        └─ onTap → item.goToDetailPage()
                                                                      │
                                                                      └─ StockDetailWidget
```

### データフロー図

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

filters (Map)    ───▶ PaginatedStockItemList         ───▶ ListView
                         │
                         ├─ requestPage()
                         │      │
                         │      ├─ StockStatus.load()
                         │      │
                         │      └─ API: /api/stock/?limit=25&offset=N
                         │             │
                         │             └─ InvenTreePageResponse
                         │
                         └─ buildItem()
                                │
                                └─ InvenTreeStockItem → ListTile
                                         │
                                         └─ StockStatus.color() → 色付き数量表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| stock_list.dart | `lib/widget/stock/stock_list.dart` | ソース | 在庫アイテム一覧画面のメインウィジェット |
| paginator.dart | `lib/widget/paginator.dart` | ソース | ページネーション共通基盤クラス |
| stock.dart | `lib/inventree/stock.dart` | ソース | 在庫アイテムデータモデル |
| model.dart | `lib/inventree/model.dart` | ソース | モデル基底クラス（API通信含む） |
| api.dart | `lib/api.dart` | ソース | API通信クライアント、StockStatusステータス管理 |
| refreshable_state.dart | `lib/widget/refreshable_state.dart` | ソース | リフレッシュ可能なState基底クラス |
| link_icon.dart | `lib/widget/link_icon.dart` | ソース | LargeTextウィジェット（数量表示用） |
| l10.dart | `lib/l10.dart` | ソース | 多言語対応（ローカライゼーション） |
| stock_detail.dart | `lib/widget/stock/stock_detail.dart` | ソース | 在庫アイテム詳細（遷移先） |
