# 通知設計書 3-サーバーエラー

## 概要

本ドキュメントは、InvenTreeモバイルアプリケーションにおける「サーバーエラー」通知の設計仕様を定義する。サーバーとの通信中にエラーが発生した際に表示される通知で、詳細ダイアログへのリンクを含むスナックバー通知の仕様を記載する。

### 本通知の処理概要

この通知は、InvenTreeサーバーとの通信中に各種エラーが発生した際に、ユーザーにエラー内容を通知し、必要に応じて詳細情報を確認できる機能を提供する。

**業務上の目的・背景**：在庫管理システムにおいて、サーバーエラーはデータの取得・更新失敗を意味する。ユーザーがエラーの発生と原因を認識することで、適切な対処（再試行、管理者への連絡、ネットワーク確認など）が可能になる。エラー内容を詳細に伝えることで、トラブルシューティングの効率が向上する。

**通知の送信タイミング**：`showServerError()`関数が呼び出された際にトリガーされる。これは以下のようなケースで発生する：
- API応答のJSONパースエラー
- サーバーからの予期しないレスポンス
- サーバー認証エラー
- サーバー設定不足（バージョン情報不足など）
- その他のサーバー通信エラー

**通知の受信者**：アプリケーションを操作している現在のユーザー。画面上にスナックバーとして表示され、タップすると詳細ダイアログが開く。

**通知内容の概要**：エラーのタイトル（例：「Server Error」）がスナックバーに表示され、「詳細」アクションボタンをタップすると、URL、エラーメッセージなどの詳細情報を含むダイアログが表示される。背景色はオレンジ色で、エラー発生時には音声フィードバック（設定有効時）も提供される。

**期待されるアクション**：ユーザーは通知を確認し、必要に応じて詳細ボタンをタップしてエラー内容を確認する。その後、操作の再試行、ネットワーク接続の確認、サーバー管理者への連絡などの対処を行う。

## 通知種別

アプリ内通知（スナックバー + 詳細ダイアログ + 音声）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高 |
| リトライ | 無し（UI通知のため） |

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

現在アプリケーションを操作しているユーザーに対して、画面下部にスナックバー形式で表示する。スナックバーには「詳細」アクションボタンがあり、タップすると詳細ダイアログが表示される。

## 通知テンプレート

### スナックバー通知の場合

| 項目 | 内容 |
|-----|------|
| 表示位置 | 画面下部 |
| 背景色 | Colors.deepOrange（エラー時） |
| 表示時間 | 10秒（アクションボタンあり） |
| 形式 | テキスト + 詳細ボタン |

### 本文テンプレート

```
[エラータイトル]  [詳細ボタン]
```

### 詳細ダイアログ

| 項目 | 内容 |
|-----|------|
| ダイアログタイプ | SimpleDialog |
| アイコン | TablerIcons.server |
| タイトル | エラータイトル |
| 本文 | エラー詳細メッセージ + URL |

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| title | エラータイトル | 呼び出し元から渡される | Yes |
| description | エラー詳細 | 呼び出し元から渡される | Yes |
| url | リクエストURL | API通信処理から | Yes |
| details | アクションボタンテキスト | L10().details | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API通信 | JSONパースエラー | FormatException発生時 | サーバーレスポンスがJSONとしてパースできない |
| API通信 | サーバー認証エラー | 401/403レスポンス時 | ユーザー名/パスワードが不正 |
| API通信 | サーバー設定エラー | 必須データ不足時 | サーバーバージョン情報がない等 |
| API通信 | 一般的なサーバーエラー | 例外発生時 | SocketException, HttpException等 |
| API通信 | 証明書エラー | CertificateException時 | SSL/TLS証明書が無効 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| コンテキストなし | `hasContext()`が`false`を返す場合 |
| 通知URLに含む場合 | URLに"notifications"が含まれる場合は無視 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[エラー発生] --> B[showServerError呼び出し]
    B --> C{hasContext?}
    C -->|No| D[処理終了]
    C -->|Yes| E{URLに"notifications"含む?}
    E -->|Yes| D
    E -->|No| F{INV_SOUNDS_SERVER有効?}
    F -->|Yes| G[エラー音再生]
    F -->|No| H[音声スキップ]
    G --> I[showSnackIcon呼び出し]
    H --> I
    I --> J[スナックバー表示]
    J --> K{ユーザーが詳細タップ?}
    K -->|Yes| L[showErrorDialog表示]
    K -->|No| M[10秒後自動消去]
    L --> N[終了]
    M --> N
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| settings | 音声設定確認 | Sembast NoSQL DB |

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

#### settings

| 参照項目（キー名） | 用途 | 取得条件 |
|-------------------|------|---------|
| INV_SOUNDS_SERVER | サーバーエラー音有効/無効 | デフォルト: true |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | 通知表示のみで更新なし |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| コンテキスト不在 | テスト環境などでUIコンテキストがない | 処理スキップ |
| 音声再生失敗 | AudioPlayerが利用できない | 音声なしで通知継続 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0回 |
| リトライ間隔 | - |
| リトライ対象エラー | - |

UI通知のため、リトライは実施しない。

## 配信設定

### レート制限

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

### 配信時間帯

制限なし（エラー発生時に即座に表示）

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

- エラー詳細にはURL情報が含まれるが、認証トークンは含まれない
- ユーザーのデバイス上でのみ表示され、外部への送信は行わない
- エラー情報はSentryにも送信される場合がある（エラーレポート設定に依存）

## 備考

- 音声ファイルは`sounds/server_error.mp3`を使用
- 音声再生はINV_SOUNDS_SERVER設定で制御される（デフォルト有効）
- 詳細ボタンがある場合、表示時間は10秒に延長される
- "notifications"を含むURLからのエラーは無視される（通知ポーリングのエラーを抑止）

---

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

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

### 推奨読解順序

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

まず、エラー通知に関連する設定値を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | preferences.dart | `lib/preferences.dart` | INV_SOUNDS_SERVER定数の定義 |

**読解のコツ**: `INV_SOUNDS_SERVER`はサーバーエラー時の音声フィードバックを制御する設定キー。

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

処理の起点となる`showServerError`関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | dialogs.dart | `lib/widget/dialogs.dart` | showServerError関数の実装 |

**主要処理フロー**:
1. **行207-248**: `showServerError()`関数 - サーバーエラー通知のメイン処理
2. **行212-214**: コンテキスト確認とアーリーリターン
3. **行216-219**: "notifications" URLのフィルタリング
4. **行226-232**: 音声再生設定の確認と再生
5. **行236-247**: showSnackIcon呼び出しと詳細ダイアログ設定

#### Step 3: 詳細ダイアログを理解する

エラー詳細を表示するダイアログの実装を確認する。

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

**主要処理フロー**:
- **行123-202**: `showErrorDialog()`関数 - エラー詳細ダイアログの生成と表示
- **行130-184**: APIResponseからのエラー情報抽出
- **行190-201**: ダイアログの表示

#### Step 4: 音声再生を理解する

エラー音の再生処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | helpers.dart | `lib/helpers.dart` | playAudioFile関数の実装 |

**主要処理フロー**:
- **行92-115**: `playAudioFile()`関数 - 音声ファイルの再生
- **行104-112**: AudioContextの設定（通知用）

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

```
[各種API通信エラー]
    |
    +-- showServerError() [dialogs.dart:207]
            |
            +-- hasContext() [helpers.dart:55]
            |
            +-- InvenTreeSettingsManager().getValue() [preferences.dart:146]
            |
            +-- playAudioFile() [helpers.dart:92]
            |       |
            |       +-- AudioPlayer.play()
            |
            +-- showSnackIcon() [snacks.dart:11]
                    |
                    +-- onAction: showErrorDialog() [dialogs.dart:123]
```

### データフロー図

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

url                  showServerError()              スナックバー表示
title           --->  |                         --> [エラータイトル]
description           |                              [詳細ボタン]
                      v
              音声設定チェック
                      |
                      v
              playAudioFile() ----------------> sounds/server_error.mp3
                      |
                      v
              showSnackIcon()
                      |
                      v
              [ユーザーが詳細タップ]
                      |
                      v
              showErrorDialog() --------------> 詳細ダイアログ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dialogs.dart | `lib/widget/dialogs.dart` | ソース | サーバーエラー通知とダイアログ表示 |
| snacks.dart | `lib/widget/snacks.dart` | ソース | スナックバー通知の表示 |
| helpers.dart | `lib/helpers.dart` | ソース | 音声再生・共通ヘルパー関数 |
| preferences.dart | `lib/preferences.dart` | ソース | 設定値管理 |
| api.dart | `lib/api.dart` | ソース | showServerError呼び出し元 |
| server_error.mp3 | `sounds/server_error.mp3` | 音声 | エラー通知音 |
