# 画面設計書 75-SLA一覧画面

## 概要

本ドキュメントはChatwootのSLA一覧画面に関する設計書です。SLA（Service Level Agreement）ポリシーの作成・管理を行う画面について記述しています。

### 本画面の処理概要

本画面では、SLAポリシーの作成と管理を行います。SLAポリシーにより、初回応答時間、次回応答時間、解決時間の目標を設定し、カスタマーサポートの品質基準を定義・監視できます。

**業務上の目的・背景**：カスタマーサポートにおいて、応答時間や解決時間の目標を明確に定義し、それらを監視することは顧客満足度の向上に不可欠です。SLAポリシーを設定することで、チームはサービスレベルの達成状況を把握し、改善が必要な領域を特定できます。違反時の通知機能と組み合わせることで、問題のエスカレーションを自動化できます。

**画面へのアクセス方法**：サイドバーの「設定」から「SLA」メニューを選択してアクセスします。または、URLで直接 `/app/accounts/:accountId/settings/sla/list` にアクセスすることもできます。

**主要な操作・処理内容**：
1. SLAポリシーの一覧表示：登録済みポリシーの名前、説明、各種時間閾値を表示
2. 新しいSLAポリシーの追加：名前、説明、時間閾値、営業時間のみ適用フラグを設定
3. SLAポリシーの削除：不要なポリシーを削除

**画面遷移**：
- 遷移元：設定ホーム画面
- 遷移先：請求設定画面（Paywall表示時のアップグレードボタン押下時）

**権限による表示制御**：管理者（administrator）権限を持つユーザーのみがアクセス可能です。Cloud/Enterprise版でのみ利用可能で、プランによってはPaywallが表示されます。SuperAdminには特別なメッセージが表示されます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 42 | SLAポリシー適用 | 主機能 | SLAポリシーの一覧表示と管理 |

## 画面種別

一覧

## URL/ルーティング

| 項目 | 値 |
|------|-----|
| パス | `/app/accounts/:accountId/settings/sla/list` |
| ルート名 | `sla_list` |
| コンポーネント | `Index.vue` |

## 入出力項目

### SLA追加フォーム（AddSLA / SlaForm）

| 項目名 | 項目ID | 種別 | 型 | 必須 | バリデーション | 説明 |
|--------|--------|------|-----|------|---------------|------|
| 名前 | name | 入力 | String | Yes | required | SLAポリシーの名前 |
| 説明 | description | 入力 | String | No | - | SLAポリシーの説明 |
| 初回応答時間 | first_response_time_threshold | 入力 | Number | No | - | 初回応答までの目標時間（秒） |
| 次回応答時間 | next_response_time_threshold | 入力 | Number | No | - | 次回応答までの目標時間（秒） |
| 解決時間 | resolution_time_threshold | 入力 | Number | No | - | 解決までの目標時間（秒） |
| 営業時間のみ | only_during_business_hours | 入力 | Boolean | No | - | 営業時間のみでカウントするか |

## 表示項目

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| SLA一覧 | records (sla/getSLA) | 登録済みSLAポリシーのリスト |
| SLA名 | sla.name | SLAポリシーの名前 |
| 説明 | sla.description | SLAポリシーの説明 |
| 初回応答時間 | displayTime(sla.first_response_time_threshold) | フォーマット済み時間表示 |
| 次回応答時間 | displayTime(sla.next_response_time_threshold) | フォーマット済み時間表示 |
| 解決時間 | displayTime(sla.resolution_time_threshold) | フォーマット済み時間表示 |
| 営業時間フラグ | sla.only_during_business_hours | 営業時間のみ適用のアイコン/バッジ |

## イベント仕様

### 1-SLA追加ボタン押下

**トリガー**: 「Add SLA」ボタンのクリック

**処理フロー**:
1. `isBehindAPaywall`をチェック
2. Paywall状態でない場合、`showAddPopup`をtrueに設定
3. AddSLAモーダルを表示
4. フォーム入力後、送信時に`sla/create`アクションを呼び出し
5. 成功時、アラートを表示しモーダルを閉じる

### 2-SLA削除ボタン押下

**トリガー**: 各SLA行の「Delete」ボタンのクリック

**処理フロー**:
1. `openDeletePopup`で`selectedResponse`に対象SLAを設定
2. `showDeleteConfirmationPopup`をtrueに設定
3. 削除確認モーダルを表示
4. 確認後、`confirmDeletion`を実行
5. `sla/delete`アクションを呼び出し
6. 成功時、アラートを表示しモーダルを閉じる

### 3-アップグレードボタン押下（Paywall表示時）

**トリガー**: Paywall内の「Upgrade」ボタンのクリック

**処理フロー**:
1. `onClickCTA`を実行
2. `billing_settings_index`ルートに遷移

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| SLA追加 | sla_policies | INSERT | 新しいSLAポリシーの作成 |
| SLA削除 | sla_policies | DELETE | SLAポリシーの削除 |

### テーブル別更新項目詳細

#### sla_policies

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | account_id | 現在のアカウントID | - |
| INSERT | name | フォーム入力値 | ポリシー名 |
| INSERT | description | フォーム入力値 | 説明 |
| INSERT | first_response_time_threshold | フォーム入力値（秒） | 初回応答時間 |
| INSERT | next_response_time_threshold | フォーム入力値（秒） | 次回応答時間 |
| INSERT | resolution_time_threshold | フォーム入力値（秒） | 解決時間 |
| INSERT | only_during_business_hours | フォーム入力値 | 営業時間フラグ |
| DELETE | id | selectedResponse.id | 削除対象ID |

## メッセージ仕様

| 種別 | キー | メッセージ | 表示条件 |
|------|-----|-----------|---------|
| 成功 | SLA.ADD.API.SUCCESS_MESSAGE | SLAポリシーが正常に作成されました | SLA追加成功時 |
| エラー | SLA.ADD.API.ERROR_MESSAGE | SLAポリシーの作成に失敗しました | SLA追加失敗時 |
| 成功 | SLA.DELETE.API.SUCCESS_MESSAGE | SLAポリシーが正常に削除されました | SLA削除成功時 |
| エラー | SLA.DELETE.API.ERROR_MESSAGE | SLAポリシーの削除に失敗しました | SLA削除失敗時 |
| 確認 | SLA.DELETE.CONFIRM.TITLE | SLAポリシーを削除しますか？ | 削除確認ダイアログタイトル |
| 確認 | SLA.DELETE.CONFIRM.MESSAGE | この操作は取り消せません | 削除確認ダイアログメッセージ |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| 権限不足 | 管理者権限がない場合、画面にアクセスできない |
| 機能制限（Paywall） | Cloud/Enterprise版でSLA機能が無効な場合、Paywall表示 |
| API通信エラー | エラーメッセージをアラートで表示 |

## 備考

- Cloud/Enterprise版のみで利用可能
- 時間表示は `convertSecondsToTimeUnit` で変換（1m, 1h, 1d形式）
- 営業時間のみフラグがオンの場合、営業時間外の時間はSLA計算から除外
- SLAポリシーは自動化ルールで会話に適用される
- SuperAdminには特別なPaywallメッセージが表示される

---

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

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

### 推奨読解順序

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

まず、SLAポリシーのデータ構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sla.js (store) | `app/javascript/dashboard/store/modules/sla.js` | stateのrecords配列構造、SLAオブジェクトのプロパティ |

**読解のコツ**: SLAオブジェクトにはname, description, first_response_time_threshold, next_response_time_threshold, resolution_time_threshold, only_during_business_hours等のプロパティがある。

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

処理の起点となるVueコンポーネントを理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Index.vue | `app/javascript/dashboard/routes/dashboard/settings/sla/Index.vue` | Paywall判定ロジック、時間表示変換 |

**主要処理フロー**:
1. **行33-39**: mapGettersでストアのデータを取得
2. **行50-52**: `isBehindAPaywall`でFeature Flag確認
3. **行57-59**: `mounted`で`sla/get`アクションを呼び出し
4. **行95-103**: `displayTime`で秒を読みやすい形式に変換

#### Step 3: コンポーネント階層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SLAHeader.vue | `app/javascript/dashboard/routes/dashboard/settings/sla/components/SLAHeader.vue` | ヘッダーと追加ボタン |
| 3-2 | SLAListItem.vue | `app/javascript/dashboard/routes/dashboard/settings/sla/components/SLAListItem.vue` | 各SLAの表示カード |
| 3-3 | SLAEmptyState.vue | `app/javascript/dashboard/routes/dashboard/settings/sla/components/SLAEmptyState.vue` | SLAが0件時の表示 |
| 3-4 | SLAPaywallEnterprise.vue | `app/javascript/dashboard/routes/dashboard/settings/sla/components/SLAPaywallEnterprise.vue` | Paywall表示 |

#### Step 4: フォームコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | AddSLA.vue | `app/javascript/dashboard/routes/dashboard/settings/sla/AddSLA.vue` | SLA追加モーダルのラッパー |
| 4-2 | SlaForm.vue | `app/javascript/dashboard/routes/dashboard/settings/sla/SlaForm.vue` | SLAフォームの実装 |

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

```
Index.vue (エントリーポイント)
    │
    ├─ mounted
    │      └─ store.dispatch('sla/get')
    │             └─ SlaAPI.get()
    │
    ├─ computed: isBehindAPaywall
    │      └─ isFeatureEnabledonAccount('sla')
    │
    ├─ SLAHeader (ヘッダー)
    │      └─ @add → openAddPopup
    │
    ├─ SLAPaywallEnterprise (条件付き表示)
    │      └─ @upgrade → onClickCTA → router.push('billing_settings_index')
    │
    ├─ SLAEmptyState (条件付き表示)
    │      └─ @primary-action → openAddPopup
    │
    ├─ SLAListItem (各SLA表示)
    │      └─ @delete → openDeletePopup
    │
    ├─ AddSLA (追加モーダル)
    │      └─ addSLA()
    │             └─ store.dispatch('sla/create')
    │                    └─ SlaAPI.create()
    │
    └─ woot-delete-modal
           └─ confirmDeletion()
                  └─ deleteSla()
                         └─ store.dispatch('sla/delete')
                                └─ SlaAPI.delete()
```

### データフロー図

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

SLAフォーム ────────────▶ sla/create ──────────────────▶ SLA作成
      │                        │
      │                        ▼
      │                 ADD_SLA mutation ─────────────▶ records更新
      │
      └── 時間値（秒） ─▶ convertSecondsToTimeUnit ────▶ 表示文字列 (1h, 30m等)

[Paywall判定]

accountId ─────────────▶ isFeatureEnabledonAccount ───▶ boolean
      │                        │
      │                        ▼
      └────────────────── isBehindAPaywall ───────────▶ 条件付き表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Index.vue | `app/javascript/dashboard/routes/dashboard/settings/sla/Index.vue` | ソース | メイン画面コンポーネント |
| AddSLA.vue | `app/javascript/dashboard/routes/dashboard/settings/sla/AddSLA.vue` | ソース | SLA追加モーダルラッパー |
| SlaForm.vue | `app/javascript/dashboard/routes/dashboard/settings/sla/SlaForm.vue` | ソース | SLAフォーム |
| SLAHeader.vue | `app/javascript/dashboard/routes/dashboard/settings/sla/components/SLAHeader.vue` | ソース | ヘッダーコンポーネント |
| SLAListItem.vue | `app/javascript/dashboard/routes/dashboard/settings/sla/components/SLAListItem.vue` | ソース | SLA表示カード |
| SLAEmptyState.vue | `app/javascript/dashboard/routes/dashboard/settings/sla/components/SLAEmptyState.vue` | ソース | 空状態表示 |
| SLAPaywallEnterprise.vue | `app/javascript/dashboard/routes/dashboard/settings/sla/components/SLAPaywallEnterprise.vue` | ソース | Paywall表示 |
| sla.js (API) | `app/javascript/dashboard/api/sla.js` | ソース | API通信クラス |
| sla.js (store) | `app/javascript/dashboard/store/modules/sla.js` | ソース | Vuexストアモジュール |
| sla.routes.js | `app/javascript/dashboard/routes/dashboard/settings/sla/sla.routes.js` | ソース | ルーティング定義 |
