# 機能設計書 14-在庫アイテム一覧表示

## 概要

本ドキュメントは、InvenTreeモバイルアプリにおける在庫アイテム一覧表示機能の設計仕様を定義する。

### 本機能の処理概要

本機能は、在庫アイテムを一覧表示する機能である。パーツ、ロケーション、ステータスなど多様な条件でフィルタリングし、ページネーション対応で大量の在庫データを効率的に表示する。

**業務上の目的・背景**：在庫管理業務において、在庫アイテムの一覧表示は最も頻繁に使用される機能の一つである。ピッキング作業時の在庫確認、棚卸し作業、在庫状況の把握など、様々な場面で活用される。フィルタリング機能により、特定条件の在庫アイテムを素早く特定でき、業務効率が向上する。

**機能の利用シーン**：
- 特定パーツの在庫アイテムを確認する場合
- 特定ロケーションの在庫を確認する場合
- 在庫状況（在庫あり/なし、外部在庫等）でフィルタする場合
- シリアル番号付きアイテムを検索する場合
- 棚卸し作業で在庫を確認する場合

**主要な処理内容**：
1. フィルタ条件に基づいて在庫アイテム一覧を取得
2. 各在庫アイテムのパーツ名、ロケーション、数量、ステータスを表示
3. 検索機能による絞り込み
4. ソート順序の変更（名前、IPN、数量、ステータス等）
5. 在庫アイテム選択時に詳細画面へ遷移

**関連システム・外部連携**：InvenTree APIの `stock/` エンドポイントを使用して在庫アイテムデータを取得する。

**権限による制御**：`stock` ロールの `view` 権限が必要である。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | ホーム画面 | 遷移元機能 | 在庫タイル押下時に在庫ロケーション画面へ遷移 |
| 20 | 部品カテゴリ画面 | 関連機能 | カテゴリ内パーツ一覧のタブ表示 |
| 22 | 部品詳細画面 | 関連機能 | 在庫タブでパーツに関連する在庫アイテム一覧表示 |
| 23 | 在庫ロケーション画面 | 関連機能 | ロケーション内在庫アイテム一覧のタブ表示 |
| 24 | 在庫アイテム一覧画面 | 主画面 | 在庫アイテムのページネーション付き一覧表示 |
| 25 | 在庫アイテム詳細画面 | 遷移先機能 | 在庫アイテム選択時に在庫詳細画面へ遷移 |

## 機能種別

データ参照（READ）/ 一覧表示

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| filters | Map<String, String> | No | フィルタリング条件 | - |
| part | int | No | パーツIDフィルタ | 正の整数 |
| location | int | No | ロケーションIDフィルタ | 正の整数またはnull |
| search | String | No | 検索クエリ | - |
| limit | int | No | 1ページあたりの取得件数（デフォルト25） | 正の整数 |
| offset | int | No | 取得開始位置 | 0以上の整数 |
| ordering | String | No | ソート順序 | 指定フィールド名 |
| in_stock | bool | No | 在庫ありのみ | true/false |
| available | bool | No | 利用可能在庫のみ | true/false |
| active | bool | No | アクティブパーツのみ | true/false |
| cascade | bool | No | サブロケーションを含む | true/false |
| external | bool | No | 外部在庫フィルタ | true/false/null |
| serialized | bool | No | シリアル化在庫のみ | true/false |
| status | int | No | ステータスコードフィルタ | ステータスコード値 |

### 入力データソース

- 上位画面から渡されるフィルタ条件
- ユーザーによる検索クエリ入力
- ユーザーによるフィルタリング/ソート設定

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| pk | int | 在庫アイテムの主キー |
| part | int | パーツID |
| partName | String | パーツ名 |
| partThumbnail | String | パーツサムネイル画像URL |
| location | int | ロケーションID |
| locationPathString | String | ロケーションパス文字列 |
| quantity | double | 在庫数量 |
| displayQuantity | String | 表示用数量（シリアル番号または数量） |
| status | int | ステータスコード |
| serial | String | シリアル番号（シリアル化されている場合） |
| batch | String | バッチコード |
| units | String | 単位 |

### 出力先

- ListView形式の画面表示
- ListTileウィジェットによる各在庫アイテム情報の表示
- 数量はステータスに応じた色で表示

## 処理フロー

### 処理シーケンス

```
1. 在庫アイテム一覧画面を初期化
   └─ フィルタ条件を受け取る
2. フィルタオプションの構築
   └─ filterOptionsでavailable, in_stock, active等を定義
3. ソートオプションの構築
   └─ orderingOptionsでname, IPN, quantity等を定義
4. APIリクエストの構築
   └─ stock/ エンドポイントにフィルタを設定
5. ページネーション付きで在庫アイテム一覧を取得
   └─ InvenTreeStockItem().listPaginated()を呼び出し
6. 取得データをListViewで表示
   └─ 各項目をListTileとして構築
7. ユーザー操作の処理
   ├─ 在庫アイテム選択：在庫詳細画面へ遷移
   ├─ 検索：検索クエリでフィルタ
   ├─ フィルタ変更：条件を変更して再取得
   └─ スクロール：次ページ取得
```

### フローチャート

```mermaid
flowchart TD
    A[在庫アイテム一覧画面] --> B[フィルタ条件設定]
    B --> C[PaginatedStockItemList構築]
    C --> D[requestPage呼び出し]
    D --> E[InvenTreeStockItem.listPaginated]
    E --> F[API: stock/]
    F --> G[JSON Response]
    G --> H[ListView表示]
    H --> I{ユーザー操作}
    I -->|アイテム選択| J[在庫詳細画面へ遷移]
    I -->|検索入力| K[検索クエリ設定]
    I -->|フィルタ変更| L[フィルタ設定]
    I -->|スクロール| M[次ページ取得]
    K --> D
    L --> D
    M --> D
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-14-01 | デフォルト在庫フィルタ | デフォルトでin_stock=trueでフィルタ | 初期表示時 |
| BR-14-02 | デフォルトアクティブフィルタ | デフォルトでactive=trueでフィルタ | 初期表示時 |
| BR-14-03 | サブロケーション含む | デフォルトでcascade=trueでサブロケーションを含む | 初期表示時 |
| BR-14-04 | シリアル表示 | シリアル化されている場合は数量の代わりにシリアル番号を表示 | serial != "" && quantity == 1 |
| BR-14-05 | ステータス色表示 | 数量はステータスに応じた色で表示 | 常時 |
| BR-14-06 | ステータスフィルタ | APIバージョン105以降でステータスフィルタが利用可能 | supportsStatusLabelEndpoints == true |

### 計算ロジック

- displayQuantity: シリアル化されている場合は"SN: {serial}"、それ以外は数量+単位

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 在庫アイテム取得 | StockItem | SELECT | フィルタ条件に合致する在庫アイテムを取得 |

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

#### StockItem（InvenTree API経由）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | part, location, quantity等 | フィルタ条件 | 取得対象カラム |
| SELECT | part_detail, location_detail | - | 詳細情報を含める |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | 認証エラー | トークン無効または期限切れ | 再ログインを促す |
| 403 | 権限エラー | 必要なロールが不足 | 権限確認メッセージを表示 |
| 500 | サーバーエラー | サーバー内部エラー | リトライまたはエラー表示 |

### リトライ仕様

ネットワークエラー時はプルダウンリフレッシュで再取得可能。

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

読み取り専用のため、トランザクション管理は不要。

## パフォーマンス要件

- ページサイズ：25件（PaginatedSearchState._pageSize）
- スクロールによる遅延読み込み対応
- 画像はキャッシュを使用（CachedNetworkImage）
- ステータスコードは事前にロード

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

- API認証トークンによるアクセス制御
- `stock` ロールの `view` 権限チェック
- HTTPS通信によるデータ保護

## 備考

- デフォルトフィルタ（part_detail, location_detail等）はdefaultFilters()で設定
- ステータスコードの色はInvenTreeAPI().StockStatus.color()で取得
- 検索は500msのデバウンス処理を適用

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | stock.dart | `lib/inventree/stock.dart` | InvenTreeStockItemクラスの定義、プロパティを理解する |

**読解のコツ**:
- **134-574行目**: InvenTreeStockItemクラスの定義
- **140行目**: APIエンドポイント `stock/`
- **145行目**: rolesRequired = ["stock"]
- **211-219行目**: defaultFilters()でpart_detail, location_detail等を含める
- **315-329行目**: partName, partDescriptionの取得ロジック
- **409-426行目**: quantityString(), allocated, availableの計算
- **432-444行目**: serialOrQuantityDisplay()でシリアル/数量の表示切替

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | stock_list.dart | `lib/widget/stock/stock_list.dart` | StockItemList/PaginatedStockItemListクラスのエントリーポイント |

**主要処理フロー**:
1. **11-18行目**: StockItemListの定義、filtersを受け取る
2. **29-31行目**: getBody()でPaginatedStockItemListを構築

#### Step 3: ページネーション対応リストを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | stock_list.dart | `lib/widget/stock/stock_list.dart` | PaginatedStockItemListクラスによるページネーション対応の一覧表示を理解 |

**主要処理フロー**:
- **34-43行目**: PaginatedStockItemListクラスの定義
- **53-61行目**: orderingOptionsでソートオプションを定義
- **63-111行目**: filterOptionsで各種フィルタを定義
- **113-129行目**: requestPage()でInvenTreeStockItem().listPaginated()を呼び出し
- **131-148行目**: buildItem()で各在庫アイテムのListTileを構築

#### Step 4: 表示用データの整形を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | stock.dart | `lib/inventree/stock.dart` | displayQuantity, locationPathString等の実装 |

**主要処理フロー**:
- **474-488行目**: displayQuantityでシリアル番号または数量+単位を返す
- **461-472行目**: locationPathStringでロケーションパスを取得
- **434行目**: isSerialized()でシリアル化判定

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

```
StockItemList / PaginatedStockItemList
    │
    ├─ PaginatedSearchState (基底クラス)
    │      ├─ requestPage()
    │      │      └─ InvenTreeStockItem().listPaginated()
    │      │              └─ InvenTreeAPI.get()
    │      │
    │      ├─ filterOptions (available, in_stock, active等)
    │      │
    │      ├─ orderingOptions (part__name, quantity等)
    │      │
    │      └─ updateSearchTerm() (検索デバウンス)
    │
    └─ buildItem()
           └─ ListTile構築
                  ├─ partName (title)
                  ├─ locationPathString (subtitle)
                  ├─ partThumbnail (leading)
                  └─ displayQuantity + status color (trailing)
```

### データフロー図

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

filters ─────────▶ InvenTreeStockItem ───────▶ ListView
(part, location)        .listPaginated()            (ListTile)
                              │
                              ▼
                   API: stock/
                         ?part_detail=true
                         &location_detail=true
                              │
                              ▼
                   JSON Response ──────▶ List<InvenTreeStockItem>
                                                │
                                                ▼
                                     画面表示（パーツ名, ロケーション, 数量）
                                                │
                                                ▼
                                     StockStatus.color(status) で色付け
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| stock_list.dart | `lib/widget/stock/stock_list.dart` | ソース | 在庫アイテム一覧表示ウィジェット |
| stock.dart | `lib/inventree/stock.dart` | ソース | InvenTreeStockItemモデルクラス定義 |
| model.dart | `lib/inventree/model.dart` | ソース | 基底モデルクラス、API呼び出し共通処理 |
| paginator.dart | `lib/widget/paginator.dart` | ソース | ページネーション対応検索ウィジェット基底クラス |
| refreshable_state.dart | `lib/widget/refreshable_state.dart` | ソース | リフレッシュ可能な状態管理基底クラス |
| api.dart | `lib/api.dart` | ソース | InvenTree API通信クラス、StockStatusプロパティ |
| status_codes.dart | `lib/inventree/status_codes.dart` | ソース | ステータスコード管理クラス |
| link_icon.dart | `lib/widget/link_icon.dart` | ソース | LargeTextウィジェット |
