# 機能設計書 99-一括削除

## 概要

本ドキュメントは、Chatwoot における通知一括削除機能の設計を記載する。

### 本機能の処理概要

一括削除機能は、ユーザーの通知を一括で削除する機能である。すべての通知を削除するか、既読の通知のみを削除するかを選択できる。非同期ジョブにより処理されるため、大量の通知があってもUIがブロックされない。

**業務上の目的・背景**：長期間使用していると通知が蓄積し、パフォーマンスやストレージに影響を与える可能性がある。一括削除機能により、不要な通知を効率的にクリーンアップし、システムを最適な状態に保つことができる。

**機能の利用シーン**：
- 過去の通知をまとめて整理したい場合
- 既読の通知のみを削除して未読通知を残したい場合
- アカウントのデータ整理を行う場合

**主要な処理内容**：
1. 削除タイプの判定（全通知 or 既読のみ）
2. DeleteNotificationJobを非同期で実行
3. バックグラウンドでの通知削除

**関連システム・外部連携**：
- Sidekiq（非同期ジョブ処理）

**権限による制御**：自分の通知のみ削除可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 26 | 通知一覧画面 | 主画面 | 「すべて削除」ボタンの実行 |

## 機能種別

バルク操作 / 非同期処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| type | String | No | 削除タイプ（read: 既読のみ、未指定: 全て） | read または 未指定 |

### 入力データソース

画面入力（API経由）

## 出力仕様

### 出力データ

レスポンスボディは空。HTTPステータスコード200（OK）を返却。

### 出力先

HTTPレスポンス

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ NotificationsController#destroy_allがリクエストを受信
2. 削除タイプ判定
   ├─ type == 'read': 既読通知のみ削除
   └─ それ以外: 全通知削除
3. DeleteNotificationJobを非同期実行
   └─ perform_later(Current.user, type: :read/:all)
4. レスポンス返却
   └─ head :ok（即座に返却、削除は非同期）
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B{認証確認}
    B -->|未認証| C[401エラー]
    B -->|認証済| D{type == 'read'?}
    D -->|Yes| E[DeleteNotificationJob type: :read]
    D -->|No| F[DeleteNotificationJob type: :all]
    E --> G[perform_later]
    F --> G
    G --> H[200 OK即座に返却]
    G --> I[バックグラウンドで削除処理]
    I --> J[トランザクション内で削除]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-99-01 | ユーザー制限 | 自分の通知のみ削除可能 | 全操作 |
| BR-99-02 | 削除タイプ | type='read'で既読のみ、それ以外は全削除 | 全操作 |
| BR-99-03 | 非同期処理 | 削除はバックグラウンドジョブで実行 | 全操作 |
| BR-99-04 | 物理削除 | 通知は論理削除ではなく物理削除 | 全操作 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| destroy_all (type: :all) | notifications | DELETE | 全通知削除 |
| destroy_all (type: :read) | notifications | DELETE | 既読通知のみ削除 |

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

#### notifications

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE (all) | - | user_id = current_user.id | 全通知削除 |
| DELETE (read) | - | user_id = current_user.id AND read_at IS NOT NULL | 既読通知のみ |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | Unauthorized | 未認証 | ログインが必要 |

### リトライ仕様

DeleteNotificationJobはSidekiqで実行されるため、失敗時は自動リトライされる。

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

DeleteNotificationJob内でActiveRecord::Base.transactionを使用し、削除処理をトランザクション内で実行。

## パフォーマンス要件

- 非同期処理により即座にレスポンス返却
- destroy_allによる一括削除（個別削除より高速）
- low キューで実行（優先度低め）

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

- Current.user の通知のみ削除対象
- ジョブ実行時にユーザー情報を引き渡し

## 備考

destroy_allはコールバックを発火する。コールバックなしで高速に削除する場合はdelete_allを検討するが、現在の実装ではdestroy_allを使用している。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | notifications_controller.rb | `app/controllers/api/v1/accounts/notifications_controller.rb` | destroy_allアクションの実装 |

**読解のコツ**:
- **42-49行目**: destroy_all アクション - type判定とジョブ登録

**主要処理フロー**:
1. **43-44行目**: type == 'read' の場合、type: :read でジョブ登録
2. **45-46行目**: それ以外の場合、type: :all でジョブ登録
3. **48行目**: head :ok で即座にレスポンス返却

#### Step 2: ジョブロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | delete_notification_job.rb | `app/jobs/notification/delete_notification_job.rb` | 削除処理の実装 |

**読解のコツ**:
- **2行目**: queue_as :low - 低優先度キュー
- **4-14行目**: perform メソッド - トランザクション内で削除

**主要処理フロー**:
1. **5行目**: ActiveRecord::Base.transaction 開始
2. **6-8行目**: type == :all の場合、全通知削除
3. **9-11行目**: type == :read の場合、既読通知のみ削除
4. **7, 10行目**: destroy_all で削除実行

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

```
Api::V1::Accounts::NotificationsController
    │
    └─ destroy_all
           │
           ├─ params[:type] == 'read'
           │      └─ DeleteNotificationJob.perform_later(Current.user, type: :read)
           │
           └─ params[:type] != 'read'
                  └─ DeleteNotificationJob.perform_later(Current.user, type: :all)
                         │
                         └─ (非同期実行)
                                │
                                └─ Notification::DeleteNotificationJob#perform
                                       │
                                       ├─ type: :all
                                       │      └─ user.notifications.destroy_all
                                       │
                                       └─ type: :read
                                              └─ user.notifications
                                                     .where.not(read_at: nil)
                                                     .destroy_all
```

### データフロー図

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

type: 'read' ──────▶ NotificationsController#destroy_all
    または                      │
   (なし)                       ▼
                         DeleteNotificationJob
                              登録
                               │
                               ▼
                          head :ok (即座)

                               │ (非同期)
                               ▼
                    Notification::DeleteNotificationJob
                               │
                               ▼
                       トランザクション開始
                               │
                    ┌──────────┼──────────┐
                    ▼          ▼          ▼
              type: :all  type: :read  (other)
                    │          │
                    ▼          ▼
              全通知削除  既読のみ削除
                    │          │
                    └────┬─────┘
                         ▼
                  トランザクション終了
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| notifications_controller.rb | `app/controllers/api/v1/accounts/notifications_controller.rb` | コントローラー | destroy_allアクション |
| delete_notification_job.rb | `app/jobs/notification/delete_notification_job.rb` | ジョブ | 非同期削除処理 |
| routes.rb | `config/routes.rb` | 設定 | POST destroy_all ルーティング |
