# 機能設計書 60-会話履歴表示

## 概要

本ドキュメントは、Chatwootにおける連絡先の会話履歴表示機能について記述する。本機能は、特定の連絡先が過去に行った全ての会話を一覧表示し、顧客対応の履歴を確認できる機能である。

### 本機能の処理概要

**業務上の目的・背景**：カスタマーサポートにおいて、顧客との過去のやり取りを把握することは、質の高いサポートを提供する上で重要である。同じ顧客が複数回問い合わせを行う場合、過去の対応履歴を参照することで、重複した説明を避け、より効率的でパーソナライズされた対応が可能となる。

**機能の利用シーン**：
- 連絡先詳細画面から過去の会話履歴を確認する
- 過去の対応内容を参照して現在の問い合わせに対応する
- 顧客との関係性を把握する
- 問題の再発パターンを確認する
- VIP顧客の対応履歴を確認する

**主要な処理内容**：
1. 連絡先IDに紐づく会話の取得
2. 権限に基づく会話のフィルタリング
3. 最終アクティビティ順での会話ソート
4. 関連情報（担当者、インボックス、ラベル）の取得
5. 最大20件の会話を返却

**関連システム・外部連携**：なし（内部機能のみ）。

**権限による制御**：会話履歴の閲覧はエージェント権限以上が必要。また、ユーザーの権限に応じて閲覧可能な会話がフィルタリングされる（インボックス権限等）。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 24 | 連絡先編集画面 | 主画面 | 会話履歴の表示 |

## 機能種別

データ取得 / 一覧表示

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| contact_id | Integer | Yes | 連絡先ID（URLパラメータ） | 存在する連絡先 |

### 入力データソース

- 連絡先詳細画面からのリクエスト
- APIリクエスト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| conversations | Array | 会話の配列（最大20件） |
| conversations[].id | Integer | 会話ID |
| conversations[].display_id | Integer | 表示用会話ID |
| conversations[].status | String | 会話ステータス |
| conversations[].last_activity_at | DateTime | 最終アクティビティ日時 |
| conversations[].assignee | Object | 担当者情報 |
| conversations[].inbox | Object | インボックス情報 |
| conversations[].labels | Array | ラベル一覧 |

### 出力先

- API レスポンス

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ contact_idを取得
2. 連絡先取得
   └─ BaseControllerでcontactを取得
3. 会話取得
   └─ account.conversations.where(contact_id: contact.id)
4. 権限フィルタリング
   └─ PermissionFilterServiceで閲覧可能な会話のみ抽出
5. ソート・制限
   └─ last_activity_at降順でソート、20件に制限
6. 関連データ取得
   └─ assignee, contact, inbox, taggingsをincludes
7. レスポンス返却
```

### フローチャート

```mermaid
flowchart TD
    A[会話履歴リクエスト] --> B[連絡先取得]
    B --> C{連絡先存在?}
    C -->|No| Z1[404 Not Found]
    C -->|Yes| D[会話クエリ構築]
    D --> E[PermissionFilterService]
    E --> F[last_activity_at降順ソート]
    F --> G[20件制限]
    G --> H[関連データincludes]
    H --> I[レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-60-01 | 権限フィルタ | ユーザーのインボックス権限に基づいて閲覧可能な会話のみ表示 | 常時 |
| BR-60-02 | ソート順序 | 最終アクティビティ日時の降順でソート | 常時 |
| BR-60-03 | 件数制限 | 最大20件まで取得 | 常時 |
| BR-60-04 | 関連データ | assignee, contact, inbox, taggingsを含めて取得 | 常時 |

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 会話取得 | conversations | SELECT | 連絡先の会話を取得 |
| 関連データ取得 | users, contacts, inboxes, taggings | SELECT | 関連データをプリロード |

### 使用インデックス

| インデックス名 | 用途 |
|---------------|------|
| index_conversations_on_contact_id | 連絡先IDによる会話検索 |
| index_conversations_on_last_activity_at | アクティビティ順ソート |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 404 | 存在しないリソース | 指定IDの連絡先が存在しない | 404 Not Foundを返却 |
| 403 | 権限エラー | 連絡先へのアクセス権限がない | 403 Forbiddenを返却 |

### リトライ仕様

なし（同期処理）

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

読み取り専用のためトランザクション管理は不要。

## パフォーマンス要件

- includesによるN+1問題の回避
- インデックスによる効率的なクエリ
- 20件制限による大量データの回避
- 通常100ms以内でレスポンス

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

- PermissionFilterServiceによる権限に基づくフィルタリングが必須
- アカウント単位でのスコープ制限
- 連絡先が属するインボックスへのアクセス権限チェック

## 備考

- Conversations::PermissionFilterServiceを使用して権限フィルタリングを実行
- 会話のステータス（open, resolved, pending等）に関わらず全ての会話を表示

---

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

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

### 推奨読解順序

#### Step 1: コントローラーのindexアクションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | conversations_controller.rb | `app/controllers/api/v1/accounts/contacts/conversations_controller.rb` | 会話履歴取得のエンドポイント |

**主要処理フロー**:
- **2-6行目**: indexアクションで連絡先の会話を取得
- **4行目**: includesで関連データをプリロード
- **6行目**: where(contact_id: @contact.id)で連絡先でフィルタ
- **9-13行目**: PermissionFilterServiceで権限フィルタリング
- **15行目**: order(last_activity_at: :desc).limit(20)でソートと制限

**読解のコツ**: BaseControllerで`@contact`が事前にセットされる。PermissionFilterServiceは会話へのアクセス権限をチェックするサービス。

#### Step 2: 権限フィルタサービスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | permission_filter_service.rb | `app/services/conversations/permission_filter_service.rb` | 会話の権限フィルタリング |

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

```
Api::V1::Accounts::Contacts::ConversationsController#index
    │
    ├─ @contact (BaseControllerでセット)
    │
    ├─ Current.account.conversations
    │      └─ includes(:assignee, :contact, :inbox, :taggings)
    │             └─ where(contact_id: @contact.id)
    │
    └─ Conversations::PermissionFilterService#perform
           └─ 権限に基づくフィルタリング
                  └─ order(last_activity_at: :desc).limit(20)
```

### データフロー図

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

contact_id         ConversationsController      conversations
(URLパラメータ) ───▶ 会話取得               ───▶  (最大20件)
                   権限フィルタリング              │
                   ソート・制限                    ▼
                                            JSON レスポンス
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| conversations_controller.rb | `app/controllers/api/v1/accounts/contacts/conversations_controller.rb` | コントローラー | 会話履歴取得エンドポイント |
| permission_filter_service.rb | `app/services/conversations/permission_filter_service.rb` | サービス | 権限フィルタリング |
| base_controller.rb | `app/controllers/api/v1/accounts/contacts/base_controller.rb` | ベースコントローラー | @contactのセット |
