# 画面設計書 29-販売注文詳細画面

## 概要

本ドキュメントは、InvenTree Flutterアプリケーションにおける「販売注文詳細画面」の設計仕様を定義する。販売注文（SalesOrder）の詳細情報を表示し、注文のライフサイクル管理（発行、キャンセル）や明細行の管理、出荷管理を行う画面である。

### 本画面の処理概要

販売注文詳細画面は、選択した販売注文の詳細情報を3つのタブ（詳細、ラインアイテム、出荷）に分けて表示する画面である。ユーザーは注文の編集、明細行の追加、出荷の追加、注文の発行・キャンセルなどの操作を行える。

**業務上の目的・背景**：販売管理において、受注した注文の詳細を確認し、そのライフサイクルを管理することは必須の機能である。本画面では、注文ステータスに応じたアクション（発行、キャンセル）を提供し、明細行と出荷の進捗を視覚的に確認できる。バーコードスキャンによる在庫引当もサポートする。

**画面へのアクセス方法**：
- 販売注文一覧画面から注文をタップ
- バーコードスキャンで販売注文を識別した場合

**主要な操作・処理内容**：
1. 販売注文詳細情報の表示（顧客、ステータス、日付等）
2. 販売注文の編集
3. ラインアイテム（明細行）の追加
4. 出荷（Shipment）の追加
5. 注文の発行（Issue）
6. 注文のキャンセル
7. バーコードスキャンによる明細追加・在庫引当
8. 画像撮影・添付ファイルアップロード
9. ノート・パラメータ・添付ファイルの閲覧

**画面遷移**：
- 遷移元：販売注文一覧画面、バーコードスキャン画面
- 遷移先：会社詳細画面、追加明細一覧画面、ノート画面、パラメータ画面、添付ファイル画面、ラインアイテム詳細画面、出荷詳細画面

**権限による表示制御**：
- 編集ボタンは `order.canEdit` がtrueの場合のみ表示
- カメラボタンは `showCameraShortcut && order.canEdit` の場合のみ表示
- 明細追加・出荷追加は `(isPending || isInProgress) && SOLineItem.canCreate` の場合のみ表示
- バーコード機能も同様の条件

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 33 | 受注詳細表示 | 主機能 | 受注の詳細情報（顧客、ステータス、ラインアイテム等）表示 |
| 34 | 受注明細表示 | 補助機能 | ラインアイテムタブで受注明細一覧表示 |
| 35 | 受注引当表示 | 補助機能 | 受注に対する在庫引当情報の表示 |
| 36 | 出荷管理 | 補助機能 | 出荷タブで出荷一覧表示・出荷追加 |
| 37 | 追加明細行表示 | 遷移先機能 | 追加明細項目押下時に追加明細一覧画面へ遷移 |
| 48 | 受注引当スキャン | 補助機能 | バーコードスキャンで受注に在庫を引き当て |
| 54 | 添付ファイル表示 | 補助機能 | 添付ファイル項目押下時に添付ファイル一覧表示 |
| 55 | 添付ファイルアップロード | 補助機能 | カメラボタン押下時に画像撮影・アップロード |
| 56 | ノート表示・編集 | 遷移先機能 | ノート項目押下時にノート画面へ遷移 |
| 39 | 会社詳細表示 | 遷移先機能 | 顧客項目押下時に会社詳細画面へ遷移 |

## 画面種別

詳細

## URL/ルーティング

Flutter Navigator によるプッシュ遷移。`SalesOrderDetailWidget` ウィジェットに `InvenTreeSalesOrder` インスタンスを渡して表示する。

## 入出力項目

| 項目名 | 入出力 | 型 | 必須 | 説明 |
|--------|--------|------|------|------|
| order | 入力 | InvenTreeSalesOrder | Yes | 表示する販売注文オブジェクト |

## 表示項目

### タブ構成

| タブ名 | 内容 | ウィジェット |
|--------|------|-------------|
| Details | 注文詳細情報 | ListView(orderTiles) |
| Line Items | 明細行一覧 | PaginatedSOLineList |
| Shipments | 出荷一覧 | PaginatedSOShipmentList |

### 詳細タブ表示項目

| 項目名 | 表示位置 | データ型 | 条件 | 説明 |
|--------|----------|----------|------|------|
| リファレンス | headerTile.title | String | 常時 | 注文リファレンス番号 |
| 説明 | headerTile.subtitle | String | 常時 | 注文の説明 |
| 顧客サムネイル | headerTile.leading | Image | customer != null | 顧客会社画像 |
| ステータス | headerTile.trailing | String | 常時 | ステータスラベル（色付き） |
| プロジェクトコード | ListTile | String | supportsProjectCodes && hasProjectCode | プロジェクトコード情報 |
| 顧客 | ListTile | String | customer != null | 顧客会社名 |
| 顧客リファレンス | ListTile | String | customerReference.isNotEmpty | 顧客側の注文番号 |
| ラインアイテム進捗 | ListTile + ProgressBar | String | 常時 | 完了/総数と進捗バー |
| 出荷進捗 | ListTile + ProgressBar | String | shipmentCount > 0 | 完了出荷/総出荷数と進捗バー |
| 追加明細行 | ListTile | int | 常時 | 追加明細行の件数 |
| 開始日 | ListTile | String | startDate.isNotEmpty | 注文開始日 |
| 目標日 | ListTile | String | targetDate.isNotEmpty | 目標完了日 |
| 完了日 | ListTile | String | shipmentDate.isNotEmpty | 出荷完了日 |
| 責任者 | ListTile | String | responsibleName.isNotEmpty | 担当者/グループ |
| ノート | ListTile | - | 常時 | ノート画面へのリンク |
| パラメータ | ListTile | int | parameterCount > 0 | パラメータ件数と画面リンク |
| 添付ファイル | ListTile | int | attachmentCount > 0 | 添付ファイル件数と画面リンク |

## イベント仕様

### 1-編集ボタン押下

AppBarの編集ボタンをタップすると、販売注文編集フォームが表示される。

**処理フロー**：
1. `IconButton.onPressed` で `editOrder(context)` を呼び出し
2. `order.formFields()` でフォームフィールドを取得
3. customerフィールドを除外（顧客は編集不可）
4. contact、project_codeフィールドをAPIサポート状況に応じて除外
5. `order.editForm()` で編集フォームを表示
6. 成功時に画面をリフレッシュし、成功メッセージを表示

### 2-明細追加ボタン押下

SpeedDialの「明細追加」ボタンをタップすると、ラインアイテム追加フォームが表示される。

**表示条件**：`(order.isPending || order.isInProgress) && InvenTreeSOLineItem().canCreate`

**処理フロー**：
1. `SpeedDialChild.onTap` で `_addLineItem(context)` を呼び出し
2. `InvenTreeSOLineItem().formFields()` でフォームフィールドを取得
3. orderフィールドに現在の注文PKを設定し、非表示に
4. `InvenTreeSOLineItem().createForm()` で作成フォームを表示
5. 成功時に画面をリフレッシュ

### 3-出荷追加ボタン押下

SpeedDialの「出荷追加」ボタンをタップすると、出荷追加フォームが表示される。

**表示条件**：`(order.isPending || order.isInProgress) && InvenTreeSOLineItem().canCreate`

**処理フロー**：
1. `SpeedDialChild.onTap` で `_addShipment(context)` を呼び出し
2. `InvenTreeSalesOrderShipment().formFields()` でフォームフィールドを取得
3. orderフィールドに現在の注文PKを設定し、非表示に
4. `InvenTreeSalesOrderShipment().createForm()` で作成フォームを表示
5. 成功時に画面をリフレッシュ

### 4-発行ボタン押下

SpeedDialの「発行」ボタンをタップすると、注文発行確認ダイアログが表示される。

**表示条件**：`order.isPending`

**処理フロー**：
1. `SpeedDialChild.onTap` で `_issueOrder(context)` を呼び出し
2. `confirmationDialog()` で確認ダイアログを表示
3. 承認時に `order.issueOrder()` を呼び出し（POST `${url}issue/`）
4. 成功時に画面をリフレッシュ

### 5-キャンセルボタン押下

SpeedDialの「キャンセル」ボタンをタップすると、キャンセル確認ダイアログが表示される。

**表示条件**：`order.isOpen`

**処理フロー**：
1. `SpeedDialChild.onTap` で `_cancelOrder(context)` を呼び出し
2. `confirmationDialog()` で確認ダイアログを表示
3. 承認時に `order.cancelOrder()` を呼び出し（POST `${url}cancel/`）
4. 成功時に画面をリフレッシュ

### 6-カメラボタン押下

SpeedDialのカメラボタンをタップすると、画像撮影・アップロード処理が実行される。

**表示条件**：`showCameraShortcut && order.canEdit`

**処理フロー**：
1. `SpeedDialChild.onTap` で `_uploadImage(context)` を呼び出し
2. `InvenTreeAttachment().uploadImage()` で画像撮影・アップロード
3. 成功時に画面をリフレッシュ

### 7-バーコード明細追加スキャン

バーコードボタンをタップすると、明細追加スキャンモードが起動する。

**表示条件**：`(order.isInProgress || order.isPending) && InvenTreeSOLineItem().canCreate`

**処理フロー**：
1. `SpeedDialChild.onTap` で `scanBarcode()` を呼び出し
2. `SOAddItemBarcodeHandler(salesOrder: order)` をハンドラとして設定

### 8-バーコード在庫引当スキャン

バーコードボタンをタップすると、在庫引当スキャンモードが起動する。

**表示条件**：`(order.isInProgress || order.isPending) && InvenTreeSOLineItem().canCreate && api.supportsBarcodeSOAllocateEndpoint`

**処理フロー**：
1. `SpeedDialChild.onTap` で `scanBarcode()` を呼び出し
2. `SOAllocateStockHandler(salesOrder: order)` をハンドラとして設定

### 9-顧客タップ

顧客ListTileをタップすると、会社詳細画面へ遷移する。

**処理フロー**：
1. `ListTile.onTap` で `customer.goToDetailPage(context)` を呼び出し
2. `Navigator.push` で会社詳細画面へ遷移

### 10-追加明細行タップ

追加明細行ListTileをタップすると、追加明細一覧画面へ遷移する。

**処理フロー**：
1. `ListTile.onTap` で `Navigator.push` を呼び出し
2. `SOExtraLineListWidget` へ遷移

### 11-ノートタップ

ノートListTileをタップすると、ノート画面へ遷移する。

**処理フロー**：
1. `ListTile.onTap` で `Navigator.push` を呼び出し
2. `NotesWidget(order)` へ遷移

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 詳細表示 | SalesOrder | SELECT | 販売注文データの取得 |
| 編集 | SalesOrder | UPDATE | 販売注文データの更新 |
| 明細追加 | SOLineItem | INSERT | 新規明細行の作成 |
| 出荷追加 | SalesOrderShipment | INSERT | 新規出荷の作成 |
| 発行 | SalesOrder | UPDATE | ステータスをIN_PROGRESSに更新 |
| キャンセル | SalesOrder | UPDATE | ステータスをCANCELLEDに更新 |
| 画像アップロード | Attachment | INSERT | 添付ファイルの作成 |

### テーブル別更新項目詳細

#### SalesOrder テーブル

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | pk, reference, description, customer, status, start_date, target_date, shipment_date, responsible, completedLineItemCount, lineItemCount, shipmentCount, completedShipmentCount | pk指定 | APIエンドポイント: /api/order/so/{pk}/ |
| UPDATE（編集） | reference, description, project_code, start_date, target_date, link, responsible, contact | フォーム入力値 | editForm()経由 |
| UPDATE（発行） | status | IN_PROGRESS | POST /api/order/so/{pk}/issue/ |
| UPDATE（キャンセル） | status | CANCELLED | POST /api/order/so/{pk}/cancel/ |

#### SOLineItem テーブル

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | order, part, quantity, reference, notes, link | フォーム入力値 | createForm()経由 |

#### SalesOrderShipment テーブル

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | order, reference, tracking_number, invoice_number, link | フォーム入力値 | createForm()経由 |

## メッセージ仕様

| メッセージID | メッセージ種別 | 表示条件 | メッセージ内容 |
|-------------|---------------|----------|---------------|
| MSG_EDIT_SUCCESS | 成功 | 編集成功時 | L10().salesOrderUpdated |
| MSG_ISSUE_CONFIRM | 確認 | 発行ボタン押下時 | L10().issueOrder |
| MSG_CANCEL_CONFIRM | 確認 | キャンセルボタン押下時 | L10().cancelOrder |

## 例外処理

| 例外条件 | 処理内容 | ユーザーへの表示 |
|---------|---------|-----------------|
| APIエラー | エラーをSentryに報告 | フォームエラーメッセージを表示 |
| 発行失敗（非Pending状態） | issueOrder()が早期リターン | 処理されない（ボタン非表示で回避） |
| キャンセル失敗（非Open状態） | cancelOrder()が早期リターン | 処理されない（ボタン非表示で回避） |

## 備考

- タブは3つ：Details（詳細）、Line Items（明細）、Shipments（出荷）
- ステータス色は `api.SalesOrderStatus.color()` で取得
- ラインアイテム進捗と出荷進捗は ProgressBar で視覚化
- カメラショートカット表示は `INV_SO_SHOW_CAMERA` 設定で制御
- プロジェクトコード対応は `api.supportsProjectCodes` と `PROJECT_CODES_ENABLED` グローバル設定で判定
- 注文ステータスの判定：
  - isOpen: PENDING, IN_PROGRESS, ON_HOLD のいずれか
  - isPending: PENDING, ON_HOLD のいずれか
  - isInProgress: IN_PROGRESS のみ
  - isComplete: SHIPPED のみ
- 編集時にcustomerフィールドは編集不可（除外）
- contactフィールドは `api.supportsContactModel` の場合のみ表示
- 合計金額表示は TODO（未実装）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sales_order.dart | `lib/inventree/sales_order.dart` | InvenTreeSalesOrderクラス（18-133行）。URL="order/so/"、isOpen, isPending, isInProgress, isComplete判定、issueOrder(), cancelOrder()メソッド |
| 1-2 | sales_order.dart | `lib/inventree/sales_order.dart` | InvenTreeSOLineItemクラス（138-232行）。URL="order/so-line/"、allocated, shipped, progressString |
| 1-3 | sales_order.dart | `lib/inventree/sales_order.dart` | InvenTreeSalesOrderShipmentクラス（262-332行）。URL="/order/so/shipment/"、isShipped, isDelivered |
| 1-4 | orders.dart | `lib/inventree/orders.dart` | InvenTreeOrder基底クラス。共通フィールド（reference, description, status等）と機能 |

**読解のコツ**: `InvenTreeSalesOrder` は `InvenTreeOrder` を継承している。購入注文と異なり、IN_PROGRESSステータスとSHIPPEDステータスがある。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sales_order_detail.dart | `lib/widget/order/sales_order_detail.dart` | SalesOrderDetailWidget（30-37行）の定義。orderをコンストラクタで受け取る |
| 2-2 | sales_order_detail.dart | `lib/widget/order/sales_order_detail.dart` | _SalesOrderDetailState（39-558行）。RefreshableStateを継承 |

**主要処理フロー**:
1. **30-37行**: `SalesOrderDetailWidget` StatefulWidgetの定義
2. **50-59行**: `getAppBarTitle()` で "Sales Order - {reference}" を返す
3. **61-77行**: `appBarActions()` で編集ボタンを構築
4. **156-221行**: `actionButtons()` でカメラ、発行、キャンセル、明細追加、出荷追加ボタンを構築
5. **223-259行**: `barcodeButtons()` でバーコード明細追加、在庫引当スキャンボタンを構築
6. **541-548行**: `getTabIcons()` でタブアイコンを定義
7. **550-557行**: `getTabs()` で各タブのコンテンツを定義

#### Step 3: データ取得処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sales_order_detail.dart | `lib/widget/order/sales_order_detail.dart` | request()メソッド（261-307行）。注文リロード、ステータスロード、設定読込 |

**主要処理フロー**:
- **263行**: `widget.order.reload()` で注文データを再取得
- **264行**: `api.SalesOrderStatus.load()` でステータスマスタをロード
- **266-275行**: プロジェクトコード対応、カメラショートカット設定を読み込み
- **277-295行**: パラメータ数、添付ファイル数を非同期で取得
- **297-306行**: 追加明細行数を取得

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sales_order_detail.dart | `lib/widget/order/sales_order_detail.dart` | headerTile()（337-351行）とorderTiles()（353-539行）。詳細タブの各タイルを構築 |

**主要処理フロー**:
- **337-351行**: ヘッダーカード（リファレンス、説明、サムネイル、ステータス）
- **358-368行**: プロジェクトコードタイル
- **370-382行**: 顧客タイル（タップで会社詳細へ遷移）
- **394-410行**: ラインアイテム進捗タイル（ProgressBar付き）
- **412-428行**: 出荷進捗タイル（ProgressBar付き、shipmentCount > 0の場合）
- **430-448行**: 追加明細行タイル（タップで一覧へ遷移）
- **452-480行**: 日付タイル群（開始日、目標日、完了日）
- **482-496行**: 責任者タイル
- **498-511行**: ノートタイル（タップでノート画面へ遷移）
- **513-536行**: パラメータ・添付ファイルタイル

#### Step 5: アクション処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | sales_order_detail.dart | `lib/widget/order/sales_order_detail.dart` | _addLineItem()（97-111行）、_addShipment()（80-94行）、_issueOrder()（125-138行）、_cancelOrder()（141-154行） |

**主要処理フロー**:
- **80-94行**: 出荷追加フォーム。orderフィールドを設定し非表示に
- **97-111行**: 明細追加フォーム。orderフィールドを設定し非表示に
- **125-138行**: 発行確認ダイアログ。承認時に `order.issueOrder()` 呼び出し
- **141-154行**: キャンセル確認ダイアログ。承認時に `order.cancelOrder()` 呼び出し

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

```
SalesOrderDetailWidget (StatefulWidget)
    |
    +-- _SalesOrderDetailState (RefreshableState)
           |
           +-- request()
           |      |
           |      +-- widget.order.reload()
           |      +-- api.SalesOrderStatus.load()
           |      +-- InvenTreeSettingsManager().getBool()
           |      +-- api.getGlobalBooleanSetting()
           |      +-- InvenTreeParameter().countParameters()
           |      +-- InvenTreeAttachment().countAttachments()
           |      +-- InvenTreeSOExtraLineItem().count()
           |
           +-- getTabs()
           |      |
           |      +-- ListView(orderTiles())
           |      |      |
           |      |      +-- headerTile()
           |      |      +-- customer.goToDetailPage() --> CompanyDetailWidget
           |      |      +-- SOExtraLineListWidget
           |      |      +-- NotesWidget
           |      |      +-- ShowParametersItem --> ParameterListWidget
           |      |      +-- ShowAttachmentsItem --> AttachmentWidget
           |      |
           |      +-- PaginatedSOLineList
           |      |      |
           |      |      +-- requestPage() --> InvenTreeSOLineItem().listPaginated()
           |      |      +-- buildItem() --> SOLineDetailWidget
           |      |
           |      +-- PaginatedSOShipmentList
           |             |
           |             +-- requestPage() --> InvenTreeSalesOrderShipment().listPaginated()
           |             +-- buildItem() --> SOShipmentDetailWidget
           |
           +-- appBarActions()
           |      |
           |      +-- editOrder() --> widget.order.editForm()
           |
           +-- actionButtons()
           |      |
           |      +-- _uploadImage() --> InvenTreeAttachment().uploadImage()
           |      +-- _addLineItem() --> InvenTreeSOLineItem().createForm()
           |      +-- _addShipment() --> InvenTreeSalesOrderShipment().createForm()
           |      +-- _issueOrder() --> widget.order.issueOrder()
           |      +-- _cancelOrder() --> widget.order.cancelOrder()
           |
           +-- barcodeButtons()
                  |
                  +-- scanBarcode(SOAddItemBarcodeHandler)
                  +-- scanBarcode(SOAllocateStockHandler)
```

### データフロー図

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

InvenTreeSalesOrder
        |
        +-----------> SalesOrderDetailWidget
                              |
                              +-- request()
                              |      |
                              |      +-- reload() --> API GET /api/order/so/{pk}/
                              |      |
                              |      +-- countParameters() --> parameterCount
                              |      |
                              |      +-- countAttachments() --> attachmentCount
                              |      |
                              |      +-- SOExtraLineItem.count() --> extraLineCount
                              |
                              +-- getTabs()
                                     |
                                     +-- Tab 0: orderTiles() --> ListView
                                     |          |
                                     |          +-- headerTile (reference, status, customer thumbnail)
                                     |          +-- customer tile --> onTap --> CompanyDetailWidget
                                     |          +-- line items progress (ProgressBar)
                                     |          +-- shipment progress (ProgressBar)
                                     |          +-- extra lines --> onTap --> SOExtraLineListWidget
                                     |          +-- dates (start, target, shipment)
                                     |          +-- notes --> onTap --> NotesWidget
                                     |
                                     +-- Tab 1: PaginatedSOLineList
                                     |          |
                                     |          +-- API GET /api/order/so-line/?order={pk}
                                     |          +-- ListTile per line item
                                     |          +-- onTap --> SOLineDetailWidget
                                     |
                                     +-- Tab 2: PaginatedSOShipmentList
                                                |
                                                +-- API GET /api/order/so/shipment/?order={pk}
                                                +-- ListTile per shipment
                                                +-- onTap --> SOShipmentDetailWidget
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sales_order_detail.dart | `lib/widget/order/sales_order_detail.dart` | ソース | 販売注文詳細画面のメインウィジェット |
| sales_order.dart | `lib/inventree/sales_order.dart` | ソース | 販売注文・明細行・出荷データモデル |
| orders.dart | `lib/inventree/orders.dart` | ソース | 注文基底クラス |
| so_line_list.dart | `lib/widget/order/so_line_list.dart` | ソース | 明細行一覧ウィジェット |
| so_line_detail.dart | `lib/widget/order/so_line_detail.dart` | ソース | 明細行詳細画面 |
| so_shipment_list.dart | `lib/widget/order/so_shipment_list.dart` | ソース | 出荷一覧ウィジェット |
| so_shipment_detail.dart | `lib/widget/order/so_shipment_detail.dart` | ソース | 出荷詳細画面 |
| so_extra_line_list.dart | `lib/widget/order/so_extra_line_list.dart` | ソース | 追加明細行一覧 |
| company.dart | `lib/inventree/company.dart` | ソース | 会社データモデル（顧客） |
| refreshable_state.dart | `lib/widget/refreshable_state.dart` | ソース | リフレッシュ可能なState基底クラス |
| notes_widget.dart | `lib/widget/notes_widget.dart` | ソース | ノート表示・編集ウィジェット |
| attachment_widget.dart | `lib/widget/attachment_widget.dart` | ソース | 添付ファイル一覧ウィジェット |
| parameter_widget.dart | `lib/widget/parameter_widget.dart` | ソース | パラメータ一覧ウィジェット |
| barcode.dart | `lib/barcode/barcode.dart` | ソース | バーコードスキャン基盤 |
| sales_order.dart | `lib/barcode/sales_order.dart` | ソース | 受注関連バーコードハンドラ |
| dialogs.dart | `lib/widget/dialogs.dart` | ソース | 確認ダイアログ |
| progress.dart | `lib/widget/progress.dart` | ソース | 進捗バーウィジェット |
| preferences.dart | `lib/preferences.dart` | ソース | 設定管理（INV_SO_SHOW_CAMERA等） |
