# 通知設計書 37-ダウンロード開始/進行通知

## 概要

本ドキュメントは、ECモバイルアプリケーションにおける「ダウンロード開始/進行通知」の設計仕様を定義する。ユーザーがダウンロード可能商品（デジタルコンテンツ）のダウンロードを開始した際に、進捗状況をリアルタイムでシステム通知バーに表示する機能について記載する。

### 本通知の処理概要

ダウンロード開始/進行通知は、ユーザーがダウンロードボタンをタップしてダウンロード処理が開始された時点で「Started」（開始）ステータスとともにプログレスバー付きの通知を表示し、ダウンロードの進捗状況をリアルタイムでユーザーにフィードバックする機能である。

**業務上の目的・背景**：大容量のデジタルコンテンツをダウンロードする際、処理に時間がかかる場合がある。ユーザーがダウンロードの開始と進捗状況を把握できることで、処理が正常に行われていることを確認でき、待機中の不安を軽減できる。また、進捗バーにより残り時間の目安を把握でき、ユーザー体験の向上に寄与する。バックグラウンドでのダウンロードにも対応しており、アプリを閉じてもダウンロード状況を確認できる。

**通知の送信タイミング**：ダウンロードボタンタップ後、createDownloadNotificationメソッドが呼び出された時点で通知が表示される。progressがtotalに達していない間（progress < total）は「Started」ステータスで進捗バーが表示される。

**通知の受信者**：ダウンロード操作を実行したユーザー本人のみが通知を受け取る。通知はAndroid/iOSのシステム通知バーに表示される。

**通知内容の概要**：通知タイトルにダウンロード中のファイル名、本文に「Started」（開始）のステータス、プログレスバーで進捗状況が表示される。

**期待されるアクション**：ユーザーはダウンロードが進行中であることを確認し、完了を待つ。必要に応じてアプリを閉じて他の作業を行い、完了通知を待つこともできる。

## 通知種別

プッシュ通知（ローカル通知）- システム通知バー表示、プログレスバー付き

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（ダウンロード開始に対する即時通知） |
| 優先度 | 高（Priority.high） |
| リトライ | 無 |

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

ダウンロード操作を実行したユーザー本人のデバイスに表示される。システム通知のためユーザー認証は不要。

## 通知テンプレート

### システム通知バーの場合

| 項目 | 内容 |
|-----|------|
| 表示位置 | システム通知バー |
| 表示時間 | ダウンロード完了まで継続表示 |
| プログレスバー | 表示（progress < total の場合） |

### 進行中テンプレート

| 項目 | 内容 |
|-----|------|
| タイトル | {ファイル名（name）} |
| 本文 | "Started"（StringConstants.started） |
| 通知ID | 1（固定） |
| チャンネルID | "progress channel" |
| チャンネル名 | "Bagisto Notification" |
| プログレスバー | 表示（maxProgress=total, progress=progress） |

```
タイトル: {ダウンロードファイル名}
本文: Started
プログレス: [=========>          ] 50%
```

### Android通知設定

| 設定項目 | 値 | 説明 |
|---------|-----|------|
| channelShowBadge | false | アプリアイコンにバッジ非表示 |
| importance | Importance.max | 最高重要度 |
| priority | Priority.high | 高優先度 |
| onlyAlertOnce | true | 最初の1回のみ音/振動 |
| showProgress | true（progress < total） | プログレスバー表示 |
| maxProgress | total | 最大進捗値 |
| progress | progress | 現在の進捗値 |

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | 通知自体には添付なし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| name | ファイル名 | createDownloadNotification引数 | Yes |
| path | ファイルパス | createDownloadNotification引数 | Yes |
| total | 総バイト数 | createDownloadNotification引数 | Yes |
| progress | 進捗バイト数 | createDownloadNotification引数 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | DownloadProductEvent発行 | progress < total | ダウンロード開始時 |
| 進捗更新 | createDownloadNotification呼び出し | progress < total | 進捗更新ごと |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| ダウンロード完了 | total == progress の場合は完了通知に切り替え |
| ダウンロード失敗 | エラー発生時は進行通知を停止 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ダウンロードボタンタップ] --> B[DownloadProductEvent発行]
    B --> C[ShowLoaderState発行]
    C --> D[Repository.downloadProductLink呼び出し]
    D --> E{API応答}
    E -->|成功| F[DownloadProductState発行]
    E -->|失敗| G[エラー状態発行]
    F --> H[DownloadBase64ProductEvent自動発行]
    H --> I[Base64データ取得開始]
    I --> J[createDownloadNotification呼び出し]
    J --> K{進捗確認}
    K -->|progress < total| L[進行通知表示 Started + プログレスバー]
    K -->|total == progress| M[完了通知表示 Completed]
    L --> N[進捗更新ループ]
    N --> J
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| downloadable_link_purchases | ダウンロード権限確認 | GraphQL API経由 |

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

#### downloadable_link_purchases

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| id | ダウンロードリンク識別 | DownloadProductEvent.id |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | 進行通知表示のみのためDB更新なし |

#### 送信ログテーブル

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| なし | - | - | ローカル通知のためログ記録なし |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| API通信エラー | ネットワーク接続不可 | 進行通知を停止、エラー通知表示 |
| ダウンロード中断 | ユーザーによるキャンセル | 通知を削除 |
| ストレージ不足 | 保存先容量不足 | エラー通知表示 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（ユーザー操作による再試行） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（進捗更新ごとに通知更新） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（24時間対応）

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

- ダウンロード操作はログイン済みユーザーのみ実行可能
- ダウンロード権限は購入履歴に基づいて検証
- 進捗情報に機密データは含まない

## 備考

- flutter_local_notificationsパッケージを使用したローカル通知を採用
- Android/iOSの両プラットフォームに対応
- onlyAlertOnce=trueにより、進捗更新時の音/振動は最初の1回のみ
- 同一の通知ID（1）を使用して進捗更新を行うため、通知は上書きされる
- channelShowBadge=falseにより、アプリアイコンのバッジ表示は無効

---

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

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

### 推奨読解順序

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

通知に関連するパラメータと設定を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | push_notifications_manager.dart | `lib/utils/push_notifications_manager.dart` | createDownloadNotificationのメソッドシグネチャ（152行目） |

**読解のコツ**: 引数（total, progress, name, path）の役割を理解する。特にtotalとprogressの関係が完了/進行中の判定に使用される。

#### Step 2: 通知作成ロジックを理解する

進行通知を作成するコアメソッドを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | push_notifications_manager.dart | `lib/utils/push_notifications_manager.dart` | createDownloadNotificationメソッド（152-176行目） |

**主要処理フロー**:
1. **154行目**: `await Future<void>.delayed(const Duration(milliseconds: 0), () async {` - 非同期処理
2. **155-163行目**: AndroidNotificationDetails設定
3. **157行目**: `channelShowBadge: false` - バッジ非表示
4. **160行目**: `onlyAlertOnce: true` - 1回のみアラート
5. **161行目**: `showProgress: progress < total ? true : false` - プログレスバー表示条件
6. **162行目**: `maxProgress: total` - 最大進捗値
7. **163行目**: `progress: progress` - 現在の進捗値
8. **170-172行目**: 本文メッセージ（Started/Completed）の切り替え

#### Step 3: ダウンロード処理フローを理解する

全体のダウンロード処理フローと通知の関連を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | downloadable_products_bloc.dart | `lib/screens/downloadable_products/bloc/downloadable_products_bloc.dart` | DownloadProductEvent/DownloadBase64ProductEventハンドリング（41-68行目） |
| 3-2 | downloadable_products.dart | `lib/screens/downloadable_products/view/downloadable_products.dart` | ダウンロード完了時の処理（117-127行目） |

**主要処理フロー**:
- **41-53行目**: DownloadProductEventハンドラ（ShowLoaderState発行、API呼び出し）
- **54-68行目**: DownloadBase64ProductEventハンドラ（Base64データ取得）
- **121-122行目**: saveBase64String呼び出し（ファイル保存と通知表示）

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

```
download_button.dart (UI Layer)
    │
    └─ DownloadProductEvent発行
           │
           ▼
    DownloadableProductsBloc
           │
           ├─ ShowLoaderState発行（ローディング表示）
           │
           ├─ DownloadProductEvent handler
           │      │
           │      └─ Repository.downloadProductLink()
           │             │
           │             └─ DownloadProductState発行
           │
           └─ DownloadBase64ProductEvent handler（自動発行）
                  │
                  └─ Repository.dataBase64ProductModel()
                         │
                         └─ DownloadBase64ProductState発行
                                │
                                ▼
    downloadable_products.dart (listener)
           │
           └─ DownloadFile.saveBase64String()
                  │
                  └─ createDownloadNotification(total, progress, name, path)
                         │
                         ▼
    PushNotificationsManager
           │
           └─ flutterLocalNotificationsPlugin.show()
                  │
                  ├─ progress < total → "Started" + Progress Bar
                  │
                  └─ progress == total → "Completed"
```

### データフロー図

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

User Tap Download  ───▶  DownloadProductEvent       ───▶  API Call
                              │
                              ▼
                         ShowLoaderState           ───▶  Loading UI
                              │
                              ▼
                         Download Link取得
                              │
                              ▼
                    DownloadBase64ProductEvent
                              │
                              ▼
                         Base64データ取得
                              │
                              ▼
                    createDownloadNotification()
                              │
                              ▼
                    ┌─────────────────────────────┐
                    │   progress < total ?        │
                    │   ┌─────┐      ┌─────────┐ │
                    │   │ Yes │      │   No    │ │
                    │   └──┬──┘      └────┬────┘ │
                    │      ▼              ▼      │
                    │ "Started"     "Completed"  │
                    │ + Progress    (No Progress)│
                    └─────────────────────────────┘
                              │
                              ▼
                    System Notification Bar
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| push_notifications_manager.dart | `lib/utils/push_notifications_manager.dart` | ソース | 通知管理、createDownloadNotification |
| downloadable_products.dart | `lib/screens/downloadable_products/view/downloadable_products.dart` | ソース | ダウンロード可能商品一覧画面 |
| download_button.dart | `lib/screens/downloadable_products/view/widgets/download_button.dart` | ソース | ダウンロードボタンウィジェット |
| downloadable_products_bloc.dart | `lib/screens/downloadable_products/bloc/downloadable_products_bloc.dart` | ソース | 状態管理、API呼び出し |
| downloadable_products_events.dart | `lib/screens/downloadable_products/bloc/downloadable_products_events.dart` | ソース | イベント定義 |
| downlaodable_products_state.dart | `lib/screens/downloadable_products/bloc/downlaodable_products_state.dart` | ソース | 状態定義 |
| string_constants.dart | `lib/utils/string_constants.dart` | 設定 | 文字列定数定義（started） |
