# 機能設計書 21-カード削除

## 概要

本ドキュメントは、Fizzyアプリケーションにおけるカード削除機能の設計を記載するものです。

### 本機能の処理概要

カード削除機能は、カンバンボード上のカードを完全に削除する機能です。削除されたカードとその関連データ（コメント、ステップ、リアクション等）はすべてデータベースから削除されます。

**業務上の目的・背景**：プロジェクト管理において、不要になったタスクや誤って作成されたカードを整理する必要があります。カード削除機能により、ボードを整理し、チームの作業効率を維持することができます。削除は復元不可能な操作であるため、権限管理により誤削除を防止しています。

**機能の利用シーン**：
- 誤って作成したカードを削除したい場合
- 完了後に不要となったカードをボードから削除したい場合
- 重複して作成されたカードを整理したい場合

**主要な処理内容**：
1. 削除権限の確認（カード作成者またはアドミンのみ削除可能）
2. カードと関連データ（コメント、ステップ、リアクション、イベント等）の一括削除
3. ボード画面へのリダイレクト

**関連システム・外部連携**：特になし。ただし、Webhookが設定されている場合は削除イベントが通知される可能性があります。

**権限による制御**：
- カード作成者：自分が作成したカードのみ削除可能
- 管理者（admin/owner）：すべてのカードを削除可能
- 一般メンバー：自分が作成していないカードは削除不可

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 19 | カード詳細画面 | 主画面 | 削除ボタンを表示、削除確認後に実行 |

## 機能種別

CRUD操作（DELETE）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | String | Yes | カード番号（number） | 存在するカードであること |

### 入力データソース

- URL パラメータからカード番号を取得
- 現在ログイン中のユーザー情報（権限確認用）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| redirect_to | URL | 削除成功時のリダイレクト先（ボード画面） |
| HTTP Status | Integer | 成功時: 302 (redirect)、権限エラー時: 403 |

### 出力先

- HTML形式：ボード詳細画面へリダイレクト
- JSON形式：HTTP 204 No Content

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信（DELETE /cards/:id）
   └─ カード番号をURLパラメータから取得

2. カード取得
   └─ Current.user.accessible_cards から対象カードを検索

3. 権限確認
   └─ Current.user.can_administer_card?(@card) で削除権限を確認
   └─ 権限がない場合は 403 Forbidden を返却

4. カード削除実行
   └─ @card.destroy! で関連データも含めて削除

5. レスポンス返却
   └─ HTML: ボード画面へリダイレクト（notice: "Card deleted"）
   └─ JSON: HTTP 204 No Content
```

### フローチャート

```mermaid
flowchart TD
    A[削除リクエスト受信] --> B[カード取得]
    B --> C{カード存在?}
    C -->|No| D[404 Not Found]
    C -->|Yes| E{削除権限あり?}
    E -->|No| F[403 Forbidden]
    E -->|Yes| G[カード削除実行]
    G --> H{レスポンス形式}
    H -->|HTML| I[ボード画面へリダイレクト]
    H -->|JSON| J[204 No Content]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-21-01 | 削除権限制限 | カード削除は作成者またはアドミンのみ可能 | すべての削除操作 |
| BR-21-02 | 完全削除 | 削除されたカードは復元不可能 | すべての削除操作 |
| BR-21-03 | 関連データ削除 | カード削除時に関連データも自動削除される | すべての削除操作 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| カード削除 | cards | DELETE | カード本体の削除 |
| カード削除 | closures | DELETE | クローズ情報の削除（dependent: :destroy） |
| カード削除 | card_not_nows | DELETE | 延期情報の削除（dependent: :destroy） |
| カード削除 | comments | DELETE | コメントの削除（dependent: :destroy） |
| カード削除 | reactions | DELETE | リアクションの削除（dependent: :delete_all） |
| カード削除 | steps | DELETE | ステップの削除（dependent: :destroy） |
| カード削除 | events | DELETE | イベント履歴の削除 |
| カード削除 | active_storage_attachments | DELETE | 添付画像の削除 |

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

#### cards

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | - | WHERE number = :id AND account_id = :current_account_id | 物理削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 404 | RecordNotFound | 指定されたカードが存在しない、またはアクセス権がない | 適切なエラー画面を表示 |
| 403 | Forbidden | 削除権限がない場合 | 403ステータスを返却 |

### リトライ仕様

削除操作はリトライ不要（冪等性あり - 既に削除されていれば404）

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

カード削除とすべての関連データ削除は、ActiveRecordのdependent設定により自動的にトランザクション内で処理されます。いずれかの削除に失敗した場合、すべてロールバックされます。

## パフォーマンス要件

- 削除処理は1秒以内に完了すること
- 関連データが多い場合でも3秒以内に完了すること

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

- 認証：ログインユーザーのみアクセス可能（ApplicationControllerで制御）
- 認可：カード作成者またはアドミンのみ削除可能（can_administer_card?メソッドで検証）
- CSRF対策：Rails標準のCSRFトークン検証を適用
- データ保護：削除されたデータは復元不可能

## 備考

- 削除は物理削除であり、論理削除（ソフトデリート）ではない
- 削除前の確認ダイアログは画面側で実装

---

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

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

### 推奨読解順序

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

カードモデルとその関連モデルの構造を把握することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | card.rb | `app/models/card.rb` | Cardモデルの定義、関連（has_one/has_many）の確認。dependent: :destroyの設定により関連データが自動削除される点に注目 |
| 1-2 | closure.rb | `app/models/closure.rb` | クローズ情報モデル。belongs_to :cardの関連 |
| 1-3 | not_now.rb | `app/models/card/not_now.rb` | 延期情報モデル |

**読解のコツ**: Card モデルには多くのconcernがincludeされています。削除に関連するのは主にCloseable（closure）とPostponable（not_now）です。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | cards_controller.rb | `app/controllers/cards_controller.rb` | destroyアクションが削除のエントリーポイント |

**主要処理フロー**:
1. **5行目**: `before_action :set_card` - URLパラメータからカードを取得
2. **7行目**: `before_action :ensure_permission_to_administer_card` - 削除権限を確認
3. **42-49行目**: `destroy`アクション - カード削除と画面遷移処理
4. **56-58行目**: `set_card`メソッド - accessible_cardsから対象カードを検索
5. **64-66行目**: `ensure_permission_to_administer_card`メソッド - 権限チェック

#### Step 3: 権限管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | role.rb | `app/models/user/role.rb` | can_administer_card?メソッドの定義 |

**主要処理フロー**:
- **29-31行目**: `can_administer_card?(card)` - admin?またはカード作成者であるかを確認

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

```
CardsController#destroy
    │
    ├─ before_action :set_card
    │      └─ Current.user.accessible_cards.find_by!(number: params[:id])
    │
    ├─ before_action :ensure_permission_to_administer_card
    │      └─ Current.user.can_administer_card?(@card)
    │             └─ User::Role#can_administer_card?
    │                    └─ admin? || card.creator == self
    │
    └─ @card.destroy!
           ├─ Closure#destroy (dependent)
           ├─ Card::NotNow#destroy (dependent)
           ├─ Comments#destroy_all (dependent)
           ├─ Reactions#delete_all (dependent)
           ├─ Steps#destroy_all (dependent)
           └─ ActiveStorage::Attachment#purge_later (dependent)
```

### データフロー図

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

DELETE /cards/:id ──▶ CardsController#destroy ──▶ redirect_to board
                           │
                           ├─ set_card
                           │    └─ Card (取得)
                           │
                           ├─ 権限確認
                           │    └─ User#can_administer_card?
                           │
                           └─ @card.destroy!
                                └─ cards, closures, comments,
                                   reactions, steps, events (削除)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| cards_controller.rb | `app/controllers/cards_controller.rb` | コントローラー | 削除リクエストの受付と処理 |
| card.rb | `app/models/card.rb` | モデル | カードモデル定義、関連設定 |
| role.rb | `app/models/user/role.rb` | モデル(concern) | 権限チェックロジック |
| closure.rb | `app/models/closure.rb` | モデル | クローズ情報（削除対象） |
| not_now.rb | `app/models/card/not_now.rb` | モデル | 延期情報（削除対象） |
| _delete.html.erb | `app/views/cards/_delete.html.erb` | ビュー | 削除ボタンのパーシャル |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（76行目） |
