# バッチ設計書 24-Sla::ProcessAppliedSlaJob

## 概要

本ドキュメントは、Chatwootシステム（Enterprise版）における個別SLA評価ジョブ（Sla::ProcessAppliedSlaJob）の設計仕様を記載したものである。

### 本バッチの処理概要

本バッチは、個別の適用SLA（applied_sla）に対して、SLA閾値の違反チェックおよびステータス更新を実行する処理を行う。

**業務上の目的・背景**：SLA（Service Level Agreement）の遵守状況を継続的に監視することは、カスタマーサポートの品質管理において極めて重要である。本バッチは、各会話に適用されたSLAポリシーの3つの閾値（初回応答時間FRT、次回応答時間NRT、解決時間RT）を評価し、違反が発生した場合にはSLAイベントを作成して関係者に通知する。また、会話が解決された際にはSLAの最終結果（達成/未達成）を判定してステータスを更新する。これにより、サポートマネージャーはSLA遵守率を正確に把握し、チームのパフォーマンス改善に活用できる。

**バッチの実行タイミング**：Sla::ProcessAccountAppliedSlasJob（No.23）から呼び出される。親ジョブの実行に伴い、5分毎に該当するSLAが評価される。

**主要な処理内容**：
1. 引数として渡されたapplied_slaオブジェクトを受け取る
2. Sla::EvaluateAppliedSlaServiceを呼び出し
3. 3つのSLA閾値（FRT、NRT、RT）をチェック
4. 閾値違反時はSLAイベントを作成し通知を送信
5. 会話解決時はSLAの最終結果（hit/missed）を判定

**前後の処理との関連**：本バッチはSla::ProcessAccountAppliedSlasJob（No.23）から呼び出される子ジョブである。3階層のジョブ構造（TriggerSlasForAccountsJob → ProcessAccountAppliedSlasJob → ProcessAppliedSlaJob）の最下層に位置し、実際のSLA評価ロジックを実行する。

**影響範囲**：applied_slasテーブルのsla_status更新、sla_eventsテーブルへのイベント作成、notificationsテーブルへの通知作成、WebSocket経由のリアルタイム更新

## バッチ種別

データ処理 / SLA評価・通知

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 5分毎（親ジョブ経由） |
| 実行時刻 | ProcessAccountAppliedSlasJobからのキューイング後 |
| 実行曜日 | 毎日 |
| 実行日 | 毎日 |
| トリガー | Sla::ProcessAccountAppliedSlasJob.perform_later |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| エディション | Enterprise版であること |
| applied_sla | 有効なAppliedSlaオブジェクトが渡されること |
| sla_policy | applied_slaに関連付けられたSLAポリシーが存在すること |
| conversation | applied_slaに関連付けられた会話が存在すること |

### 実行可否判定

本ジョブは呼び出された時点で必ず実行される。親ジョブでactive/active_with_missesステータスのフィルタリングが行われている。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| applied_sla | AppliedSla | Yes | - | 評価対象の適用SLAオブジェクト |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| applied_slas | DB | 適用済みSLA情報 |
| sla_policies | DB | SLAポリシー（閾値設定） |
| conversations | DB | 会話情報（作成日時、初回返信日時等） |
| messages | DB | メッセージ情報（NRT計算用） |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| applied_slas | DB | sla_statusの更新 |
| sla_events | DB | SLA違反イベントの作成 |
| notifications | DB | SLA違反通知の作成 |
| WebSocket | Push | 会話更新イベントの配信 |

### 出力ファイル仕様

ファイル出力なし

## 処理フロー

### 処理シーケンス

```
1. performメソッド実行
   └─ applied_slaオブジェクトを引数として受け取り

2. EvaluateAppliedSlaService.perform呼び出し
   └─ SLA評価サービスを初期化して実行

3. check_sla_thresholds（3閾値のチェック）
   ├─ check_first_response_time_threshold (FRT)
   │   └─ 会話作成時刻 + FRT閾値 を超過していないか確認
   ├─ check_next_response_time_threshold (NRT)
   │   └─ 最後の顧客メッセージ + NRT閾値 を超過していないか確認
   └─ check_resolution_time_threshold (RT)
       └─ 会話作成時刻 + RT閾値 を超過していないか確認

4. 閾値違反時の処理
   ├─ handle_missed_sla呼び出し
   ├─ SlaEvent作成（重複チェック付き）
   ├─ applied_sla.sla_status を active_with_misses に更新
   └─ 関係者への通知送信

5. 会話解決時の最終判定
   ├─ activeの場合: sla_status を hit に更新
   └─ active_with_missesの場合: sla_status を missed に更新
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[EvaluateAppliedSlaService.perform]
    B --> C[check_sla_thresholds]
    C --> D{FRT閾値設定あり?}
    D -->|Yes| E[FRTチェック]
    D -->|No| F{NRT閾値設定あり?}
    E --> F
    F -->|Yes| G[NRTチェック]
    F -->|No| H{RT閾値設定あり?}
    G --> H
    H -->|Yes| I[RTチェック]
    H -->|No| J{会話解決済み?}
    I --> J
    J -->|No| Z[バッチ終了]
    J -->|Yes| K{現在のステータス}
    K -->|active| L[sla_status = hit]
    K -->|active_with_misses| M[sla_status = missed]
    L --> Z
    M --> Z
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| SLAポリシー取得 | sla_policies | SELECT | 閾値設定の取得 |
| 会話情報取得 | conversations | SELECT | 作成日時、初回返信日時等の取得 |
| メッセージ取得 | messages | SELECT | 最後の顧客メッセージ取得（NRT用） |
| 重複チェック | sla_events | SELECT | 同一違反イベントの存在確認 |
| イベント作成 | sla_events | INSERT | SLA違反イベントの記録 |
| ステータス更新 | applied_slas | UPDATE | sla_statusの更新 |
| 通知作成 | notifications | INSERT | SLA違反通知の作成 |

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

#### applied_slas

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | sla_status | active_with_misses (3) | 違反検出時 |
| UPDATE | sla_status | hit (1) | 会話解決・SLA達成時 |
| UPDATE | sla_status | missed (2) | 会話解決・SLA未達成時 |
| UPDATE | updated_at | 現在時刻 | 自動更新 |

#### sla_events

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | event_type | frt (0) / nrt (1) / rt (2) | 違反種別 |
| INSERT | meta | { message_id: xxx } | NRT違反時のみ |
| INSERT | applied_sla_id | 対象SLAのID | |
| INSERT | conversation_id | 対象会話のID | |
| INSERT | account_id | アカウントID | |
| INSERT | inbox_id | インボックスID | |
| INSERT | sla_policy_id | SLAポリシーID | |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | NoMethodError | applied_slaがnilの場合 | Sidekiqリトライ |
| - | ActiveRecord::RecordNotFound | 関連レコード削除済み | ログ出力、処理スキップ |
| - | ActiveRecord::RecordInvalid | イベント/通知作成失敗 | Sidekiqリトライ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Sidekiqデフォルト設定に依存 |
| リトライ間隔 | Sidekiqデフォルト設定に依存 |
| リトライ対象エラー | 一時的なエラー全般 |

### 障害時対応

- 5分毎に再評価されるため、一時的な障害は次回実行で回復
- 重複イベント作成は already_missed? チェックで防止
- 永続的なエラーの場合はSidekiqダッシュボードで確認・対処

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | 各更新操作は個別トランザクション |
| コミットタイミング | 各操作完了時 |
| ロールバック条件 | 各操作の失敗時に個別ロールバック |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 1件のapplied_sla |
| 目標処理時間 | 数秒以内 |
| メモリ使用量上限 | 特に制限なし |

## 排他制御

- SlaEvent作成時に already_missed? で重複チェック
- 同一イベントタイプ・メタデータの組み合わせで既存レコードがある場合はスキップ

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 警告ログ | SLA違反検出時 | SLA {type} missed for conversation {id} in account {id} for sla_policy {id} |
| 情報ログ | SLA達成時 | SLA hit for conversation {id} in account {id} for sla_policy {id} |
| 情報ログ | SLA未達成確定時 | SLA missed for conversation {id} in account {id} for sla_policy {id} |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| ジョブ実行エラー | 発生時 | Sidekiq監視 |
| SLA違反率 | 設定閾値超過時 | 運用担当 |

## 備考

- Enterprise版専用機能
- キューはmediumを使用（優先度中）
- SLA閾値の種類：
  - first_response_time_threshold (FRT): 初回応答時間閾値
  - next_response_time_threshold (NRT): 次回応答時間閾値（顧客メッセージ後）
  - resolution_time_threshold (RT): 解決時間閾値
- 各閾値は秒単位で設定される
- NRT違反時はメッセージIDがメタデータとして記録される
- SlaEvent作成後、after_create_commitで自動的に通知が作成される
- 通知対象者：会話参加者、アカウント管理者、会話担当者
