# 機能設計書 58-通知既読

## 概要

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

### 本機能の処理概要

通知を既読にすることで、確認済みの通知を未読一覧から除外し、未確認の通知を把握しやすくする機能である。

**業務上の目的・背景**：多くの通知が届く中で、確認済みの通知と未確認の通知を区別することは重要である。本機能により、ユーザーは確認した通知を既読にマークし、まだ対応が必要な通知に集中できる。

**機能の利用シーン**：通知一覧画面や通知トレイで、個別の通知の既読ボタンをクリックして実行する。また、通知をクリックしてカードに遷移した際も自動的に既読になる場合がある。

**主要な処理内容**：
1. ユーザーが通知の既読ボタンをクリック
2. 指定された通知を取得
3. read_atに現在時刻を設定し、unread_countを0にする
4. Turbo Streamで画面を更新（未読一覧から削除）

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

**権限による制御**：ユーザー固有の通知のみが既読に変更可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 33 | 通知一覧画面 | 主画面 | 通知を既読にする |
| 34 | 通知トレイ画面 | 関連画面 | 通知を既読にする（API連携） |

## 機能種別

CRUD操作（UPDATE）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| notification_id | UUID | Yes | 対象通知のID | 通知IDとして存在すること |

### 入力データソース

画面操作（既読ボタンクリック）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| @notification | Notification | 更新された通知オブジェクト |

### 出力先

- 画面表示（Turbo Stream）
- HTTPレスポンス（204 No Content - JSON時）

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ POST /notifications/:notification_id/reading
2. 通知取得
   └─ Current.user.notifications.find(params[:notification_id])
3. 既読処理
   └─ @notification.read
      └─ update!(read_at: Time.current, unread_count: 0)
4. レスポンス返却
   └─ Turbo Stream/JSONでレスポンスを返す
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B[通知取得]
    B --> C{通知存在?}
    C -->|No| D[404 Not Found]
    C -->|Yes| E[readメソッド実行]
    E --> F[read_at更新]
    F --> G[unread_count = 0]
    G --> H{リクエスト形式}
    H -->|Turbo Stream| I[Turbo Stream返却]
    H -->|JSON| J[204 No Content返却]
    I --> K[終了]
    J --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-58-01 | 既読マーク | read_atに現在時刻を設定 | 既読処理時 |
| BR-58-02 | 未読カウントリセット | unread_countを0に設定 | 既読処理時 |
| BR-58-03 | 未読に戻す | destroyアクションで未読に戻せる | 未読戻し時 |

### 計算ロジック

該当なし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 既読更新 | notifications | UPDATE | read_at、unread_countを更新 |

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

#### notifications

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | read_at | Time.current | 既読日時 |
| UPDATE | unread_count | 0 | 未読カウント |
| UPDATE | updated_at | 現在時刻 | 自動更新 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 404 | Not Found | 通知が存在しないか、他ユーザーの通知 | エラーページ表示 |

### リトライ仕様

リトライは不要

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

update!は単一トランザクションで実行される。

## パフォーマンス要件

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

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

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

## 備考

- 既読にした通知は未読に戻すことも可能（destroyアクション）
- Action Cableにより既読状態の変更がブロードキャストされる

---

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

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

### 推奨読解順序

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

まず、通知モデルの既読関連メソッドを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | notification.rb | `app/models/notification.rb` | readメソッド、unreadメソッド、read?メソッド |

**読解のコツ**:
- `read`メソッドでread_atとunread_countを更新
- `read?`メソッドでread_at.present?をチェック
- after_update_commitでブロードキャスト

**主要処理フロー**:
- **41-43行目**: readメソッド（既読処理）
- **45-47行目**: unreadメソッド（未読戻し）
- **49-51行目**: read?メソッド（既読判定）
- **62-67行目**: broadcast_updateメソッド（状態変更時のブロードキャスト）

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

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

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

**主要処理フロー**:
- **2-9行目**: createアクション（既読処理）
- **11-19行目**: destroyアクション（未読戻し）

**読解のコツ**:
- createで既読、destroyで未読に戻す
- Turbo StreamとJSONの両方に対応

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

```
Notifications::ReadingsController#create
    │
    ├─ Current.user.notifications.find(params[:notification_id])
    │      └─ @notification に通知を設定
    │
    └─ @notification.read
           │
           └─ update!(read_at: Time.current, unread_count: 0)
                  │
                  └─ [after_update_commit] broadcast_update
                         │
                         └─ broadcast_remove_to(user, :notifications)
```

### データフロー図

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

notification_id ───▶ notifications.find  ───▶ @notification
                       │
                       ▼
                 @notification.read
                       │
                       ├─ read_at = Time.current
                       └─ unread_count = 0
                       │
                       ▼
                 update!              ───▶ notifications (UPDATE)
                       │
                       ▼
                 broadcast_update
                       │
                       └─ broadcast_remove_to
                       │
                       ▼
                 Turbo Stream / JSON  ───▶ ブラウザ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| readings_controller.rb | `app/controllers/notifications/readings_controller.rb` | コントローラー | 通知既読/未読処理 |
| notification.rb | `app/models/notification.rb` | モデル | 通知のデータモデル |
| create.turbo_stream.erb | `app/views/notifications/readings/create.turbo_stream.erb` | ビュー | 既読時のTurbo Stream |
| destroy.turbo_stream.erb | `app/views/notifications/readings/destroy.turbo_stream.erb` | ビュー | 未読戻し時のTurbo Stream |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義 |
| schema.rb | `db/schema.rb` | スキーマ | notificationsテーブル定義 |
