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

## 概要

本ドキュメントは、GitLabにおけるユーザー通知設定機能の設計を記述する。ユーザーはグローバル、グループ単位、プロジェクト単位で通知レベルと通知先メールアドレスをカスタマイズできる。

### 本機能の処理概要

**業務上の目的・背景**：開発者は日々多くのプロジェクト、イシュー、マージリクエストに関わっており、適切な通知管理が生産性に大きく影響する。GitLabの通知設定機能は、ユーザーが必要な情報のみを受け取り、情報過多を防ぐための柔軟な設定を提供する。グローバル設定をベースに、グループやプロジェクト単位での詳細なカスタマイズが可能である。

**機能の利用シーン**：
- 特定プロジェクトの通知を完全に無効化したい場合
- 重要なプロジェクトのみ全ての通知を受け取りたい場合
- 自分が参加している議論のみ通知を受け取りたい場合
- 特定イベント（パイプライン失敗等）のみカスタム通知を設定したい場合
- 通知先メールアドレスをプロジェクト毎に変えたい場合

**主要な処理内容**：
1. グローバル通知設定の表示・更新
2. グループ別通知設定の表示・更新
3. プロジェクト別通知設定の表示・更新
4. 通知レベルの設定（disabled, participating, watch, mention, custom）
5. カスタム通知時の個別イベント有効/無効設定
6. 通知先メールアドレスの設定

**関連システム・外部連携**：
- メール送信システム（通知メール配信）
- イベントシステム（各種イベント発生時の通知トリガー）
- ユーザーメール管理（確認済みメールアドレスの参照）

**権限による制御**：
- ユーザーは自身の通知設定のみ管理可能
- 通知先メールアドレスは確認済みメールのみ選択可能

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 204 | 通知設定 | 主画面 | 通知設定の管理 |
| 217 | 通知停止 | 主画面 | メール通知の停止確認 |

## 機能種別

CRUD操作 / 設定管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| level | Integer/Enum | Yes | 通知レベル（0-5） | 有効な値のみ |
| notification_email | String | No | 通知先メールアドレス | 確認済みメールのみ |
| new_note | Boolean | No | 新規コメント通知 | カスタム時のみ |
| new_issue | Boolean | No | 新規イシュー通知 | カスタム時のみ |
| reopen_issue | Boolean | No | イシュー再オープン通知 | カスタム時のみ |
| close_issue | Boolean | No | イシュークローズ通知 | カスタム時のみ |
| reassign_issue | Boolean | No | イシュー担当者変更通知 | カスタム時のみ |
| issue_due | Boolean | No | イシュー期限通知 | カスタム時のみ |
| new_merge_request | Boolean | No | 新規MR通知 | カスタム時のみ |
| push_to_merge_request | Boolean | No | MRへのプッシュ通知 | カスタム時のみ |
| reopen_merge_request | Boolean | No | MR再オープン通知 | カスタム時のみ |
| close_merge_request | Boolean | No | MRクローズ通知 | カスタム時のみ |
| reassign_merge_request | Boolean | No | MR担当者変更通知 | カスタム時のみ |
| change_reviewer_merge_request | Boolean | No | MRレビュアー変更通知 | カスタム時のみ |
| merge_merge_request | Boolean | No | MRマージ通知 | カスタム時のみ |
| failed_pipeline | Boolean | No | パイプライン失敗通知 | カスタム時のみ |
| fixed_pipeline | Boolean | No | パイプライン修復通知 | カスタム時のみ |
| success_pipeline | Boolean | No | パイプライン成功通知 | カスタム時のみ |
| moved_project | Boolean | No | プロジェクト移動通知 | カスタム時のみ |
| merge_when_pipeline_succeeds | Boolean | No | パイプライン成功時マージ通知 | カスタム時のみ |
| new_release | Boolean | No | 新規リリース通知 | カスタム時のみ |

### 入力データソース

- 画面入力（Profiles::NotificationsController経由）
- API経由

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | Integer | 通知設定ID |
| level | Enum | 通知レベル |
| notification_email | String | 通知先メールアドレス |
| source_type | String | 設定対象種別（Namespace/Project） |
| source_id | Integer | 設定対象ID |
| 各イベントフラグ | Boolean | イベント別通知有効/無効 |

### 出力先

- 画面表示（通知設定一覧）

## 処理フロー

### 処理シーケンス

```
1. 通知設定画面アクセス
   └─ Profiles::NotificationsController#show
2. 現在の設定取得
   └─ グローバル設定、グループ設定、プロジェクト設定の取得
3. 設定更新リクエスト
   └─ Profiles::NotificationsController#update
4. バリデーション
   └─ 通知先メール確認状態チェック
5. 設定保存
   └─ Users::UpdateService経由で保存
6. 結果返却
   └─ フラッシュメッセージと共にリダイレクト
```

### フローチャート

```mermaid
flowchart TD
    A[設定画面アクセス] --> B[現在設定取得]
    B --> C[グローバル設定]
    B --> D[グループ設定一覧]
    B --> E[プロジェクト設定一覧]
    C --> F[設定表示]
    D --> F
    E --> F
    F --> G{更新リクエスト?}
    G -->|No| H[表示のみ]
    G -->|Yes| I{メール確認済み?}
    I -->|No| J[バリデーションエラー]
    I -->|Yes| K[設定保存]
    K --> L[成功メッセージ]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-83-01 | 通知レベル階層 | グローバル→グループ→プロジェクトの順で設定が継承される | 常時 |
| BR-83-02 | カスタム通知 | level=customの場合、個別イベント設定が有効になる | level=5時 |
| BR-83-03 | 確認済みメール必須 | 通知先メールは確認済みアドレスのみ選択可能 | notification_email設定時 |
| BR-83-04 | パイプライン通知デフォルト | failed_pipeline/fixed_pipelineはnullの場合true扱い | カスタム通知時 |
| BR-83-05 | Watcher除外イベント | watchレベルでも一部イベントは通知対象外 | level=watch時 |

### 計算ロジック

**通知レベル**：
- 0: disabled - 全通知無効
- 1: participating - 参加中のスレッドのみ
- 2: watch - 全イベント通知（一部除外あり）
- 3: global - 上位設定を継承
- 4: mention - メンションのみ
- 5: custom - カスタム設定

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 取得 | notification_settings | SELECT | 現在の設定取得 |
| 更新 | notification_settings | UPDATE | 設定値更新 |
| 作成 | notification_settings | INSERT | 新規設定作成（初回アクセス時） |
| 更新 | users | UPDATE | notification_emailフィールド更新 |

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

#### notification_settings

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | user_id, source_type, source_id | ユーザーID、ソース指定 | |
| INSERT/UPDATE | level | 選択されたレベル | |
| INSERT/UPDATE | notification_email | 選択されたメール | |
| INSERT/UPDATE | 各イベントフラグ | true/false | カスタム時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | バリデーションエラー | 未確認メールアドレス指定 | エラーメッセージ表示 |
| - | 保存エラー | データベースエラー | フラッシュアラート表示 |

### リトライ仕様

設定保存はユーザー操作の再実行による。

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

設定更新は単一レコードの更新のため、明示的なトランザクション不要。

## パフォーマンス要件

- 設定画面表示：500ms以内
- 設定更新：200ms以内

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

- 通知先メールは確認済みアドレスのみ許可
- ユーザーは自身の設定のみ編集可能

## 備考

- EMAIL_EVENTSで定義されたイベントのみカスタマイズ可能
- EXCLUDED_WATCHER_EVENTSはwatchレベルでも通知対象外

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | notification_setting.rb | `app/models/notification_setting.rb` | 通知設定モデル、イベント定義 |

**読解のコツ**: enumによるレベル定義とEMAIL_EVENTSの配列がカスタム通知の基盤。

**主要処理フロー**:
- **7行目**: enum :level - 通知レベル定義（global, watch, participating等）
- **9-11行目**: アソシエーション定義
- **38-58行目**: EMAIL_EVENTS - カスタマイズ可能なイベント一覧
- **60-66行目**: EXCLUDED_WATCHER_EVENTS - watchでも除外されるイベント
- **90-97行目**: reset_email_for_user! - メール削除時のリセット処理
- **102-114行目**: failed_pipeline/fixed_pipelineのデフォルト動作
- **124-129行目**: notification_email_verified - メール確認バリデーション

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | notifications_controller.rb | `app/controllers/profiles/notifications_controller.rb` | コントローラーアクション |

**主要処理フロー**:
- **7-13行目**: show - 設定表示（グローバル、グループ、プロジェクト）
- **15-25行目**: update - 設定更新

#### Step 3: 通知受信者決定ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | build_service.rb | `app/services/notification_recipients/build_service.rb` | 通知受信者構築 |
| 3-2 | base.rb | `app/services/notification_recipients/builder/base.rb` | ビルダー基底クラス |

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

```
Profiles::NotificationsController#show
    │
    ├─ current_user.global_notification_setting
    │
    ├─ UserGroupNotificationSettingsFinder#execute
    │      └─ NotificationSetting (グループ別)
    │
    └─ NotificationSetting.for_projects
           └─ プロジェクト別設定

Profiles::NotificationsController#update
    │
    └─ Users::UpdateService#execute
           └─ user.update(notification_email, notified_of_own_activity)

NotificationService (通知送信時)
    │
    └─ NotificationRecipients::BuildService
           ├─ 通知レベル判定
           ├─ カスタム設定確認
           └─ 受信者リスト構築
```

### データフロー図

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

ユーザー設定         NotificationsController           DB保存
(level,         ──▶ ├─バリデーション            ──▶  notification_settings
 notification_email) ├─メール確認チェック
                     └─Users::UpdateService

イベント発生     NotificationService               メール送信
            ──▶ ├─NotificationRecipients::Build ──▶ 対象ユーザー
                 └─設定に基づく受信者判定
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| notification_setting.rb | `app/models/notification_setting.rb` | モデル | 通知設定データモデル |
| notifications_controller.rb | `app/controllers/profiles/notifications_controller.rb` | コントローラー | Web UI用コントローラー |
| build_service.rb | `app/services/notification_recipients/build_service.rb` | サービス | 通知受信者構築 |
| base.rb | `app/services/notification_recipients/builder/base.rb` | サービス | ビルダー基底クラス |
| notification_service.rb | `app/services/notification_service.rb` | サービス | 通知送信メインサービス |
