# 機能設計書 37-追加明細行表示

## 概要

本ドキュメントは、InvenTreeモバイルアプリにおける受注（Sales Order）の追加明細行表示機能の設計を定義する。追加明細行は、通常の受注明細（パーツに紐づく明細）とは別に、送料・手数料・税金などの追加費用を管理するための明細行である。

### 本機能の処理概要

この機能では、受注に対して登録された追加明細行（Extra Line Items）を一覧表示し、新規追加・詳細確認を行うことができる。

**業務上の目的・背景**：受注においては、製品の販売価格以外にも送料、梱包費、保険料、税金などの追加費用が発生することがある。これらの費用を受注に正確に反映させることで、顧客への請求金額の正確性を確保し、会計処理の精度を向上させる必要がある。追加明細行機能は、このような付随費用を受注単位で管理し、受注の総額を正確に把握するために不可欠である。

**機能の利用シーン**：
- 受注詳細画面から追加費用の一覧を確認したい場合
- 受注に送料や手数料などの追加費用を追加登録したい場合
- 追加費用の内容を編集・確認したい場合

**主要な処理内容**：
1. 受注IDに紐づく追加明細行をAPIから取得
2. ページネーション対応の一覧として表示
3. 各明細行のリファレンス、説明、数量を表示
4. 明細行タップで詳細画面へ遷移
5. 編集権限がある場合は新規追加ボタンを表示

**関連システム・外部連携**：InvenTree REST API (`/api/order/so-extra-line/`)

**権限による制御**：受注の編集権限（`sales_order` ロールの`change`権限）がある場合のみ、追加明細行の新規作成ボタンが表示される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 29 | 販売注文詳細画面 | 遷移元画面 | 追加明細項目押下時に追加明細一覧画面へ遷移 |

## 機能種別

データ表示（CRUD操作のRead）/ 一覧表示

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| order | InvenTreeSalesOrder | Yes | 対象の受注オブジェクト | PKが1以上であること |
| filters | Map<String, String> | No | 追加フィルタ条件 | - |

### 入力データソース

- 受注詳細画面から渡される受注オブジェクト
- InvenTree REST API (`/api/order/so-extra-line/`)

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| reference | String | 追加明細行のリファレンス番号 |
| description | String | 追加明細行の説明 |
| quantity | double | 数量 |

### 出力先

画面表示（ListTileのリスト形式）

## 処理フロー

### 処理シーケンス

```
1. ウィジェット初期化
   └─ SOExtraLineListWidgetが受注オブジェクトとフィルタを受け取る
2. 画面構築
   └─ PaginatedSOExtraLineListウィジェットを本体として構築
3. ページデータ取得
   └─ InvenTreeSOExtraLineItem().listPaginated()でAPIリクエスト
4. 一覧表示
   └─ 各アイテムをListTileとして描画
5. アイテムタップ時
   └─ 詳細画面へ遷移
6. 追加ボタンタップ時（権限がある場合）
   └─ 追加フォームを表示
```

### フローチャート

```mermaid
flowchart TD
    A[画面表示開始] --> B[受注オブジェクト受け取り]
    B --> C[PaginatedSOExtraLineList構築]
    C --> D{権限確認}
    D -->|編集権限あり| E[追加ボタン表示]
    D -->|権限なし| F[追加ボタン非表示]
    E --> G[APIからデータ取得]
    F --> G
    G --> H{データあり?}
    H -->|Yes| I[ListTileとして一覧表示]
    H -->|No| J[結果なしメッセージ表示]
    I --> K{ユーザー操作}
    K -->|アイテムタップ| L[詳細画面へ遷移]
    K -->|追加ボタン| M[追加フォーム表示]
    K -->|スクロール| N[次ページ取得]
    L --> O[終了]
    M --> O
    N --> G
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-037-01 | 追加ボタン表示制御 | 受注の編集権限がある場合のみ追加ボタンを表示 | 常時 |
| BR-037-02 | 受注フィルタ | 表示する追加明細行は指定された受注に紐づくもののみ | 常時 |
| BR-037-03 | ページサイズ | 1ページあたり25件を取得 | 常時 |

### 計算ロジック

該当なし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 一覧取得 | order_salesorderextraline | SELECT | 受注IDで絞り込んだ追加明細行を取得 |

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

#### order_salesorderextraline

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, reference, description, quantity, price, price_currency, order_id | order_id = 指定受注ID | ページネーション適用 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | 認証エラー | APIトークンが無効 | ログイン画面へ遷移 |
| 403 | 権限エラー | 閲覧権限がない | エラーメッセージ表示 |
| 404 | 不存在エラー | 受注が存在しない | 前画面へ戻る |
| 500 | サーバーエラー | サーバー側の問題 | リトライを促すメッセージ表示 |

### リトライ仕様

プルダウンによるリフレッシュ操作で再取得可能

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

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

## パフォーマンス要件

- 1ページあたり25件のデータを取得
- 無限スクロールによる段階的データ読み込み

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

- APIアクセスには認証トークンが必要
- 受注の閲覧権限（sales_order）が必要
- 追加操作には受注の編集権限が必要

## 備考

- 追加明細行の詳細画面はExtraLineDetailWidgetで共通化されている
- 発注と受注の追加明細行は別クラス（InvenTreePOExtraLineItem, InvenTreeSOExtraLineItem）だが、同様の構造を持つ
- 受注詳細画面から遷移する際、orderフィルタが自動設定される

---

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

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

### 推奨読解順序

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

まず、追加明細行のデータモデルを理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sales_order.dart | `lib/inventree/sales_order.dart` | InvenTreeSOExtraLineItemクラスの構造（234-257行目） |

**読解のコツ**: InvenTreeSOExtraLineItemはInvenTreeExtraLineItemを継承している。ExtraLineItemの基底クラスは`lib/inventree/orders.dart`に定義されており、reference, description, quantityなどの共通プロパティを持つ。

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

一覧画面の構成を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | so_extra_line_list.dart | `lib/widget/order/so_extra_line_list.dart` | SOExtraLineListWidgetの構造全体 |

**主要処理フロー**:
1. **15-26行目**: SOExtraLineListWidgetクラス定義。受注オブジェクトとフィルタを受け取る
2. **28-74行目**: _SalesOrderExtraLineListWidgetStateクラス。RefreshableStateを継承
3. **35-49行目**: _addLineItem()メソッド。追加フォームの表示処理
4. **51-67行目**: actionButtons()メソッド。編集権限確認と追加ボタン構築

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | so_extra_line_list.dart | `lib/widget/order/so_extra_line_list.dart` | PaginatedSOExtraLineListクラス（76-124行目） |

**主要処理フロー**:
- **96-107行目**: requestPage()メソッド。APIからページデータを取得
- **109-123行目**: buildItem()メソッド。各アイテムのListTile構築

#### Step 4: 利用箇所を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sales_order_detail.dart | `lib/widget/order/sales_order_detail.dart` | SOExtraLineListWidgetの利用箇所（430-448行目） |

**主要処理フロー**:
- **431-447行目**: 追加明細行タイルのListTile構築とタップ時の遷移処理

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

```
SalesOrderDetailWidget
    │
    └─ orderTiles()
           └─ ListTile（追加明細行）
                  └─ onTap → Navigator.push
                         └─ SOExtraLineListWidget

SOExtraLineListWidget
    │
    ├─ _SalesOrderExtraLineListWidgetState
    │      ├─ getAppBarTitle() → "Extra Line Items"
    │      ├─ actionButtons() → 追加ボタン構築
    │      │      └─ _addLineItem() → フォーム表示
    │      └─ getBody() → PaginatedSOExtraLineList
    │
    └─ PaginatedSOExtraLineList
           └─ _PaginatedSOExtraLineListState
                  ├─ requestPage() → API呼び出し
                  │      └─ InvenTreeSOExtraLineItem().listPaginated()
                  └─ buildItem() → ListTile構築
                         └─ line.goToDetailPage() → 詳細画面遷移
```

### データフロー図

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

受注オブジェクト ───▶ SOExtraLineListWidget ───▶ アプリバータイトル
    │                       │
    │                       ▼
    │               PaginatedSOExtraLineList
    │                       │
    ▼                       ▼
フィルタ条件 ───────▶ requestPage()
                            │
                            ▼
                    InvenTreeAPI
                    /api/order/so-extra-line/
                            │
                            ▼
                    InvenTreePageResponse
                            │
                            ▼
                    buildItem() ───▶ ListTile一覧
                            │
                            ▼
                    onTap ───▶ 詳細画面遷移
                            (ExtraLineDetailWidget)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| so_extra_line_list.dart | `lib/widget/order/so_extra_line_list.dart` | ソース | 追加明細行一覧ウィジェット |
| sales_order.dart | `lib/inventree/sales_order.dart` | ソース | 受注・追加明細行データモデル |
| orders.dart | `lib/inventree/orders.dart` | ソース | ExtraLineItem基底クラス |
| sales_order_detail.dart | `lib/widget/order/sales_order_detail.dart` | ソース | 受注詳細画面（利用箇所） |
| paginator.dart | `lib/widget/paginator.dart` | ソース | ページネーション共通処理 |
| refreshable_state.dart | `lib/widget/refreshable_state.dart` | ソース | リフレッシュ可能State基底クラス |
| extra_line_detail.dart | `lib/widget/order/extra_line_detail.dart` | ソース | 追加明細行詳細画面 |
| l10.dart | `lib/l10.dart` | ソース | 多言語対応文字列 |
