# 機能設計書 21-在庫履歴表示

## 概要

本ドキュメントは、InvenTreeアプリにおける在庫履歴表示機能の設計を記載する。在庫アイテムの変更履歴を時系列で表示し、ユーザーが在庫の変動を追跡できる機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：在庫管理において、いつ誰が在庫を変更したかを追跡することは、在庫差異の原因究明、監査対応、品質管理において極めて重要である。本機能により、在庫アイテムに対する全ての操作履歴を確認でき、トレーサビリティを確保する。

**機能の利用シーン**：在庫詳細画面から履歴タブを選択した際、または在庫の変動原因を調査する際に利用される。棚卸し差異の原因調査、出荷・入荷記録の確認、在庫調整の監査などに活用される。

**主要な処理内容**：
1. 在庫アイテムIDに基づいてAPIから履歴データを取得
2. 履歴データをページネーション形式で表示
3. 各履歴エントリの日時、操作者、操作内容、備考を表示
4. 無限スクロールによる追加データの遅延読み込み

**関連システム・外部連携**：InvenTree REST API（`stock/track/`エンドポイント）と連携し、履歴データを取得する。

**権限による制御**：`stock`ロールを持つユーザーのみが履歴を閲覧可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 25 | 在庫アイテム詳細画面 | 遷移元画面 | 履歴項目押下時に履歴画面へ遷移 |

## 機能種別

データ参照 / 一覧表示

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| item | int | Yes | 在庫アイテムのID | 正の整数 |
| limit | int | No | 取得件数上限 | デフォルト25件 |
| offset | int | No | 取得開始位置 | デフォルト0 |

### 入力データソース

在庫詳細画面から渡される`InvenTreeStockItem`オブジェクトから在庫アイテムIDを取得。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| date | DateTime | 操作日時 |
| label | String | 操作ラベル（追加、削除、移動等） |
| notes | String | 操作時のメモ |
| user | int | 操作者ユーザーID |
| username | String | 操作者ユーザー名 |
| deltas | Map | 変更内容の詳細（数量変更など） |

### 出力先

画面（リストビュー形式）

## 処理フロー

### 処理シーケンス

```
1. 画面初期化
   └─ StockItemHistoryWidgetが在庫アイテムを受け取って表示
2. PaginatedStockHistoryListの生成
   └─ フィルタにitem IDを設定
3. 履歴データ取得要求
   └─ InvenTreeStockItemHistory.listPaginatedを呼び出し
4. ステータスコードのロード
   └─ StockHistoryStatusを事前ロード
5. 履歴リストの表示
   └─ 各履歴エントリをListTileとして描画
6. スクロールによる追加ロード
   └─ 次のページをリクエスト
```

### フローチャート

```mermaid
flowchart TD
    A[在庫詳細画面から遷移] --> B[StockItemHistoryWidget初期化]
    B --> C[PaginatedStockHistoryList生成]
    C --> D[requestPage呼び出し]
    D --> E[StockHistoryStatus.load]
    E --> F[listPaginated API呼び出し]
    F --> G{データ取得成功?}
    G -->|Yes| H[buildItemで各履歴を描画]
    G -->|No| I[エラー表示]
    H --> J[スクロール検知]
    J --> K{追加データ必要?}
    K -->|Yes| D
    K -->|No| L[表示完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-21-01 | 降順表示 | 履歴は日時の降順（新しい順）で表示する | 常時 |
| BR-21-02 | ユーザー情報表示 | 操作者情報がある場合のみユーザー名を表示 | user_detailが存在する場合 |
| BR-21-03 | 備考表示 | notesが空でない場合のみサブタイトルとして表示 | notes.isNotEmpty |

### 計算ロジック

履歴エントリの`deltas`から数量変更を抽出する際、`simpleNumberString`関数で数値を適切にフォーマットする。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 履歴取得 | stock_tracking | SELECT | 在庫追跡履歴を取得 |

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

#### stock_tracking（APIエンドポイント: stock/track/）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | item | WHERE item = :stockItemId | 対象在庫のみ |
| SELECT | date | ORDER BY date DESC | 降順ソート |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | 認証エラー | トークン無効 | 再ログインを促す |
| 403 | 権限エラー | stockロール未付与 | 権限不足メッセージ表示 |
| 500 | サーバーエラー | サーバー側障害 | リトライを促す |

### リトライ仕様

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

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

参照のみのため、トランザクション管理不要。

## パフォーマンス要件

- 1ページあたり25件を取得
- 無限スクロールによる遅延読み込み
- キャッシュは行わず常に最新データを取得

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

- トークンベース認証による保護
- stockロールを持つユーザーのみアクセス可能
- HTTPS通信（設定による）

## 備考

- デフォルトフィルタとして`ordering: "-date"`と`user_detail: "true"`が設定される
- フィルタオプションは現時点では未実装（TODOコメントあり）

---

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

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

### 推奨読解順序

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

まず、履歴データを表現するモデルクラスを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | stock.dart | `lib/inventree/stock.dart` | InvenTreeStockItemHistoryクラスの構造（79-129行目） |

**読解のコツ**: `InvenTreeModel`を継承しており、`getString`, `getDate`, `getMap`などのヘルパーメソッドでJSONデータにアクセスする。

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

画面のウィジェット構造と状態管理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | stock_item_history.dart | `lib/widget/stock/stock_item_history.dart` | StockItemHistoryWidgetとその状態クラス（11-39行目） |

**主要処理フロー**:
1. **11-19行目**: StatefulWidgetの定義、在庫アイテムをコンストラクタで受け取る
2. **27-28行目**: AppBarのタイトルを多言語対応で設定
3. **34-38行目**: PaginatedStockHistoryListを生成し、フィルタを設定

#### Step 3: ページネーション処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | stock_item_history.dart | `lib/widget/stock/stock_item_history.dart` | PaginatedStockHistoryListとその状態クラス（44-101行目） |
| 3-2 | paginator.dart | `lib/widget/paginator.dart` | PaginatedSearchWidgetの基底クラス（1-200行目） |

**主要処理フロー**:
- **74-88行目**: requestPageメソッドでAPIからデータを取得
- **79行目**: StockHistoryStatusをロードして状態コードを取得
- **81-85行目**: listPaginatedでページネーション付きデータ取得
- **91-100行目**: buildItemでListTileを構築

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

```
StockItemHistoryWidget
    │
    ├─ _StockItemHistoryDisplayState
    │      └─ getBody() → PaginatedStockHistoryList生成
    │
    └─ PaginatedStockHistoryList
           │
           └─ _PaginatedStockHistoryState
                  │
                  ├─ requestPage()
                  │      ├─ InvenTreeAPI().StockHistoryStatus.load()
                  │      └─ InvenTreeStockItemHistory().listPaginated()
                  │
                  └─ buildItem()
                         └─ ListTile構築
```

### データフロー図

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

InvenTreeStockItem ───▶ StockItemHistoryWidget ───▶ 履歴一覧画面
       │                        │
       │                        ▼
       │                 PaginatedStockHistoryList
       │                        │
       ▼                        ▼
   item.pk ─────────▶ API: stock/track/?item={pk}
                               │
                               ▼
                     InvenTreeStockItemHistory[]
                               │
                               ▼
                          ListTile[]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| stock_item_history.dart | `lib/widget/stock/stock_item_history.dart` | ソース | 履歴表示ウィジェット |
| stock.dart | `lib/inventree/stock.dart` | ソース | 在庫関連モデル定義 |
| paginator.dart | `lib/widget/paginator.dart` | ソース | ページネーション基底クラス |
| refreshable_state.dart | `lib/widget/refreshable_state.dart` | ソース | 更新可能な状態の基底クラス |
| api.dart | `lib/api.dart` | ソース | API通信処理 |
| l10.dart | `lib/l10.dart` | ソース | 多言語対応 |
