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

## 概要

本ドキュメントは、InvenTreeアプリにおける「サーバーエラー音」の設計仕様を定義する。サーバーとの通信でエラーが発生した際に、ユーザーに音声フィードバックを提供する。

### 本通知の処理概要

サーバーエラー音は、API通信エラーや接続エラーが発生した際に、ユーザーに即座に問題を知らせるための音声フィードバック機能である。視覚的な通知を見逃しやすい状況でも、聴覚によるフィードバックで確実にエラーを認識させる。

**業務上の目的・背景**：在庫管理業務では、サーバーとの通信は常に発生する重要な処理である。通信エラーが発生すると、データの保存や取得が失敗し、作業に支障をきたす。特に連続して複数の操作を行っている場合、画面上のエラーメッセージを見逃すことがある。サーバーエラー音を再生することで、エラーの発生を確実にユーザーに伝え、適切な対処（再試行、ネットワーク確認など）を促すことができる。

**通知の送信タイミング**：サーバーとの通信でエラーが発生した時点で、`showServerError()` 関数内で再生される。タイムアウトエラー、HTTPステータスコードエラーなど、様々なサーバーエラー時に呼び出される。

**通知の受信者**：現在アプリを操作しているユーザー。音声はデバイスのスピーカーから再生される。

**通知内容の概要**：`server_error.mp3` という音声ファイルが再生される。音声ファイルはアプリのアセットとしてバンドルされている。

**期待されるアクション**：ユーザーは音声を聞いて、サーバーエラーが発生したことを認識する。その後、スナックバー通知を確認し、詳細ダイアログを開くか、操作を再試行するか判断する。

## 通知種別

音声通知（Audio Notification）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（エラー検出と同時に再生） |
| 優先度 | 高（エラー通知） |
| リトライ | 無（再生失敗時は静かに失敗） |

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

- 現在アプリを操作しているユーザー
- 条件：`INV_SOUNDS_SERVER` 設定が `true` の場合にのみ再生

## 通知テンプレート

### 音声ファイル構成

| 結果 | ファイルパス | 説明 |
|-----|------------|------|
| サーバーエラー | `assets/sounds/server_error.mp3` | サーバーエラー時の警告音 |

### 再生設定

| 項目 | 設定値 | 説明 |
|-----|-------|------|
| AudioContext | AndroidUsageType.notification | Android通知音として再生 |
| AudioFocus | AndroidAudioFocus.none | 他の音声を中断しない |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| INV_SOUNDS_SERVER | サーバーエラー音設定 | InvenTreeSettingsManager | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| サーバーエラー | showServerError呼び出し | INV_SOUNDS_SERVER == true | 各種サーバーエラー発生時 |
| タイムアウト | showTimeoutError呼び出し | INV_SOUNDS_SERVER == true | リクエストタイムアウト時 |
| ステータスコードエラー | showStatusCodeError呼び出し | INV_SOUNDS_SERVER == true | HTTPエラーステータス受信時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| INV_SOUNDS_SERVER == false | サーバーエラー音設定がオフの場合 |
| hasContext() == false | アプリコンテキストが利用できない場合（テスト環境等） |
| notificationsのURL | 通知取得APIのエラーは音を鳴らさない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[サーバーエラー発生] --> B{URL確認}
    B -->|notificationsを含む| C[音声再生スキップ]
    B -->|その他| D[showServerError呼び出し]
    D --> E[INV_SOUNDS_SERVER設定確認]
    E -->|有効| F[hasContext確認]
    E -->|無効| G[スナックバー表示のみ]
    F -->|true| H[playAudioFile実行]
    F -->|false| G
    H --> I[音声再生]
    I --> J[スナックバー表示]
    C --> K[終了]
    G --> K
    J --> K
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| Settings（ローカルDB） | サーバーエラー音設定の確認 | Sembast NoSQLデータベース |

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

#### Settings

| 参照項目（キー） | 用途 | デフォルト値 |
|----------------|------|------------|
| INV_SOUNDS_SERVER | サーバーエラー音の有効/無効 | true |

### 更新テーブル一覧

なし（読み取り専用）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 音声ファイル欠損 | アセットファイルが存在しない場合 | エラーは暗黙的に処理される |
| 再生失敗 | オーディオプレーヤーエラー | エラーは暗黙的に処理される |
| コンテキスト不足 | hasContext() == false | 再生をスキップ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0回（再生失敗時はスキップ） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（ただし頻繁なエラー時は注意） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

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

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

- 音声再生はローカルのみで完結
- 個人情報は含まれない
- 周囲への音漏れに配慮が必要（業務環境による）

## 備考

- 設定画面でサーバーエラー音のオン/オフを切り替え可能
- AudioPlayerライブラリ（audioplayers）を使用
- Androidでは通知音として分類（他のメディア再生に影響しない）
- notifications APIのエラーは音を鳴らさない（バックグラウンド更新時のノイズ防止）
- テスト環境ではdebug()によるログ出力のみ

---

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

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

### 推奨読解順序

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

音声設定の定義と、使用される音声ファイルを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | preferences.dart | `lib/preferences.dart` | INV_SOUNDS_SERVER定数の定義 |
| 1-2 | assets/sounds/ | `assets/sounds/server_error.mp3` | 音声ファイルの存在確認 |

**読解のコツ**: INV_SOUNDS_SERVERのデフォルト値がtrueであることを確認しておくと良い。

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

音声再生のトリガーとなる関数を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | dialogs.dart | `lib/widget/dialogs.dart` | showServerError()関数（207-248行目） |

**主要処理フロー**:
1. **212-218行目**: URL確認（notificationsのエラーは無視）
2. **225-231行目**: INV_SOUNDS_SERVER設定確認と音声再生
3. **236-247行目**: スナックバー表示

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

実際の音声再生ロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | helpers.dart | `lib/helpers.dart` | playAudioFile()関数（92-115行目）の実装詳細 |

**主要処理フロー**:
- **92-98行目**: デバッグ出力とhasContext()チェック
- **100-114行目**: AudioPlayer生成とAudioContext設定、再生実行

#### Step 4: 関連するエラーダイアログを理解する

サーバーエラー音と連携するエラー表示機能を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | dialogs.dart | `lib/widget/dialogs.dart` | showStatusCodeError()、showTimeoutError()関数 |

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

```
APIエラー発生
    |
    +-- showServerError() [dialogs.dart:207-248行目]
    |       |
    |       +-- URL確認（notifications除外）
    |       |
    |       +-- INV_SOUNDS_SERVER設定確認
    |       |
    |       +-- playAudioFile("sounds/server_error.mp3")
    |       |       |
    |       |       +-- [helpers.dart:92-115行目]
    |       |               |
    |       |               +-- debug()
    |       |               |
    |       |               +-- hasContext()チェック
    |       |               |
    |       |               +-- AudioPlayer()生成
    |       |               |
    |       |               +-- setAudioContext()
    |       |               |
    |       |               +-- play(AssetSource)
    |       |
    |       +-- showSnackIcon() [スナックバー表示]
    |
    +-- showStatusCodeError() [dialogs.dart:253-267行目]
    |       |
    |       +-- showServerError()呼び出し
    |
    +-- showTimeoutError() [dialogs.dart:306-308行目]
            |
            +-- showServerError()呼び出し
```

### データフロー図

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

サーバーエラー発生 ────> showServerError() ────────> URL確認
(API応答/タイムアウト等)                                      |
                                                              v
                                                   notifications?
                                                              |
                              +------------------+------------+
                              |                  |
                              v                  v
                           [Yes]              [No]
                              |                  |
                              v                  v
                        処理終了        INV_SOUNDS_SERVER確認
                                                 |
                                                 v
                                        +-------+-------+
                                        |               |
                                        v               v
                                     [有効]          [無効]
                                        |               |
                                        v               v
                                hasContext()確認   スナックバーのみ
                                        |
                                        v
                                音声ファイル再生
                                        |
                                        v
                                スナックバー表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dialogs.dart | `lib/widget/dialogs.dart` | ソース | showServerError/showStatusCodeError/showTimeoutError関数 |
| helpers.dart | `lib/helpers.dart` | ソース | playAudioFile関数の実装 |
| preferences.dart | `lib/preferences.dart` | ソース | INV_SOUNDS_SERVER定数、InvenTreeSettingsManager |
| server_error.mp3 | `assets/sounds/server_error.mp3` | アセット | サーバーエラー音の音声ファイル |
| snacks.dart | `lib/widget/snacks.dart` | ソース | showSnackIcon関数（視覚的フィードバック） |
| api.dart | `lib/api.dart` | ソース | API通信処理（エラーハンドラーの呼び出し元） |
