# 機能設計書 65-ブロック機能

## 概要

本ドキュメントは、Chatwootにおける連絡先（Contact）のブロック機能の設計を記述する。スパムや悪質な連絡先からのメッセージを遮断するためのブロック/アンブロック機能を提供する。

### 本機能の処理概要

連絡先ブロック機能は、特定の連絡先をブロックして、その連絡先からの新規会話開始やメッセージ受信を制限する機能を提供する。blockedフラグをtrueに設定することで、当該連絡先を無効化する。

**業務上の目的・背景**：カスタマーサポート業務において、スパム送信者や悪質なユーザーからの接触を遮断することは、エージェントの業務効率とシステムの健全性を維持するために重要である。ブロック機能により、不要な通知やメッセージの受信を防ぎ、正規の顧客対応に集中できる環境を提供する。

**機能の利用シーン**：
- スパムメッセージを送信する連絡先をブロックする場合
- 悪質なクレーマーからの接触を遮断したい場合
- 誤ってブロックした連絡先を解除する場合
- ブロック状態の連絡先を一覧で確認する場合

**主要な処理内容**：
1. 連絡先のブロック状態設定（blocked = true）
2. 連絡先のブロック解除（blocked = false）
3. ブロック状態の表示
4. ブロックされた連絡先のフィルタリング

**関連システム・外部連携**：
- 通知システム：ブロックされた連絡先からのイベントは通知されない
- メッセージ受信：ブロックされた連絡先からのメッセージは受信制限される可能性

**権限による制御**：連絡先へのアクセス権限を持つエージェントのみがブロック操作が可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 24 | 連絡先編集画面 | 主画面 | ブロック/アンブロック操作 |
| 20 | 連絡先一覧画面 | 参照画面 | ブロック状態の表示 |

## 機能種別

CRUD操作（Update）/ バリデーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | Integer | Yes | 対象連絡先ID | URLパラメータ、存在確認 |
| blocked | Boolean | No | ブロック状態 | true/false |

### 入力データソース

- 画面入力：連絡先編集画面からのトグル操作
- APIパラメータ：blocked フラグ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| blocked | Boolean | ブロック状態 |

### 出力先

- API レスポンス（JSON形式）
- フロントエンド各画面

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ PATCH /api/v1/accounts/:account_id/contacts/:id

2. 認証・認可チェック
   └─ BaseController で認証確認
   └─ 連絡先の存在確認と所属確認

3. ブロック状態更新
   └─ permitted_params に :blocked を含める
   └─ contact.update!(blocked: params[:blocked])

4. イベント発行
   └─ after_update_commit で dispatch_update_event
   └─ CONTACT_UPDATED イベントをブロードキャスト

5. レスポンス生成
   └─ 更新後の連絡先情報を返却
```

### フローチャート

```mermaid
flowchart TD
    A[更新リクエスト受信] --> B{認証済み?}
    B -->|No| C[401 Unauthorized]
    B -->|Yes| D{連絡先存在?}
    D -->|No| E[404 Not Found]
    D -->|Yes| F[blockedパラメータ取得]
    F --> G[contact.update!]
    G --> H[dispatch_update_event]
    H --> I[CONTACT_UPDATEDイベント]
    I --> J[JSONレスポンス]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | デフォルト非ブロック | 新規連絡先作成時のデフォルトはblocked = false | 連絡先作成時 |
| BR-02 | オンライン削除禁止 | オンライン状態の連絡先は削除できない（ブロックは可能） | 削除時 |
| BR-03 | ブロック状態通知 | ブロック状態の変更はCONTACT_UPDATEDイベントでブロードキャスト | 更新時 |
| BR-04 | インデックス | blockedカラムにインデックスが設定されている | データベース |

### 計算ロジック

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

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ブロック | contacts | UPDATE | blocked カラムを更新 |

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

#### contacts

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | blocked | true/false | NOT NULL, デフォルト false |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | Unauthorized | 認証トークンが無効または期限切れ | 再認証を促す |
| 404 | Not Found | 連絡先が存在しない | 正しいIDを指定 |

### リトライ仕様

特にリトライ仕様はなし。

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

- update! による暗黙的なトランザクション管理
- 失敗時は例外発生によりロールバック

## パフォーマンス要件

- blocked カラムにインデックスが設定されており、フィルタリング時のパフォーマンスを確保

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

- アカウント単位でのアクセス制御
- Strong Parameters による入力パラメータの制限

## 備考

- blocked はスキーマ定義でデフォルト false、NOT NULL 制約あり
- push_event_data, webhook_data にブロック状態が含まれる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | contact.rb | `app/models/contact.rb` | blocked カラムの定義とスキーマ |

**読解のコツ**: ファイル冒頭のSchema Informationコメントで、blockedカラムの定義を確認する。

**主要処理フロー**:
- **9行目（スキーマ）**: `blocked :boolean default(FALSE), not null` - ブロックフラグ定義
- **32行目（インデックス）**: `index_contacts_on_blocked (blocked)` - ブロックフィルタリング用インデックス
- **150-163行目**: `push_event_data` - blocked を含むイベントデータ
- **165-179行目**: `webhook_data` - blocked を含むWebhookデータ
- **239-241行目**: `dispatch_update_event` - 更新時のイベント発行

#### Step 2: コントローラーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | contacts_controller.rb | `app/controllers/api/v1/accounts/contacts_controller.rb` | updateアクションとpermitted_params |

**主要処理フロー**:
- **94-98行目**: `update` アクション - assign_attributes と save!
- **174行目**: `permitted_params` - :blocked を許可パラメータに含む
- **100-110行目**: `destroy` アクション - オンラインチェック（ブロックとは別の制限）

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

```
Api::V1::Accounts::ContactsController#update
    │
    ├─ contact.assign_attributes(blocked: ...)
    │
    ├─ contact.save!
    │      │
    │      └─ after_update_commit :dispatch_update_event
    │              │
    │              └─ Rails.configuration.dispatcher.dispatch(CONTACT_UPDATED, ...)
    │                      │
    │                      └─ changed_attributes: previous_changes (blockedを含む)
    │
    └─ render contact (JBuilder)
           │
           └─ blocked: contact.blocked
```

### データフロー図

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

blocked (Boolean) ───▶ contact.assign_attributes ────▶ contacts テーブル
 (PATCH body)                  │                        (UPDATE blocked)
                               │
                        contact.save!
                               │
                        after_update_commit
                               │
                        dispatch_update_event
                               │
                               ▼
                        CONTACT_UPDATED イベント ────▶ WebSocket / Webhook
                               │
                               ▼
                        JSON レスポンス
                        (blocked: true/false)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| contact.rb | `app/models/contact.rb` | モデル | blockedカラム定義、イベント発行 |
| contacts_controller.rb | `app/controllers/api/v1/accounts/contacts_controller.rb` | コントローラー | updateアクション、permitted_params |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義 |
| _contact.json.jbuilder | `app/views/api/v1/models/_contact.json.jbuilder` | ビュー | JSON出力（blockedを含む） |
