# 機能設計書 60-通知設定

## 概要

本ドキュメントは、Fizzyアプリケーションにおける通知設定機能の詳細設計を記述する。

### 本機能の処理概要

メール通知の頻度や配信設定を変更することで、ユーザーの好みに合わせた通知受信環境を構築する機能である。

**業務上の目的・背景**：通知は重要な情報を伝える一方、頻度が高すぎると作業の妨げになることもある。本機能により、ユーザーは自身の働き方に合わせてメール通知の頻度を調整でき、必要な情報を適切なタイミングで受け取れるようになる。

**機能の利用シーン**：通知設定画面にアクセスし、メール通知の頻度（即時、数時間ごと、毎日、毎週、なし）を選択して保存する。新規参加時や業務スタイルの変化に応じて設定を変更する場合に使用される。

**主要な処理内容**：
1. ユーザーが通知設定画面にアクセス
2. 現在の設定とボード一覧を表示
3. メール通知頻度を選択して保存
4. 設定に応じてバンドル通知の処理を調整

**関連システム・外部連携**：通知バンドル機能との連携（メール通知のバッチ処理）

**権限による制御**：ユーザー固有の設定のみが変更可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 35 | 通知設定画面 | 主画面 | メール通知の頻度や配信設定を変更 |

## 機能種別

CRUD操作（READ/UPDATE）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| user_settings[bundle_email_frequency] | String | Yes | メール通知頻度 | never/every_few_hours/daily/weekly のいずれか |

### 入力データソース

画面入力（設定フォーム）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| @settings | User::Settings | ユーザーの設定オブジェクト |
| @boards | Array | ユーザーがアクセス可能なボード一覧 |

### 出力先

- 画面表示（設定画面）
- データベース（user_settingsテーブル）

## 処理フロー

### 処理シーケンス（show）

```
1. リクエスト受信
   └─ GET /notifications/settings
2. 設定取得
   └─ Current.user.settings
3. ボード一覧取得
   └─ Current.user.boards.alphabetically
4. レスポンス返却
   └─ 設定画面を表示
```

### 処理シーケンス（update）

```
1. リクエスト受信
   └─ PATCH /notifications/settings
2. 設定取得
   └─ Current.user.settings
3. 設定更新
   └─ @settings.update!(settings_params)
4. バンドル処理調整
   └─ review_pending_bundles（after_updateコールバック）
5. レスポンス返却
   └─ 設定画面にリダイレクト（成功メッセージ付き）
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B{アクション}
    B -->|show| C[設定取得]
    B -->|update| D[設定取得]
    C --> E[ボード一覧取得]
    E --> F[設定画面表示]
    D --> G[設定更新]
    G --> H{頻度変更?}
    H -->|Yes| I[review_pending_bundles]
    H -->|No| J[リダイレクト]
    I --> K{バンドリング有効?}
    K -->|Yes| L[flush_pending_bundles]
    K -->|No| M[cancel_pending_bundles]
    L --> J
    M --> J
    F --> N[終了]
    J --> N
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-60-01 | 頻度選択 | never/every_few_hours/daily/weeklyから選択 | 常時 |
| BR-60-02 | バンドル有効判定 | bundle_email_never?でない、システムユーザーでない、アクティブ、認証済みの場合に有効 | bundling_emails?で判定 |
| BR-60-03 | 頻度変更時処理 | 頻度変更時に保留中のバンドルを処理 | 設定更新後 |
| BR-60-04 | バンドル無効化時 | neverに変更時は保留中のバンドルをキャンセル | 設定更新後 |
| BR-60-05 | バンドル有効化時 | バンドリングが有効な場合は保留中のバンドルをフラッシュ | 設定更新後 |

### 計算ロジック

**バンドル集約期間の計算**:
```ruby
def bundle_aggregation_period
  case bundle_email_frequency
  when "every_few_hours" then 4.hours
  when "daily" then 1.day
  when "weekly" then 1.week
  else 1.day
  end
end
```

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 設定取得 | user_settings | SELECT | ユーザーの設定を取得 |
| 設定更新 | user_settings | UPDATE | メール通知頻度を更新 |
| バンドルキャンセル | notification_bundles | DELETE | 保留中のバンドルを削除 |

### テーブル別操作詳細

#### user_settings

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | user_id | Current.user.id | ユーザー制限 |
| UPDATE | bundle_email_frequency | パラメータから取得 | 0: never, 1: every_few_hours, 2: daily, 3: weekly |
| UPDATE | updated_at | 現在時刻 | 自動更新 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 422 | Unprocessable Entity | 無効な頻度値 | バリデーションエラー表示 |

### リトライ仕様

リトライは不要

## トランザクション仕様

update!は単一トランザクションで実行される。after_updateコールバックも同一トランザクション内で完了。

## パフォーマンス要件

- レスポンス時間: 200ms以内

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

- ログイン必須（ApplicationControllerで制御）
- Current.user.settingsスコープによりユーザー固有の設定のみ更新可能
- CSRFトークン検証（Railsデフォルト）
- Strong Parametersによるパラメータ制限

## 備考

- メール通知頻度はenumで定義（never: 0, every_few_hours: 1, daily: 2, weekly: 3）
- 頻度変更時にafter_updateコールバックでバンドル処理を調整
- システムユーザー、非アクティブユーザー、未認証ユーザーはバンドリング無効

---

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

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

### 推奨読解順序

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

まず、ユーザー設定モデルと通知頻度の定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | settings.rb | `app/models/user/settings.rb` | User::Settingsモデル、enum定義、バンドル処理 |

**読解のコツ**:
- `enum :bundle_email_frequency`で通知頻度を定義
- `bundling_emails?`でバンドリングが有効かを判定
- `after_update :review_pending_bundles`で頻度変更時の処理を実行

**主要処理フロー**:
- **5-6行目**: bundle_email_frequencyのenum定義
- **8行目**: after_updateコールバック
- **10-20行目**: bundle_aggregation_periodメソッド（集約期間の計算）
- **23-25行目**: bundling_emails?メソッド（バンドリング有効判定）
- **35-42行目**: review_pending_bundlesメソッド（バンドル処理）
- **44-51行目**: cancel/flush_pending_bundlesメソッド

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

リクエストを受け取るコントローラーの処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | settings_controller.rb | `app/controllers/notifications/settings_controller.rb` | show/updateアクションの処理フロー |

**主要処理フロー**:
- **2行目**: before_actionでset_settingsを実行
- **4-6行目**: showアクション（設定とボード一覧取得）
- **8-10行目**: updateアクション（設定更新とリダイレクト）
- **13-15行目**: set_settingsメソッド
- **17-19行目**: settings_paramsメソッド（Strong Parameters）

**読解のコツ**:
- `params.expect(user_settings: :bundle_email_frequency)`でパラメータを制限
- 更新成功時はnotice付きでリダイレクト

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

```
Notifications::SettingsController#update
    │
    ├─ [before_action] #set_settings
    │      └─ @settings = Current.user.settings
    │
    └─ @settings.update!(settings_params)
           │
           └─ [after_update] User::Settings#review_pending_bundles
                  │
                  └─ bundling_emails?
                         │
                         ├─ [true] flush_pending_bundles
                         │      └─ user.notification_bundles.pending.find_each(&:flush)
                         │
                         └─ [false] cancel_pending_bundles
                                └─ user.notification_bundles.pending.find_each(&:destroy)
```

### データフロー図

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

GET /notifications/settings
    │
    ▼
set_settings        ───▶ @settings
    │
    ▼
boards.alphabetically ─▶ @boards
    │
    ▼
設定画面表示        ───▶ ブラウザ

---

PATCH /notifications/settings
    │
    ▼
user_settings[bundle_email_frequency]
    │
    ▼
@settings.update!   ───▶ user_settings (UPDATE)
    │
    ▼
[after_update]
review_pending_bundles
    │
    ├─ bundling? ───▶ flush_pending_bundles
    └─ not bundling ─▶ cancel_pending_bundles
    │
    ▼
redirect_to         ───▶ 設定画面
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| settings_controller.rb | `app/controllers/notifications/settings_controller.rb` | コントローラー | 通知設定の表示・更新 |
| settings.rb | `app/models/user/settings.rb` | モデル | ユーザー設定のデータモデル |
| show.html.erb | `app/views/notifications/settings/show.html.erb` | ビュー | 通知設定画面 |
| _email.html.erb | `app/views/notifications/settings/_email.html.erb` | パーシャル | メール設定セクション |
| _browser.html.erb | `app/views/notifications/settings/_browser.html.erb` | パーシャル | ブラウザ設定セクション |
| _push_notifications.html.erb | `app/views/notifications/settings/_push_notifications.html.erb` | パーシャル | プッシュ通知設定 |
| _board.html.erb | `app/views/notifications/settings/_board.html.erb` | パーシャル | ボード別設定 |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義 |
| schema.rb | `db/schema.rb` | スキーマ | user_settingsテーブル定義 |
