# 機能設計書 42-SLAポリシー適用

## 概要

本ドキュメントは、Chatwootにおける会話へのSLAポリシー適用と応答時間・解決時間の追跡機能の設計を記述します。本機能はEnterprise版の機能です。

### 本機能の処理概要

SLA（Service Level Agreement）ポリシーを会話に適用し、初回応答時間、次回応答時間、解決時間の閾値を設定・監視する機能を提供します。SLAポリシー違反時には自動的にアラートが発生し、サービス品質の維持に貢献します。

**業務上の目的・背景**：カスタマーサポートにおいて、応答時間と解決時間はサービス品質の重要な指標です。SLAポリシーを設定し自動監視することで、顧客への迅速な対応を保証し、サービスレベルの可視化と改善を実現します。特に大規模なサポートチームや契約ベースのサービスでは、SLA遵守が業務要件となることが多くあります。

**機能の利用シーン**：
- 新規会話にSLAポリシーを自動または手動で適用する場面
- エージェントが会話のSLA状況（残り時間、違反状態）を確認する場面
- 管理者がSLA達成率をレポートで確認・分析する場面
- SLA違反時にメール通知を受け取る場面

**主要な処理内容**：
1. SLAポリシーの作成・編集・削除
2. 会話へのSLAポリシー適用とAppliedSlaレコード作成
3. 定期的なSLA閾値チェックとSlaEvent記録
4. SLA違反時のメール通知送信
5. SLA達成状況のレポート生成

**関連システム・外部連携**：
- オートメーションルール：特定条件で自動的にSLAポリシーを適用
- メール通知システム：SLA違反時のアラート配信
- レポートシステム：SLA達成率の集計・分析

**権限による制御**：SLAポリシーの作成・編集は管理者権限が必要です。SLA状況の参照はエージェント以上で可能です。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 11 | 会話詳細画面 | 主画面 | SLA状況の表示、残り時間の確認 |
| 42 | SLAレポート画面 | 主画面 | SLAに関するレポート表示 |
| 75 | SLA一覧画面 | 設定画面 | SLAポリシーの一覧表示・管理 |

## 機能種別

データ管理 / バリデーション / 計算処理 / 通知

## 入力仕様

### 入力パラメータ（SLAポリシー作成）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | String | Yes | SLAポリシー名 | 必須 |
| description | String | No | SLAポリシーの説明 | - |
| first_response_time_threshold | Float | No | 初回応答時間閾値（秒） | 正の数値 |
| next_response_time_threshold | Float | No | 次回応答時間閾値（秒） | 正の数値 |
| resolution_time_threshold | Float | No | 解決時間閾値（秒） | 正の数値 |
| only_during_business_hours | Boolean | No | 営業時間のみ計算するか | デフォルト: false |

### 入力パラメータ（会話へのSLA適用）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| sla_policy_id | BigInt | Yes | 適用するSLAポリシーのID | 存在するSLAポリシーID |

### 入力データソース

- 画面入力：SLA一覧画面でのポリシー作成フォーム
- オートメーションルール：条件に基づく自動適用
- API：`POST /api/v1/accounts/{account_id}/sla_policies`

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| sla_policy | Object | SLAポリシー情報 |
| applied_sla | Object | 会話に適用されたSLA情報 |
| sla_status | Enum | SLA状態（active/hit/missed/active_with_misses） |
| sla_events | Array | SLAイベント（FRT/NRT/RT違反など） |

### 出力先

- API レスポンス：JSON形式でSLA情報を返却
- データベース：sla_policies, applied_slas, sla_eventsテーブル
- WebSocket：SLA状態変更時のCONVERSATION_UPDATEDイベント
- メール通知：SLA違反時のアラートメール

## 処理フロー

### 処理シーケンス

```
1. SLAポリシー適用
   └─ 会話にsla_policy_idを設定
2. AppliedSlaレコード作成
   └─ around_saveコールバックでトランザクション内で作成
3. 定期的なSLA評価（バッチ処理）
   └─ Sla::EvaluateAppliedSlaServiceが各閾値をチェック
4. 閾値違反時
   └─ SlaEventを作成し、sla_statusを更新
5. 会話解決時
   └─ 最終的なSLA達成/未達成を判定
6. 通知・イベント
   └─ SLA状態変更をWebSocketで通知
```

### フローチャート

```mermaid
flowchart TD
    A[会話にSLAポリシー適用] --> B{validate_sla_policy}
    B -->|失敗| C[エラー: ポリシー適用不可]
    B -->|成功| D[会話保存]
    D --> E[AppliedSla作成]
    E --> F[定期バッチ処理]
    F --> G{FRT閾値チェック}
    G -->|違反| H[SlaEvent作成 frt]
    G -->|OK| I{NRT閾値チェック}
    H --> I
    I -->|違反| J[SlaEvent作成 nrt]
    I -->|OK| K{RT閾値チェック}
    J --> K
    K -->|違反| L[SlaEvent作成 rt]
    K -->|OK| M{会話解決済み?}
    L --> M
    M -->|Yes| N{active_with_misses?}
    M -->|No| O[次回評価まで待機]
    N -->|Yes| P[sla_status = missed]
    N -->|No| Q[sla_status = hit]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-42-001 | 単一SLA適用 | 会話には1つのSLAポリシーのみ適用可能 | 既にSLAが適用されている会話への再適用時 |
| BR-42-002 | SLA削除不可 | 適用済みのSLAポリシーは会話から削除できない | sla_policy_idをnullに変更しようとした場合 |
| BR-42-003 | FRT判定 | 初回応答は会話作成時刻からの経過時間で判定 | first_response_time_thresholdが設定されている場合 |
| BR-42-004 | NRT判定 | 次回応答はwaiting_sinceからの経過時間で判定 | next_response_time_thresholdが設定されかつfirst_replyが存在する場合 |
| BR-42-005 | RT判定 | 解決時間は会話作成時刻から解決までの時間で判定 | resolution_time_thresholdが設定されている場合 |
| BR-42-006 | 重複イベント防止 | 同一閾値の違反イベントは1度のみ記録 | already_missed?チェック |

### 計算ロジック

**初回応答時間（FRT）閾値**:
```
threshold = conversation.created_at + sla_policy.first_response_time_threshold
違反条件 = first_reply_created_at.blank? AND Time.now > threshold
```

**次回応答時間（NRT）閾値**:
```
threshold = conversation.waiting_since + sla_policy.next_response_time_threshold
違反条件 = waiting_since.present? AND Time.now > threshold
```

**解決時間（RT）閾値**:
```
threshold = conversation.created_at + sla_policy.resolution_time_threshold
違反条件 = !conversation.resolved? AND Time.now > threshold
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| SLAポリシー作成 | sla_policies | INSERT | SLAポリシーの新規作成 |
| SLA適用 | conversations | UPDATE | sla_policy_idの設定 |
| SLA適用 | applied_slas | INSERT | 適用SLAレコードの作成 |
| SLA違反記録 | sla_events | INSERT | 違反イベントの記録 |
| SLA状態更新 | applied_slas | UPDATE | sla_statusの更新 |

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

#### sla_policies

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name | ポリシー名 | 必須 |
| INSERT | first_response_time_threshold | 秒単位の閾値 | Float型 |
| INSERT | next_response_time_threshold | 秒単位の閾値 | Float型 |
| INSERT | resolution_time_threshold | 秒単位の閾値 | Float型 |
| INSERT | only_during_business_hours | 営業時間フラグ | Boolean |

#### applied_slas

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | conversation_id | 会話ID | - |
| INSERT | sla_policy_id | SLAポリシーID | - |
| INSERT | sla_status | active | 初期値 |
| UPDATE | sla_status | hit/missed/active_with_misses | 評価結果 |

#### sla_events

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | event_type | frt/nrt/rt | 違反タイプ |
| INSERT | meta | {message_id: ...} | NRTの場合 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 422 | バリデーションエラー | 既に別のSLAが適用されている | 新規会話を作成するか、既存SLAを利用 |
| 422 | バリデーションエラー | SLAポリシーの削除を試みた | SLAポリシーは削除不可 |
| 422 | バリデーションエラー | アカウントIDの不一致 | 同一アカウント内のSLAポリシーを使用 |

### リトライ仕様

定期バッチ処理による評価は継続的に実行されるため、一時的な失敗は次回評価で自動的にリトライされます。

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

会話へのSLAポリシー適用時は、`around_save`コールバック内のトランザクションで以下を一括処理：
1. 会話のsla_policy_id更新
2. AppliedSlaレコードの作成

いずれかが失敗した場合は全体がロールバックされます。

## パフォーマンス要件

- SLA評価バッチは定期実行（数分間隔）
- applied_slasテーブルには複合インデックス（account_id, sla_policy_id, conversation_id）
- 大量の会話に対する評価はジョブキューで非同期処理

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

- SLAポリシーの作成・編集は管理者権限が必要
- アカウント境界を超えたSLAポリシー参照は不可
- EnterpriseAccountsControllerで権限チェックを実施

## 備考

- 本機能はEnterprise版のみで利用可能です
- only_during_business_hours機能は営業時間外の経過時間を除外して計算します
- SLA違反時のメール通知はconversation_notifications_mailerで送信されます

---

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

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

### 推奨読解順序

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

まず、SLAに関連するモデルの構造を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sla_policy.rb | `enterprise/app/models/sla_policy.rb` | SLAポリシーのスキーマ定義（1-19行目）、push_event_data（27-35行目） |
| 1-2 | applied_sla.rb | `enterprise/app/models/applied_sla.rb` | 適用SLAのスキーマ（1-19行目）、sla_status enum（30行目） |
| 1-3 | sla_event.rb | `enterprise/app/models/sla_event.rb` | SLAイベントの記録構造 |

**読解のコツ**: SlaPolicy -> AppliedSla -> SlaEventの関係を理解することが重要です。1つの会話に対して1つのAppliedSlaが作成され、違反が発生するたびにSlaEventが追加されます。

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

SLAポリシーの適用処理とAPIを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sla_policies_controller.rb | `enterprise/app/controllers/api/v1/accounts/sla_policies_controller.rb` | CRUD操作（1-32行目） |
| 2-2 | conversation.rb (Enterprise) | `enterprise/app/models/enterprise/concerns/conversation.rb` | SLAポリシー関連のconcern（1-39行目） |

**主要処理フロー**:
1. **9-10行目** (concerns/conversation.rb): before_validationでvalidate_sla_policyを呼び出し
2. **10行目**: around_saveでensure_applied_sla_is_createdを実行
3. **31-38行目**: トランザクション内でAppliedSlaを作成

#### Step 3: SLA評価処理を理解する

定期的に実行されるSLA評価ロジックを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | evaluate_applied_sla_service.rb | `enterprise/app/services/sla/evaluate_applied_sla_service.rb` | SLA評価の核心ロジック |

**主要処理フロー**:
- **4-12行目**: performメソッドで閾値チェックを実行
- **16-21行目**: check_sla_thresholdsで3種類の閾値を順にチェック
- **28-33行目**: check_first_response_time_thresholdでFRT判定
- **40-49行目**: check_next_response_time_thresholdでNRT判定
- **61-68行目**: check_resolution_time_thresholdでRT判定
- **70-80行目**: handle_missed_slaでSlaEvent作成とステータス更新

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

```
Conversation#save (sla_policy_id変更時)
    │
    ├─ validate_sla_policy
    │      └─ バリデーション（重複・削除・アカウント不一致チェック）
    │
    └─ ensure_applied_sla_is_created (around_save)
           │
           └─ AppliedSla.create!
                  └─ ensure_account_id (before_validation)

定期バッチ (Sla::ProcessAccountAppliedSlasJob)
    │
    └─ Sla::EvaluateAppliedSlaService#perform
           │
           ├─ check_first_response_time_threshold
           │      └─ handle_missed_sla ('frt')
           │
           ├─ check_next_response_time_threshold
           │      └─ handle_missed_sla ('nrt')
           │
           ├─ check_resolution_time_threshold
           │      └─ handle_missed_sla ('rt')
           │
           └─ handle_hit_sla (会話解決時)
```

### データフロー図

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

sla_policy_id       ───▶ Conversation#save              ───▶ DB (conversations.sla_policy_id)
                              │
                              │
                              └─▶ ensure_applied_sla   ───▶ DB (applied_slas)
                                       │
                                       │
                    ┌──────────────────┘
                    │
                    ▼
             定期バッチ処理
                    │
                    ├─▶ check_thresholds               ───▶ DB (sla_events)
                    │
                    └─▶ update_sla_status              ───▶ DB (applied_slas.sla_status)
                              │
                              │
                              └──────────────────────────▶ WebSocket (CONVERSATION_UPDATED)
                              │
                              └──────────────────────────▶ Email (SLA違反通知)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sla_policy.rb | `enterprise/app/models/sla_policy.rb` | モデル | SLAポリシー定義 |
| applied_sla.rb | `enterprise/app/models/applied_sla.rb` | モデル | 適用SLA管理 |
| sla_event.rb | `enterprise/app/models/sla_event.rb` | モデル | SLAイベント記録 |
| sla_policies_controller.rb | `enterprise/app/controllers/api/v1/accounts/sla_policies_controller.rb` | コントローラー | SLAポリシーAPI |
| concerns/conversation.rb | `enterprise/app/models/enterprise/concerns/conversation.rb` | モデル拡張 | 会話モデルへのSLA機能追加 |
| evaluate_applied_sla_service.rb | `enterprise/app/services/sla/evaluate_applied_sla_service.rb` | サービス | SLA評価ロジック |
| conversation_notifications_mailer.rb | `enterprise/app/mailers/enterprise/agent_notifications/conversation_notifications_mailer.rb` | メーラー | SLA違反通知 |
| sla_activity_message_handler.rb | `app/models/concerns/sla_activity_message_handler.rb` | モデル拡張 | SLA活動メッセージ |
