# 機能設計書 33-受注詳細表示

## 概要

本ドキュメントは、InvenTreeモバイルアプリにおける受注（Sales Order）詳細表示機能の設計を定義する。受注詳細画面は、個々の受注に関する包括的な情報を表示し、受注の編集・発行・キャンセル・明細追加・出荷管理などの操作を提供する中心的な画面である。

### 本機能の処理概要

この機能では、個々の受注（Sales Order）の詳細情報を表示し、受注のライフサイクル管理（発行・キャンセル）、明細行管理、出荷管理、添付ファイル管理などの包括的な操作を提供する。

**業務上の目的・背景**：受注詳細画面は、顧客からの注文の全容を把握し、適切な処理を行うための中心的なインターフェースである。受注の進捗状況（明細の完了率、出荷状況）を視覚的に確認でき、顧客への対応、在庫引当、出荷手配などの意思決定を支援する。また、受注に関連するすべての情報（顧客情報、プロジェクトコード、添付ファイル、ノート、パラメータ）を一元的に管理できる。

**機能の利用シーン**：
- 受注の詳細内容を確認したい場合
- 受注のステータスを変更（発行・キャンセル）したい場合
- 受注に明細行を追加したい場合
- 出荷を作成・管理したい場合
- バーコードスキャンで在庫を引き当てたい場合
- 受注に添付ファイルや画像をアップロードしたい場合

**主要な処理内容**：
1. 受注の詳細情報をAPIから取得・表示
2. 顧客情報、プロジェクトコード、参照番号、日付情報の表示
3. 明細行の進捗状況をプログレスバーで表示
4. 出荷の進捗状況をプログレスバーで表示
5. タブ切り替えで詳細・明細行・出荷の各ビューを表示
6. 受注の発行・キャンセル操作
7. 明細行・出荷の追加操作
8. バーコードスキャンによる在庫引当

**関連システム・外部連携**：
- InvenTree REST API (`/api/order/so/`, `/api/order/so/{pk}/issue/`, `/api/order/so/{pk}/cancel/`, `/api/order/so/{pk}/allocate/`)
- バーコードスキャン機能（SOAddItemBarcodeHandler, SOAllocateStockHandler）

**権限による制御**：
- 受注の編集権限がある場合のみ、編集ボタン・発行・キャンセル・画像アップロード操作が可能
- 明細行の作成権限がある場合のみ、明細追加・出荷追加操作が可能
- バーコード引当はAPIバージョン依存（supportsBarcodeSOAllocateEndpoint）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 28 | 販売注文一覧画面 | 遷移元画面 | 受注選択時に受注詳細画面へ遷移 |
| 29 | 販売注文詳細画面 | 主機能 | 受注の詳細情報表示と各種操作 |
| 31 | 会社詳細画面 | 遷移先画面 | 顧客項目押下時に会社詳細画面へ遷移 |

## 機能種別

データ表示（CRUD操作のRead・Update）/ 詳細表示 / ステータス変更

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| order | InvenTreeSalesOrder | Yes | 対象の受注オブジェクト | PKが1以上であること |

### 入力データソース

- 受注一覧画面から渡される受注オブジェクト
- InvenTree REST API（詳細情報のリロード）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| reference | String | 受注参照番号 |
| description | String | 受注の説明 |
| status | int | 受注ステータスコード |
| customer | InvenTreeCompany | 顧客情報 |
| customerReference | String | 顧客参照番号 |
| projectCode | String | プロジェクトコード |
| startDate | String | 開始日 |
| targetDate | String | 目標日 |
| shipmentDate | String | 出荷完了日 |
| lineItemCount | int | 明細行数 |
| completedLineItemCount | int | 完了済み明細行数 |
| shipmentCount | int | 出荷数 |
| completedShipmentCount | int | 完了済み出荷数 |
| responsibleName | String | 責任者名 |
| responsibleLabel | String | 責任者種別（user/group） |

### 出力先

画面表示（タブ構成：詳細タブ、明細行タブ、出荷タブ）

## 処理フロー

### 処理シーケンス

```
1. ウィジェット初期化
   └─ SalesOrderDetailWidgetが受注オブジェクトを受け取る
2. データ読み込み
   ├─ 受注データのリロード
   ├─ SalesOrderStatusの読み込み
   ├─ プロジェクトコードサポート確認
   ├─ カメラショートカット設定確認
   ├─ パラメータ数のカウント
   ├─ 添付ファイル数のカウント
   └─ 追加明細行数のカウント
3. 画面構築
   ├─ AppBarにタイトルと編集ボタン
   ├─ タブ構成（詳細・明細行・出荷）
   └─ SpeedDialボタン（アクション・バーコード）
4. ユーザー操作
   ├─ タブ切り替え
   ├─ 顧客タップ → 会社詳細画面へ遷移
   ├─ ノートタップ → ノート画面へ遷移
   ├─ 添付ファイルタップ → 添付ファイル画面へ遷移
   ├─ 発行ボタン → 確認ダイアログ → issueOrder()
   ├─ キャンセルボタン → 確認ダイアログ → cancelOrder()
   ├─ 明細追加ボタン → 作成フォーム
   ├─ 出荷追加ボタン → 作成フォーム
   └─ バーコードスキャン → 在庫引当
```

### フローチャート

```mermaid
flowchart TD
    A[画面表示開始] --> B[受注オブジェクト受け取り]
    B --> C[order.reload]
    C --> D[SalesOrderStatus.load]
    D --> E[各種カウント取得]
    E --> F[画面構築]
    F --> G{ステータス確認}
    G -->|Pending| H[発行ボタン表示]
    G -->|Open| I[キャンセルボタン表示]
    G -->|その他| J[アクションなし]
    H --> K[タブ表示]
    I --> K
    J --> K
    K --> L{ユーザー操作}
    L -->|詳細タブ| M[詳細タイル表示]
    L -->|明細タブ| N[PaginatedSOLineList]
    L -->|出荷タブ| O[PaginatedSOShipmentList]
    L -->|発行| P[issueOrder実行]
    L -->|キャンセル| Q[cancelOrder実行]
    L -->|明細追加| R[createForm表示]
    P --> S[refresh]
    Q --> S
    R --> S
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-033-01 | 編集ボタン表示 | 受注の編集権限がある場合のみ編集ボタンを表示 | 常時 |
| BR-033-02 | 発行ボタン表示 | 受注がPending/On Holdの場合のみ発行ボタンを表示 | isPending == true |
| BR-033-03 | キャンセルボタン表示 | 受注がOpen（Pending/In Progress/On Hold）の場合のみキャンセルボタンを表示 | isOpen == true |
| BR-033-04 | 明細追加条件 | 受注がPendingまたはIn Progressで、明細行作成権限がある場合のみ | isPending または isInProgress |
| BR-033-05 | プロジェクトコード表示 | サーバーがプロジェクトコードをサポートし、PROJECT_CODES_ENABLEDが有効な場合のみ | API条件 |
| BR-033-06 | カメラショートカット | INV_SO_SHOW_CAMERA設定がtrueの場合のみカメラボタン表示 | 設定依存 |
| BR-033-07 | バーコード引当 | supportsBarcodeSOAllocateEndpointがtrueの場合のみバーコード引当ボタン表示 | API条件 |

### 計算ロジック

進捗表示ロジック:
```dart
// 明細行進捗色
Color lineColor = widget.order.complete ? COLOR_SUCCESS : COLOR_WARNING;
// 進捗表示: "completedLineItemCount / lineItemCount"
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 詳細取得 | order_salesorder | SELECT | 受注詳細情報取得 |
| 編集 | order_salesorder | UPDATE | 受注情報更新 |
| 発行 | order_salesorder | UPDATE | ステータスをIN_PROGRESSに更新 |
| キャンセル | order_salesorder | UPDATE | ステータスをCANCELLEDに更新 |

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

#### order_salesorder

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | 全カラム | pk = 指定ID | customer_detail含む |
| UPDATE（発行） | status | IN_PROGRESS | /issue/エンドポイント |
| UPDATE（キャンセル） | status | CANCELLED | /cancel/エンドポイント |

## エラー処理

### エラーケース一覧

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

### リトライ仕様

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

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

- 詳細取得：読み取り専用
- 編集・発行・キャンセル：API側でトランザクション管理

## パフォーマンス要件

- 初回表示時に受注データをリロード
- パラメータ・添付ファイル・追加明細行の件数は非同期で取得
- 明細行・出荷はページネーション（タブ切り替え時に取得）

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

- APIアクセスには認証トークンが必要
- 受注の閲覧権限（sales_order）が必要
- 編集操作には編集権限が必要
- 添付ファイルアップロードはInvenTreeAttachmentで処理

## 備考

- タブ構成: 詳細（Details）、明細行（Line Items）、出荷（Shipments）
- 追加明細行へのアクセスは詳細タブ内のListTileから
- バーコード引当機能はAPIバージョン依存

---

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

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

### 推奨読解順序

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

受注のデータモデルとステータス管理を理解する。

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

**読解のコツ**: ステータス判定メソッド（isOpen, isPending, isInProgress, isComplete）はapi.SalesOrderStatus.isNameIn()を使用している。issueOrder()とcancelOrder()は各エンドポイントへのPOSTリクエストを発行する。

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

詳細画面の構成を把握する。

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

**主要処理フロー**:
1. **30-37行目**: SalesOrderDetailWidgetクラス定義
2. **39-47行目**: State変数（lines, extraLineCount, attachmentCount等）
3. **50-59行目**: getAppBarTitle()。受注参照番号を含むタイトル
4. **61-77行目**: appBarActions()。編集ボタン構築
5. **156-221行目**: actionButtons()。発行・キャンセル・追加ボタン
6. **223-259行目**: barcodeButtons()。バーコード関連ボタン

#### Step 3: データ読み込み処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sales_order_detail.dart | `lib/widget/order/sales_order_detail.dart` | request()メソッド（261-307行目） |

**主要処理フロー**:
- **263行目**: order.reload()で最新データ取得
- **264行目**: api.SalesOrderStatus.load()でステータス情報読み込み
- **266-275行目**: プロジェクトコードサポート確認とカメラ設定読み込み
- **277-306行目**: パラメータ・添付ファイル・追加明細行の件数を非同期カウント

#### Step 4: 画面タイル構築を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sales_order_detail.dart | `lib/widget/order/sales_order_detail.dart` | orderTiles()メソッド（353-539行目） |

**主要処理フロー**:
- **354行目**: headerTile()でヘッダーカード構築
- **358-368行目**: プロジェクトコード表示
- **370-382行目**: 顧客情報タイル（タップで詳細画面遷移）
- **394-410行目**: 明細行進捗タイル（ProgressBar使用）
- **412-428行目**: 出荷進捗タイル
- **430-448行目**: 追加明細行タイル（タップでSOExtraLineListWidget遷移）

#### Step 5: タブ構成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | sales_order_detail.dart | `lib/widget/order/sales_order_detail.dart` | getTabIcons(), getTabs()（541-557行目） |

**主要処理フロー**:
- **542-547行目**: タブアイコン定義（Details, Line Items, Shipments）
- **550-557行目**: 各タブの内容（ListView, PaginatedSOLineList, PaginatedSOShipmentList）

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

```
SalesOrderDetailWidget
    │
    ├─ _SalesOrderDetailState
    │      ├─ getAppBarTitle() → "Sales Order - {reference}"
    │      ├─ appBarActions() → 編集ボタン
    │      │      └─ editOrder() → editForm表示
    │      │
    │      ├─ request()
    │      │      ├─ order.reload()
    │      │      ├─ api.SalesOrderStatus.load()
    │      │      ├─ api.getGlobalBooleanSetting()
    │      │      ├─ InvenTreeParameter().countParameters()
    │      │      ├─ InvenTreeAttachment().countAttachments()
    │      │      └─ InvenTreeSOExtraLineItem().count()
    │      │
    │      ├─ actionButtons()
    │      │      ├─ _uploadImage() → 画像アップロード
    │      │      ├─ _issueOrder() → 発行処理
    │      │      ├─ _cancelOrder() → キャンセル処理
    │      │      ├─ _addLineItem() → 明細追加
    │      │      └─ _addShipment() → 出荷追加
    │      │
    │      ├─ barcodeButtons()
    │      │      ├─ SOAddItemBarcodeHandler
    │      │      └─ SOAllocateStockHandler
    │      │
    │      ├─ orderTiles() → 詳細タブ内容
    │      │      ├─ headerTile()
    │      │      ├─ 顧客情報
    │      │      ├─ 明細行進捗
    │      │      ├─ 出荷進捗
    │      │      ├─ 追加明細行 → SOExtraLineListWidget
    │      │      ├─ 日付情報
    │      │      ├─ ノート → NotesWidget
    │      │      ├─ パラメータ → ShowParametersItem
    │      │      └─ 添付ファイル → ShowAttachmentsItem
    │      │
    │      └─ getTabs()
    │             ├─ ListView(orderTiles)
    │             ├─ PaginatedSOLineList
    │             └─ PaginatedSOShipmentList
```

### データフロー図

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

受注オブジェクト ───▶ SalesOrderDetailWidget
    │                       │
    │                       ▼
    │                   request()
    │                       │
    │               ┌───────┴───────┐
    │               ▼               ▼
    │       order.reload()   非同期カウント取得
    │               │               │
    │               ▼               ▼
    │       SalesOrderStatus   パラメータ数
    │           .load()        添付ファイル数
    │                          追加明細行数
    │                               │
    └───────────────────────────────┘
                    │
                    ▼
            orderTiles() 構築
                    │
        ┌───────────┼───────────┐
        ▼           ▼           ▼
    詳細タブ    明細タブ    出荷タブ
    (ListView)  (Paginated  (Paginated
                SOLineList) SOShipmentList)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sales_order_detail.dart | `lib/widget/order/sales_order_detail.dart` | ソース | 受注詳細ウィジェット |
| sales_order.dart | `lib/inventree/sales_order.dart` | ソース | 受注データモデル |
| so_line_list.dart | `lib/widget/order/so_line_list.dart` | ソース | 受注明細行一覧 |
| so_shipment_list.dart | `lib/widget/order/so_shipment_list.dart` | ソース | 出荷一覧 |
| so_extra_line_list.dart | `lib/widget/order/so_extra_line_list.dart` | ソース | 追加明細行一覧 |
| company.dart | `lib/inventree/company.dart` | ソース | 会社（顧客）データモデル |
| barcode.dart | `lib/barcode/barcode.dart` | ソース | バーコードスキャン共通 |
| sales_order.dart | `lib/barcode/sales_order.dart` | ソース | 受注用バーコードハンドラ |
| attachment.dart | `lib/inventree/attachment.dart` | ソース | 添付ファイル管理 |
| parameter.dart | `lib/inventree/parameter.dart` | ソース | パラメータ管理 |
| notes_widget.dart | `lib/widget/notes_widget.dart` | ソース | ノート表示・編集 |
| attachment_widget.dart | `lib/widget/attachment_widget.dart` | ソース | 添付ファイルウィジェット |
| progress.dart | `lib/widget/progress.dart` | ソース | プログレスバーウィジェット |
| dialogs.dart | `lib/widget/dialogs.dart` | ソース | 確認ダイアログ |
| refreshable_state.dart | `lib/widget/refreshable_state.dart` | ソース | リフレッシュ可能State基底クラス |
