# 通知設計書 28-出荷更新

## 概要

本ドキュメントは、InvenTreeアプリにおける出荷（シップメント）更新通知の設計を定義する。出荷情報の編集が正常に完了した際に、ユーザーにスナックバー形式で成功を通知する。

### 本通知の処理概要

出荷更新通知は、ユーザーが出荷詳細画面から出荷情報を編集したり、出荷ステータスを変更した際に、その変更がサーバーに正常に保存されると表示される。出荷の編集、チェック、アンチェック、送信など複数のシナリオで同じ通知が使用される。

**業務上の目的・背景**：出荷（Shipment）は販売発注の実行段階における重要なプロセスである。出荷参照番号、追跡番号、請求書番号、出荷日などの変更が正しく反映されたことをユーザーに即座にフィードバックすることで、物流管理の正確性と顧客への配送追跡情報提供を実現する。出荷情報の誤りは配送トラブルや顧客クレームに直結するため、更新完了の明確な確認が重要である。

**通知の送信タイミング**：出荷編集フォームで「保存」操作を実行し、サーバーAPIからの応答が成功となった直後、または出荷のチェック/アンチェック/送信操作が成功した際に通知が送信される。`_editShipment`、`_sendShipment`メソッドや各種アクションボタンの`onTap`コールバックで発火する。

**通知の受信者**：編集操作を実行したユーザー本人のみ。ローカル通知のため、他のユーザーには通知されない。

**通知内容の概要**：「Shipment Updated」（出荷が更新されました）というテキストメッセージと成功を示す緑色のチェックマークアイコンが表示される。

**期待されるアクション**：ユーザーは通知を確認し、出荷情報の更新が正常に完了したことを認識する。通知は5秒後に自動的に消える。

## 通知種別

アプリ内通知（スナックバー）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（UIスレッド） |
| 優先度 | 中 |
| リトライ | 無し |

### 送信先決定ロジック

編集操作を実行したユーザーの画面に直接表示される。現在アクティブな画面コンテキストに対して通知が表示される。

## 通知テンプレート

### スナックバー通知

| 項目 | 内容 |
|-----|------|
| 背景色 | Colors.lightGreen（成功時） |
| アイコン | TablerIcons.circle_check |
| 表示位置 | 画面下部 |
| 自動消去 | 5秒後 |

### 本文テンプレート

```
Shipment Updated
```

多言語対応: L10().shipmentUpdated により国際化された文字列が使用される。

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | スナックバー通知のため添付なし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| shipmentUpdated | 通知メッセージ | L10().shipmentUpdated（国際化リソース） | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | 出荷編集フォームの保存ボタン押下 | API応答が成功 | `_editShipment`メソッドのonSuccessコールバック |
| 画面操作 | 出荷送信フォームの送信ボタン押下 | API応答が成功 | `_sendShipment`メソッドのonSuccessコールバック |
| 画面操作 | 出荷チェックボタン押下 | API応答が成功 | actionButtons内のチェック処理のthenコールバック |
| 画面操作 | 出荷アンチェックボタン押下 | API応答が成功 | actionButtons内のアンチェック処理のthenコールバック |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| API応答エラー | サーバーからエラー応答があった場合は成功通知は表示されない |
| 編集権限なし | widget.shipment.canEditがfalseの場合は編集ボタンが表示されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[アクション開始] --> B{アクションタイプ}
    B -->|編集| C[_editShipmentメソッド]
    B -->|送信| D[_sendShipmentメソッド]
    B -->|チェック/アンチェック| E[updateメソッド]
    C --> F[編集フォーム表示]
    F --> G[保存ボタン押下]
    G --> H[API PUT/PATCH リクエスト]
    D --> I[送信フォーム表示]
    I --> J[送信ボタン押下]
    J --> K[API POST リクエスト]
    E --> L[API PATCH リクエスト]
    H --> M{API応答}
    K --> M
    L --> M
    M -->|成功| N[showSnackIcon呼び出し]
    M -->|失敗| O[エラーハンドリング]
    N --> P[スナックバー表示]
    P --> Q[画面リフレッシュ]
    Q --> R[5秒後自動消去]
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| sales_order_shipment | 編集対象出荷の現在値取得 | InvenTreeSalesOrderShipment モデル経由 |
| sales_order | 関連販売発注の取得 | 出荷に紐づく販売発注情報 |

### テーブル別参照項目詳細

#### sales_order_shipment（サーバー側）

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| pk | 出荷識別子 | 編集対象出荷のID |
| reference | 出荷参照番号 | フォーム表示用 |
| order | 販売発注ID | 関連発注の取得用 |
| shipment_date | 出荷日 | フォーム表示用 |
| tracking_number | 追跡番号 | フォーム表示用 |
| invoice_number | 請求書番号 | フォーム表示用 |
| checked_by | チェック担当者ID | ステータス管理用 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| sales_order_shipment | UPDATE | 出荷情報の更新 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| API通信エラー | ネットワーク接続不可 | エラーダイアログ表示 |
| バリデーションエラー | 入力値が不正 | フォームエラー表示 |
| 権限エラー | 編集権限なし | 権限エラー通知 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0回（自動リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（ユーザー操作起点のため）

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

- 通知はローカル表示のみで外部送信なし
- 通知内容に機密情報は含まれない
- 編集権限チェックはモデル側で実施（widget.shipment.canEdit）

## 備考

- 通知メッセージは国際化対応済み（L10().shipmentUpdated）
- 出荷には複数のステータス変更アクション（チェック、アンチェック、送信）が存在
- チェック処理ではchecked_byフィールドにユーザーIDを設定
- アンチェック処理ではchecked_byフィールドをnullに設定
- 出荷済みの場合はチェック/アンチェックボタンが表示されない
- カメラショートカット設定により画像アップロード機能の表示/非表示が切り替わる

---

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

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

### 推奨読解順序

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

InvenTreeSalesOrderShipmentクラスが出荷データの構造を定義している。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sales_order.dart | `lib/inventree/sales_order.dart` | InvenTreeSalesOrderShipmentクラスの定義、ステータス管理（isChecked, isShipped, isDelivered） |

**読解のコツ**: 出荷にはチェック済み、出荷済み、配達済みの3つのステータスがあり、それぞれのステータスによって利用可能なアクションが異なる。

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

出荷詳細画面が編集操作のエントリーポイント。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | so_shipment_detail.dart | `lib/widget/order/so_shipment_detail.dart` | 各種編集・ステータス変更メソッドを確認 |

**主要処理フロー**:
1. **45-60行目**: appBarActionsで編集ボタンを追加
2. **62-76行目**: `_editShipment`メソッドで基本情報編集
3. **120-143行目**: `_sendShipment`メソッドで出荷送信処理
4. **146-216行目**: actionButtonsで各種アクションボタン定義
5. **167-179行目**: チェック処理（checked_byにユーザーID設定）
6. **185-197行目**: アンチェック処理（checked_byをnullに設定）

#### Step 3: 通知表示層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | snacks.dart | `lib/widget/snacks.dart` | showSnackIcon関数の実装詳細 |

**主要処理フロー**:
- **11行目**: showSnackIcon関数定義
- **35-41行目**: success: true時の緑色背景とチェックアイコン設定

#### Step 4: 国際化リソースを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | app_en.arb | `lib/l10n/app_en.arb` | shipmentUpdated（1463行目）の定義 |

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

```
SOShipmentDetailWidget (so_shipment_detail.dart)
    |
    +-- appBarActions() [45-60行目]
    |      |
    |      +-- IconButton onPressed --> _editShipment() [62行目]
    |                                        |
    |                                        +-- editForm() --> onSuccess --> showSnackIcon() [73行目]
    |
    +-- actionButtons() [146-216行目]
           |
           +-- チェックボタン [167-179行目]
           |      +-- update() --> then() --> showSnackIcon() [176行目]
           |
           +-- アンチェックボタン [185-197行目]
           |      +-- update() --> then() --> showSnackIcon() [192行目]
           |
           +-- 送信ボタン [200-210行目]
                  +-- _sendShipment() [120行目]
                         +-- launchApiForm() --> onSuccess --> showSnackIcon() [140行目]
```

### データフロー図

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

ユーザー操作      ──────> 編集/チェック/アンチェック/送信
(各種ボタン)                    |
                               v
                         API リクエスト ──────> サーバー
                               |
                               v
                         成功応答
                               |
                               +───> showSnackIcon() ──────> スナックバー表示
                               |           |
                               |           v
                               |     L10().shipmentUpdated ──────> "Shipment Updated"
                               |
                               +───> refresh() ──────> 画面更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| so_shipment_detail.dart | `lib/widget/order/so_shipment_detail.dart` | ソース | 出荷詳細画面、各種編集・ステータス変更処理 |
| snacks.dart | `lib/widget/snacks.dart` | ソース | スナックバー通知表示 |
| sales_order.dart | `lib/inventree/sales_order.dart` | ソース | 出荷モデル定義 |
| app_en.arb | `lib/l10n/app_en.arb` | リソース | 英語メッセージ定義 |
| l10.dart | `lib/l10.dart` | ソース | 国際化ヘルパー |
| api_form.dart | `lib/api_form.dart` | ソース | APIフォーム送信（launchApiForm） |
