# 機能設計書 26-発注明細表示

## 概要

本ドキュメントは、InvenTreeアプリにおける発注明細表示機能の設計を記載する。発注に含まれる明細行（ラインアイテム）の一覧表示および個別の明細詳細表示を提供する。

### 本機能の処理概要

**業務上の目的・背景**：発注業務において、発注に含まれる各品目の数量、単価、受入進捗を確認することは必須である。本機能により、発注明細を一覧形式で確認し、各明細の詳細情報（サプライヤーパーツ、受入状況、価格等）にアクセスできる。

**機能の利用シーン**：発注詳細画面のLine Itemsタブで発注明細一覧を確認する際、または個別の明細をタップして詳細画面を表示する際に利用される。受入進捗の確認、明細情報の確認に活用。

**主要な処理内容**：
1. 発注IDに基づいて明細行をページネーション形式で取得
2. 各明細のSKU、パーツ名、受入進捗を一覧表示
3. 明細タップで詳細画面を表示
4. 詳細画面でパーツ情報、サプライヤーパーツ情報、価格情報等を表示
5. 詳細画面から受入処理を実行可能

**関連システム・外部連携**：InvenTree REST API（`order/po-line/`エンドポイント）と連携。

**権限による制御**：`purchase_order`ロールを持つユーザーが閲覧可能。編集にはcanEdit権限、受入にはcanCreate権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 27 | 購入注文詳細画面 | 遷移元画面 | ラインアイテムタブで発注明細一覧表示 |

## 機能種別

データ参照 / 一覧表示 / 詳細表示

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| order | int | Yes | 発注ID | 正の整数 |
| limit | int | No | 取得件数上限 | デフォルト25件 |
| offset | int | No | 取得開始位置 | デフォルト0 |
| pending | bool | No | 未完了のみ表示 | - |
| received | bool | No | 受入済みのみ表示 | - |

### 入力データソース

発注詳細画面から渡される発注IDを使用。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| SKU | String | サプライヤーパーツのSKU |
| partName | String | 内部パーツ名 |
| quantity | double | 発注数量 |
| received | double | 受入済み数量 |
| progressString | String | 進捗表示文字列（例: "50 / 100"） |
| purchasePrice | double | 単価 |
| reference | String | 参照番号 |
| destination | InvenTreeStockLocation | 受入先ロケーション |

### 出力先

画面（リストビュー形式 / 詳細タイル形式）

## 処理フロー

### 処理シーケンス

```
1. 一覧表示（PaginatedPOLineList）
   └─ requestPage()で明細データ取得
2. 各明細をListTileで表示
   ├─ SKUとパーツ名
   ├─ 進捗（received / quantity）
   └─ サムネイル画像
3. 明細タップ
   ├─ item.reload()で最新データ取得
   └─ POLineDetailWidgetへ遷移
4. 詳細画面表示
   ├─ 内部パーツ情報
   ├─ サプライヤーパーツ情報
   ├─ 受入先ロケーション
   ├─ 受入進捗
   ├─ 参照番号
   ├─ 単価
   ├─ 備考
   └─ 外部リンク
5. アクション（詳細画面）
   ├─ 編集ボタン（canEdit時）
   └─ 受入ボタン（未完了時）
```

### フローチャート

```mermaid
flowchart TD
    A[発注詳細画面Line Itemsタブ] --> B[PaginatedPOLineList表示]
    B --> C[requestPage呼び出し]
    C --> D[listPaginated API呼び出し]
    D --> E{データ取得成功?}
    E -->|Yes| F[buildItemで各明細を描画]
    E -->|No| G[エラー表示]
    F --> H[明細タップ?]
    H -->|Yes| I[item.reload]
    H -->|No| J[スクロール継続]
    I --> K[POLineDetailWidget遷移]
    K --> L[詳細情報表示]
    L --> M[アクションボタン待機]
    M --> N{アクション種別}
    N -->|編集| O[_editLineItem]
    N -->|受入| P[receiveLineItem]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-26-01 | 進捗色分け | 完了時は緑、未完了時はオレンジで進捗表示 | 常時 |
| BR-26-02 | サプライヤーパーツ必須 | サプライヤーパーツがない場合はエラー表示 | supplierPart == null |
| BR-26-03 | 受入ボタン表示 | 未完了の場合のみ受入ボタン表示 | !isComplete |
| BR-26-04 | 編集ボタン表示 | canEdit時のみ編集ボタン表示 | canEdit == true |
| BR-26-05 | 受入先推定 | 受入先未設定時は発注の受入先を使用 | destinationId == 0 |

### 計算ロジック

- `progressRatio = received / quantity`（0〜1の範囲）
- `progressString = simpleNumberString(received) + " / " + simpleNumberString(quantity)`
- `isComplete = received >= quantity`
- `outstanding = quantity - received`（受入残数）

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 一覧取得 | purchase_order_line | SELECT | 発注明細を取得 |
| 詳細取得 | purchase_order_line | SELECT | 明細詳細を取得 |
| 受入処理 | stock_item | INSERT | 受入在庫を作成 |

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

#### purchase_order_line（APIエンドポイント: order/po-line/）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | order | WHERE order = :orderId | 発注でフィルタ |
| SELECT | part_detail | true | パーツ詳細を含む |
| SELECT | order_detail | true | 発注詳細を含む |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | 認証エラー | トークン無効 | 再ログインを促す |
| 403 | 権限エラー | purchase_orderロール未付与 | 権限不足メッセージ表示 |
| 404 | Not Found | 明細が存在しない | 一覧に戻る |
| 500 | サーバーエラー | サーバー側障害 | リトライを促す |

### リトライ仕様

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

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

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

## パフォーマンス要件

- 1ページあたり25件を取得
- 無限スクロールによる遅延読み込み
- 詳細遷移時にローディングオーバーレイ表示

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

- トークンベース認証による保護
- purchase_orderロールを持つユーザーのみアクセス可能

## 備考

- ソートオプション: part, SKU, quantity
- フィルタオプション: pending, received
- サプライヤーパーツ未設定の場合はエラータイルを表示

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | purchase_order.dart | `lib/inventree/purchase_order.dart` | InvenTreePOLineItemクラス（159-313行目） |
| 1-2 | orders.dart | `lib/inventree/orders.dart` | InvenTreeOrderLine基底クラス（86-124行目） |

**読解のコツ**: `InvenTreePOLineItem`は`InvenTreeOrderLine`を継承し、発注明細固有のプロパティ（received、isComplete、progressRatio等）を定義している。

#### Step 2: 一覧表示処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | po_line_list.dart | `lib/widget/order/po_line_list.dart` | PaginatedPOLineListの全体構造（19-110行目） |

**主要処理フロー**:
1. **19-28行目**: PaginatedSearchWidgetの継承、フィルタ受け取り
2. **41-45行目**: orderingOptionsでソートオプション定義
3. **48-59行目**: filterOptionsでフィルタオプション定義
4. **62-73行目**: requestPageでAPIからデータ取得
5. **76-109行目**: buildItemでListTile構築

#### Step 3: 詳細表示処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | po_line_detail.dart | `lib/widget/order/po_line_detail.dart` | POLineDetailWidgetの全体構造（23-259行目） |

**主要処理フロー**:
- **44-59行目**: appBarActionsで編集ボタン設定
- **62-81行目**: actionButtonsで受入ボタン設定
- **84-110行目**: requestでdestination取得
- **113-125行目**: _editLineItemで編集フォーム表示
- **128-136行目**: receiveLineItemで受入フォーム表示
- **139-258行目**: getTilesで詳細タイル構築

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

```
PurchaseOrderDetailWidget
    │
    └─ getTabs()
           │
           └─ PaginatedPOLineList
                  │
                  └─ _PaginatedPOLineListState
                         │
                         ├─ requestPage()
                         │      └─ InvenTreePOLineItem().listPaginated()
                         │
                         └─ buildItem()
                                │
                                └─ ListTile構築
                                       │
                                       └─ onTap → POLineDetailWidget遷移
                                              │
                                              └─ _POLineDetailWidgetState
                                                     │
                                                     ├─ request()
                                                     │      └─ destination取得
                                                     │
                                                     ├─ getTiles()
                                                     │      └─ 詳細タイル構築
                                                     │
                                                     ├─ _editLineItem()
                                                     │
                                                     └─ receiveLineItem()
```

### データフロー図

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

order.pk ─────────────▶ PaginatedPOLineList
                               │
                               ▼
               API: order/po-line/?order={pk}
                               │
                               ▼
                  InvenTreePOLineItem[]
                               │
                               ▼
                         buildItem()
                               │
                               ▼
                          ListTile[]
             (SKU・パーツ名・進捗・サムネイル)
                               │
                               ▼
                    onTap → POLineDetailWidget
                               │
                               ▼
                          getTiles()
                               │
                               ▼
     詳細タイル（パーツ情報・価格・進捗・リンク等）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| po_line_list.dart | `lib/widget/order/po_line_list.dart` | ソース | 発注明細一覧ウィジェット |
| po_line_detail.dart | `lib/widget/order/po_line_detail.dart` | ソース | 発注明細詳細ウィジェット |
| purchase_order.dart | `lib/inventree/purchase_order.dart` | ソース | 発注明細モデル定義 |
| orders.dart | `lib/inventree/orders.dart` | ソース | オーダーライン基底モデル |
| paginator.dart | `lib/widget/paginator.dart` | ソース | ページネーション基底クラス |
| refreshable_state.dart | `lib/widget/refreshable_state.dart` | ソース | 更新可能な状態の基底クラス |
| progress.dart | `lib/widget/progress.dart` | ソース | プログレスバー |
| api.dart | `lib/api.dart` | ソース | API通信処理 |
| helpers.dart | `lib/helpers.dart` | ソース | ヘルパー関数（renderCurrency等） |
