# 機能設計書 57-通知一覧表示

## 概要

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

### 本機能の処理概要

未読・既読の通知一覧を表示することで、ユーザーが自分に関連するアクティビティを把握できる機能である。

**業務上の目的・背景**：チームでのコラボレーションにおいて、自分宛のメンション、アサインの変更、コメントの追加など、様々なイベントが発生する。本機能により、これらの通知を一元的に確認でき、見落としを防ぎ、迅速な対応を可能にする。

**機能の利用シーン**：ヘッダーの通知アイコンをクリックして通知一覧画面にアクセスする。未読通知は上部に表示され、既読通知は下部にページネーションで表示される。各通知をクリックすると関連するカードやコメントに遷移できる。

**主要な処理内容**：
1. ユーザーが通知一覧画面にアクセス
2. 未読通知を取得（最大500件、API経由は100件）
3. 既読通知をページネーション付きで取得
4. 通知を時系列順に表示
5. Action Cableでリアルタイム更新

**関連システム・外部連携**：Action Cableによるリアルタイム通知更新

**権限による制御**：ユーザー固有の通知のみが表示される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 33 | 通知一覧画面 | 主画面 | 未読・既読の通知一覧を表示 |
| 34 | 通知トレイ画面 | 関連画面 | 通知トレイをポップアップ表示 |

## 機能種別

データ検索・参照

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| page | Integer | No | ページ番号（既読通知用） | 正の整数 |

### 入力データソース

なし（画面アクセス）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| @unread | Array | 未読通知一覧（最大500件/100件） |
| @page | Array | 既読通知一覧（ページネーション） |

### 出力先

- 画面表示（HTML/Turbo Stream/JSON）

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ GET /notifications
2. 未読通知取得
   └─ Current.user.notifications.unread.ordered.preloaded.limit(max)
   └─ ※ページパラメータがない場合のみ
3. 既読通知取得
   └─ Current.user.notifications.read.ordered.preloaded
   └─ ページネーション処理
4. レスポンス返却
   └─ HTML/Turbo Stream/JSONでレスポンスを返す
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B{ページパラメータあり?}
    B -->|No| C[未読通知取得]
    B -->|Yes| D[未読通知スキップ]
    C --> E[既読通知取得]
    D --> E
    E --> F[ページネーション処理]
    F --> G{リクエスト形式}
    G -->|HTML| H[通常HTML返却]
    G -->|Turbo Stream| I[Turbo Stream返却]
    G -->|JSON| J[JSON返却]
    H --> K[終了]
    I --> K
    J --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-57-01 | 未読上限 | 未読通知は最大500件まで表示（API経由は100件） | 常時 |
| BR-57-02 | 表示順序 | read_at降順、updated_at降順で表示 | 常時 |
| BR-57-03 | プリロード | card, board, column, creator等を事前読み込み | 常時 |
| BR-57-04 | ページパラメータ | ページパラメータがある場合は未読通知をスキップ | 既読一覧ページング時 |

### 計算ロジック

**未読通知上限の決定**:
```ruby
request.format.json? ? MAX_UNREAD_NOTIFICATIONS_VIA_API : MAX_UNREAD_NOTIFICATIONS
# JSON: 100件、それ以外: 500件
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 未読通知取得 | notifications | SELECT | read_at IS NULL の通知を取得 |
| 既読通知取得 | notifications | SELECT | read_at IS NOT NULL の通知を取得 |

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

#### notifications

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | user_id | Current.user.id | ユーザー制限 |
| SELECT | read_at | IS NULL（未読） / IS NOT NULL（既読） | 未読/既読フィルタ |
| SELECT | * | ORDER BY read_at DESC, updated_at DESC | ソート条件 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 空結果 | 通知がない場合 | 「通知はありません」メッセージ表示 |

### リトライ仕様

リトライは不要

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

参照系処理のため、トランザクション制御は不要。

## パフォーマンス要件

- レスポンス時間: 300ms以内
- プリロードによるN+1問題の回避
- インデックス: user_id + read_at + updated_at

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

- ログイン必須（ApplicationControllerで制御）
- Current.user.notificationsスコープによりユーザー固有の通知のみ取得
- CSRFトークン検証（Railsデフォルト）

## 備考

- Action Cable経由で新着通知がリアルタイムにブロードキャストされる
- after_create_commit/after_update_commit/after_destroy_commitでブロードキャスト
- 通知トレイ（ポップアップ）とは別のフルページ表示

---

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

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

### 推奨読解順序

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

まず、通知のデータモデルとスコープを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | notification.rb | `app/models/notification.rb` | Notificationモデル、スコープ、ブロードキャスト |

**読解のコツ**:
- `belongs_to :source, polymorphic: true`で様々なソースに対応
- `scope :unread / :read`で未読/既読をフィルタ
- `scope :ordered`でソート順を定義
- `after_create_commit`等でAction Cableブロードキャスト

**主要処理フロー**:
- **10-11行目**: unread、readスコープ
- **12行目**: orderedスコープ
- **13-19行目**: preloadedスコープ（関連データ事前読み込み）
- **25-27行目**: after_commitコールバック（ブロードキャスト）
- **32-38行目**: read_all、unread_allクラスメソッド
- **41-47行目**: read、unreadインスタンスメソッド

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

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

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

**主要処理フロー**:
- **2-3行目**: MAX定数定義（500/100）
- **5-6行目**: indexアクション（未読通知取得条件）
- **7行目**: 既読通知のページネーション取得
- **9-13行目**: レスポンス形式別の処理
- **16-18行目**: max_unread_notificationsメソッド

**読解のコツ**:
- `current_page_param`がない場合のみ未読通知を取得
- `set_page_and_extract_portion_from`でページネーション処理

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

```
NotificationsController#index
    │
    ├─ [未読通知取得]（ページパラメータがない場合）
    │      │
    │      └─ Current.user.notifications
    │             .unread
    │             .ordered
    │             .preloaded
    │             .limit(max_unread_notifications)
    │                    │
    │                    └─ @unread に設定
    │
    └─ [既読通知取得]
           │
           └─ set_page_and_extract_portion_from(
                  Current.user.notifications
                      .read
                      .ordered
                      .preloaded
              )
                  │
                  └─ @page に設定
```

### データフロー図

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

GET /notifications
    │
    ▼
page パラメータ ───▶ ページパラメータチェック
    │
    ├─ [なし] ───▶ 未読通知取得        ───▶ @unread
    │
    ▼
既読通知取得          ───────────────────▶ @page
    │
    ▼
respond_to
    │
    ├─ turbo_stream ───▶ index.turbo_stream.erb
    ├─ html         ───▶ index.html.erb
    └─ json         ───▶ index.json.jbuilder
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| notifications_controller.rb | `app/controllers/notifications_controller.rb` | コントローラー | 通知一覧取得 |
| notification.rb | `app/models/notification.rb` | モデル | 通知のデータモデル |
| index.html.erb | `app/views/notifications/index.html.erb` | ビュー | 通知一覧画面 |
| index.turbo_stream.erb | `app/views/notifications/index.turbo_stream.erb` | ビュー | Turbo Streamレスポンス |
| _notification.html.erb | `app/views/notifications/_notification.html.erb` | パーシャル | 通知アイテム表示 |
| _unread_notifications.html.erb | `app/views/notifications/index/_unread_notifications.html.erb` | パーシャル | 未読通知セクション |
| _read_notifications.html.erb | `app/views/notifications/index/_read_notifications.html.erb` | パーシャル | 既読通知セクション |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義 |
| schema.rb | `db/schema.rb` | スキーマ | notificationsテーブル定義 |
