# 機能設計書 8-取引先削除

## 概要

本ドキュメントは、Fat Free CRMシステムにおける取引先削除機能の設計を定義する。この機能は、取引先を削除する。

### 本機能の処理概要

取引先削除機能は、既存の取引先レコードを削除するための機能である。削除された取引先に関連するデータ（連絡先との紐付け、商談との紐付け、タスクなど）も適切に処理される。

**業務上の目的・背景**：取引が終了した顧客や重複登録された取引先など、不要になった取引先情報をシステムから削除する必要がある。本機能により、データベースの整理と管理の効率化が可能となる。削除前に十分な確認が必要であるため、UIでは確認ダイアログが表示される。

**機能の利用シーン**：
- 取引が完全に終了した顧客の情報を削除する場面
- 重複登録された取引先を整理する場面
- テストデータを削除する場面

**主要な処理内容**：
1. 削除権限の確認
2. 取引先レコードの削除
3. 関連データの削除（dependent: :destroy）
4. 一覧画面またはHTML画面へのレスポンス

**関連システム・外部連携**：本機能は外部システムとの連携はなく、内部データベースの削除のみで構成される。

**権限による制御**：`load_and_authorize_resource`により、ユーザーが削除権限を持つ取引先のみ削除可能。通常は所有者のみが削除可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 7 | 取引先一覧画面 | 補助機能 | 取引先の削除処理 |
| 8 | 取引先詳細画面 | 遷移先機能 | 詳細画面からの取引先削除 |

## 機能種別

データ削除（DELETE操作）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | Integer | Yes | 取引先ID | 存在する取引先IDであること |

### 入力データソース

- URLパラメータ（:id）
- セッション情報（current_user）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| @account | Account | 削除された取引先 |
| @accounts | ActiveRecord::Relation<Account> | 更新された取引先一覧（AJAX時） |
| @account_category_total | HashWithIndifferentAccess | カテゴリ別件数（AJAX時） |

### 出力先

- AJAX応答（destroy.js.haml）
- HTMLリダイレクト（取引先一覧画面）
- データベース（accounts、関連テーブル）

## 処理フロー

### 処理シーケンス

```
1. load_and_authorize_resourceによるリソースロード・認可
2. @account.destroy実行
3. respond_withによるレスポンス分岐
   ├─ HTML形式: respond_to_destroy(:html)
   │   ├─ current_page = 1にリセット
   │   ├─ フラッシュメッセージ設定
   │   └─ 一覧画面へリダイレクト
   └─ JS形式: respond_to_destroy(:ajax)
       ├─ get_accountsで一覧再取得
       ├─ get_data_for_sidebarでサイドバー更新
       ├─ 一覧が空の場合、前ページ取得
       └─ destroy.js.hamlまたはindex.js.hamlレンダリング
```

### フローチャート

```mermaid
flowchart TD
    A[削除リクエスト] --> B[認可チェック]
    B --> C{認可OK?}
    C -->|No| D[403エラー]
    C -->|Yes| E[destroy実行]
    E --> F{フォーマット?}
    F -->|HTML| G[ページリセット]
    G --> H[フラッシュ設定]
    H --> I[一覧へリダイレクト]
    F -->|JS/AJAX| J[一覧再取得]
    J --> K[サイドバー更新]
    K --> L{一覧空?}
    L -->|Yes| M[前ページ取得]
    L -->|No| N[destroy.js返却]
    M --> O[index.js返却]
    I --> P[終了]
    N --> P
    O --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 削除権限 | 所有者のみ削除可能 | 常時 |
| BR-002 | 関連データ削除 | 紐付きデータ（タスク等）も削除 | dependent: :destroy |
| BR-003 | 削除後ページ | 一覧が空になった場合は前ページ表示 | AJAX削除時 |
| BR-004 | ソフトデリート | 論理削除（deleted_at設定） | Paranoia使用時 |

### 計算ロジック

特に計算ロジックは存在しない。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 取引先削除 | accounts | DELETE/UPDATE | 取引先レコードの削除（論理/物理） |
| 紐付き削除 | account_contacts | DELETE | 連絡先との紐付け削除 |
| 紐付き削除 | account_opportunities | DELETE | 商談との紐付け削除 |
| タスク削除 | tasks | DELETE | 紐付きタスク削除 |
| 住所削除 | addresses | DELETE | 紐付き住所削除 |
| 履歴作成 | versions | INSERT | 削除履歴（PaperTrail） |

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

#### accounts

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | deleted_at | 現在日時 | ソフトデリート |
| DELETE | - | id = params[:id] | ハードデリート |

#### account_contacts

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | - | account_id = @account.id | dependent: :destroy |

#### account_opportunities

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | - | account_id = @account.id | dependent: :destroy |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | 認証エラー | 未ログイン状態でアクセス | ログイン画面へリダイレクト |
| 403 | 認可エラー | 削除権限がない | エラーメッセージ表示 |
| 404 | 未検出 | 指定IDの取引先が存在しない | 一覧画面へリダイレクト |

### リトライ仕様

本機能ではリトライ処理は実装されていない。

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

取引先と関連データの削除はActiveRecordのトランザクション内で実行される。いずれかが失敗した場合はロールバック。

## パフォーマンス要件

- 削除処理時間: 2秒以内を目標
- 関連データが多い場合は処理時間が増加する可能性あり

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

- 認証: Deviseによるユーザー認証が必須
- 認可: CanCanによるアクセス権限制御
- CSRF: protect_from_forgeryによる対策
- 監査ログ: PaperTrailによる削除履歴

## 備考

- 削除前にUIで確認ダイアログを表示（JavaScript）
- 削除は取り消し不可（論理削除の場合は復元可能）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | account.rb | `app/models/entities/account.rb` | dependent: :destroy設定 |
| 1-2 | account_contact.rb | `app/models/entities/account_contact.rb` | 紐付きモデル |
| 1-3 | account_opportunity.rb | `app/models/entities/account_opportunity.rb` | 紐付きモデル |

**読解のコツ**: has_many関連のdependent: :destroy（33, 35, 38行目）で連鎖削除を確認。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | routes.rb | `config/routes.rb` | DELETE /accounts/:id ルート |
| 2-2 | accounts_controller.rb | `app/controllers/entities/accounts_controller.rb` | destroyアクション |

**主要処理フロー**:
1. **80-87行目**: destroyアクション
2. **81行目**: @account.destroy
3. **83-86行目**: respond_withによるフォーマット分岐

#### Step 3: レスポンス処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | accounts_controller.rb | `app/controllers/entities/accounts_controller.rb` | respond_to_destroyメソッド |

**主要処理フロー**:
- **136-150行目**: respond_to_destroy
- **137-144行目**: AJAX時の処理
- **145-149行目**: HTML時の処理

#### Step 4: ビュー層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | destroy.js.haml | `app/views/accounts/destroy.js.haml` | 削除結果JS |

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

```
AccountsController#destroy
    │
    ├─ load_and_authorize_resource (Account.find)
    │
    ├─ @account.destroy
    │   └─ dependent: :destroy
    │       ├─ account_contacts.destroy_all
    │       ├─ account_opportunities.destroy_all
    │       ├─ tasks.destroy_all
    │       └─ addresses.destroy_all
    │
    └─ respond_with(@account)
           │
           ├─ 【HTML】respond_to_destroy(:html)
           │   ├─ self.current_page = 1
           │   ├─ flash[:notice] = t(:msg_asset_deleted)
           │   └─ redirect_to accounts_path
           │
           └─ 【AJAX】respond_to_destroy(:ajax)
               ├─ get_accounts
               ├─ get_data_for_sidebar
               ├─ 【一覧空】get_accounts(page: current_page - 1)
               │   └─ render(:index)
               └─ 【一覧あり】render destroy.js.haml
```

### データフロー図

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

URLパラメータ ───▶ AccountsController#destroy ───▶ @account
(id)                   │                          @accounts (AJAX)
                       │                              │
                       ├─ 認可チェック               │
                       ├─ destroy実行                │
                       │                              │
                       ▼                              ▼
               データベース                    destroy.js.haml
               (accounts DELETE,              または
                account_contacts DELETE,      redirect_to accounts_path
                account_opportunities DELETE,
                tasks DELETE,
                addresses DELETE,
                versions INSERT)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| accounts_controller.rb | `app/controllers/entities/accounts_controller.rb` | ソース | メインコントローラー |
| account.rb | `app/models/entities/account.rb` | ソース | 取引先モデル |
| account_contact.rb | `app/models/entities/account_contact.rb` | ソース | 紐付きモデル |
| account_opportunity.rb | `app/models/entities/account_opportunity.rb` | ソース | 紐付きモデル |
| destroy.js.haml | `app/views/accounts/destroy.js.haml` | テンプレート | 削除結果JS |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義 |
