# 通知設計書 9-バーコードスキャンエラー

## 概要

本ドキュメントは、InvenTreeモバイルアプリケーションにおける「バーコードスキャンエラー」通知の設計仕様を定義する。バーコードスキャンに失敗した際に再生される音声通知の仕様を記載する。

### 本通知の処理概要

この通知は、バーコードスキャン操作が失敗したことをユーザーに音声フィードバックで伝える機能である。視覚的な確認なしでも操作の失敗を認識できる。

**業務上の目的・背景**：倉庫作業や在庫管理において、スキャンエラーを即座に認識することは重要である。成功音と異なるエラー音を再生することで、作業者は画面を見なくても操作の失敗を認識でき、すぐに再スキャンや問題の確認を行える。これにより、誤ったデータ入力やスキャン漏れを防止できる。

**通知の送信タイミング**：`barcodeFailureTone()`関数が呼び出された際にトリガーされる。これは主に以下の場面で発生する：
- バーコードスキャン後、サーバーからエラーレスポンスが返された場合
- `BarcodeHandler.onBarcodeUnknown()`が呼び出された場合
- `BarcodeHandler.onBarcodeUnhandled()`が呼び出された場合
- バーコードが空または無効な場合
- API通信エラーが発生した場合

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

**通知内容の概要**：`sounds/barcode_error.mp3`という音声ファイルが再生される。成功音とは異なる「ブー」という失敗音で、視覚に頼らず操作結果を認識できる。

**期待されるアクション**：ユーザーは音声を確認し、スキャンが失敗したことを認識して以下の対処を行う：
- バーコードを再スキャン
- バーコードの状態を確認（汚れ、破損など）
- 画面を確認してエラーの詳細を把握
- 正しいバーコードをスキャンしているか確認

## 通知種別

音声通知（サウンドエフェクト）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期 |
| 優先度 | 高 |
| リトライ | 無し（音声再生のため） |

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

現在アプリケーションを操作しているユーザーのデバイスで音声が再生される。音声再生は`AudioPlayer`ライブラリを使用し、`AndroidUsageType.notification`として再生される。

## 通知テンプレート

### 音声ファイル

| 項目 | 内容 |
|-----|------|
| ファイルパス | `sounds/barcode_error.mp3` |
| 形式 | MP3 |
| 再生タイミング | スキャンエラー時即座 |
| 音量 | システム通知音量に従う |

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| INV_SOUNDS_BARCODE | バーコード音声有効/無効 | InvenTreeSettingsManager | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| バーコード | バーコード未認識 | サーバーからエラーレスポンス | BarcodeHandler.onBarcodeUnknown |
| バーコード | 予期しないレスポンス | 不明なレスポンス形式 | BarcodeHandler.onBarcodeUnhandled |
| バーコード | 空バーコード | barcode.isEmpty | 空のバーコードデータ |
| バーコード | API通信エラー | response == null | サーバー通信失敗 |
| バーコード | 無効なレスポンス | !response.isValid() | レスポンス検証失敗 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| コンテキストなし | `hasContext()`が`false`を返す場合 |
| 音声設定無効 | `INV_SOUNDS_BARCODE`が`false`の場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[バーコードスキャン] --> B{バーコード有効?}
    B -->|No| C[barcodeFailureTone呼び出し]
    B -->|Yes| D[サーバーにPOST]
    D --> E{レスポンス成功?}
    E -->|No| F{エラータイプ判定}
    F -->|Unknown| G[onBarcodeUnknown呼び出し]
    F -->|Unhandled| H[onBarcodeUnhandled呼び出し]
    G --> I[barcodeFailureTone呼び出し]
    H --> I
    C --> I
    I --> J{INV_SOUNDS_BARCODE?}
    J -->|true| K{hasContext?}
    J -->|false| L[音声スキップ]
    K -->|Yes| M[playAudioFile呼び出し]
    K -->|No| L
    M --> N[barcode_error.mp3再生]
    E -->|Yes| O[onBarcodeMatched呼び出し]
    N --> P[終了]
    L --> P
    O --> P
```

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

### 参照テーブル一覧

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

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

#### settings

| 参照項目（キー名） | 用途 | 取得条件 |
|-------------------|------|---------|
| INV_SOUNDS_BARCODE | バーコード音声有効/無効 | デフォルト: true |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | 音声再生のみで更新なし |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 音声再生失敗 | AudioPlayerが利用できない | 音声なしで処理継続 |
| ファイル不在 | 音声ファイルが見つからない | 例外をキャッチして継続 |

### リトライ仕様

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

音声通知のため、リトライは行わない。

## 配信設定

### レート制限

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

### 配信時間帯

制限なし（スキャンエラー時に即座に再生）

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

- 音声ファイルに機密情報は含まれない
- 周囲に音が聞こえる可能性があるが、内容は単純な確認音のみ

## 備考

- 音声再生は`AudioPlayer`ライブラリを使用
- `AudioContext`は`AndroidUsageType.notification`に設定（他のメディア再生を中断しない）
- `AudioFocus.none`に設定（他のアプリの音声を中断しない）
- 音声設定は設定画面から変更可能（`INV_SOUNDS_BARCODE`）
- デフォルトでは音声有効
- エラー音は成功音と明確に異なる音色で区別可能

---

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

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

### 推奨読解順序

#### Step 1: 音声再生関数を理解する

まず、バーコードエラー音を再生する専用関数を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | tones.dart | `lib/barcode/tones.dart` | barcodeFailureTone関数 |

**読解のコツ**: `barcodeFailureTone()`は設定を確認してから`playAudioFile()`を呼び出す簡潔な関数。成功音と同じ設定キーを使用。

#### Step 2: 呼び出し元を理解する

barcodeFailureToneが呼び出される箇所を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | handler.dart | `lib/barcode/handler.dart` | BarcodeHandlerクラスのエラー処理 |

**主要処理フロー**:
1. **行17-25**: `barcodeFailureTone()`関数 - 設定確認と音声再生
2. **行34-44**: `onBarcodeUnknown()` - 未認識バーコード時の処理
3. **行47-50**: `onBarcodeUnhandled()` - 予期しないレスポンス時の処理
4. **行67-77**: `processBarcode()` - 空バーコードのエラー処理
5. **行92-96**: `processBarcode()` - API通信エラー処理

#### Step 3: 音声再生の実装を理解する

playAudioFile関数の実装を確認する。

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

**主要処理フロー**:
- **行92-115**: `playAudioFile()`関数 - AudioPlayerの設定と再生

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

```
[バーコードスキャンエラー]
    |
    +-- BarcodeHandler.processBarcode() [handler.dart:57]
    |       |
    |       +-- [空バーコード] --> barcodeFailureTone()
    |       +-- [response == null] --> barcodeFailureTone()
    |       +-- [!response.isValid()] --> onBarcodeUnknown()
    |
    +-- BarcodeHandler.onBarcodeUnknown() [handler.dart:34]
    |       |
    |       +-- barcodeFailureTone() [tones.dart:17]
    |
    +-- BarcodeHandler.onBarcodeUnhandled() [handler.dart:47]
            |
            +-- barcodeFailureTone() [tones.dart:17]
                    |
                    +-- InvenTreeSettingsManager().getValue()
                    |
                    +-- playAudioFile() [helpers.dart:92]
                            |
                            +-- hasContext() [helpers.dart:55]
                            +-- AudioPlayer() [audioplayers]
                            +-- player.play(AssetSource("sounds/barcode_error.mp3"))
```

### データフロー図

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

スキャンエラー       barcodeFailureTone()             音声再生
     |          --->       |                   --> barcode_error.mp3
     v                     v
サーバー応答        INV_SOUNDS_BARCODE確認
error/unknown             |
                          v
                    playAudioFile()
                          |
                          v
                    AudioPlayer.play()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| tones.dart | `lib/barcode/tones.dart` | ソース | バーコード音声再生関数 |
| helpers.dart | `lib/helpers.dart` | ソース | 音声再生の実装 |
| handler.dart | `lib/barcode/handler.dart` | ソース | バーコードハンドラ基底クラス |
| preferences.dart | `lib/preferences.dart` | ソース | INV_SOUNDS_BARCODE設定 |
| barcode_error.mp3 | `sounds/barcode_error.mp3` | 音声 | エラー音 |
