# 機能設計書 173-可用性設定

## 概要

本ドキュメントは、Chatwootにおけるユーザー可用性（Availability）設定機能の設計仕様を定義する。この機能は、エージェントがアカウント毎に自身のオンライン状態（Online/Offline/Busy）を設定するためのAPIを提供する。

### 本機能の処理概要

**業務上の目的・背景**：
カスタマーサポートチームにおいて、エージェントの可用性状態を正確に管理することは、会話の適切な割り当てと顧客対応の品質維持に不可欠である。エージェントが休憩中や他の業務中であることをシステムに伝えることで、新規会話の自動割り当てを制御し、チーム全体の業務効率を向上させる。

**機能の利用シーン**：
- エージェントが業務を開始し、対応可能状態（Online）に設定する場合
- エージェントが休憩に入り、対応不可状態（Offline）に設定する場合
- エージェントが特定の作業に集中するため、取り込み中状態（Busy）に設定する場合
- 複数アカウントに所属するエージェントが、アカウント毎に異なる状態を設定する場合

**主要な処理内容**：
1. 認証済みユーザーの確認
2. 指定されたアカウントのAccountUser取得
3. 可用性状態（availability）の更新
4. Redis上のプレゼンス情報の更新
5. 更新後のユーザー情報を返却

**関連システム・外部連携**：
- Redis: オンラインステータスのリアルタイム追跡
- OnlineStatusTracker: プレゼンス管理サービス

**権限による制御**：
認証済みユーザーのみが自身の可用性状態を変更可能。自分が所属するアカウントに対してのみ設定可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 89 | プロフィール設定画面 | 主画面 | Online/Offline状態の設定 |

## 機能種別

CRUD操作（Update）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| profile[account_id] | Integer | Yes | 対象アカウントID | 所属アカウントであること |
| profile[availability] | String | Yes | 可用性状態 | "online", "offline", "busy" のいずれか |

### 入力データソース

- フロントエンド画面からのJSON形式リクエスト
- 認証トークンからのユーザー識別

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | Integer | ユーザーID |
| accounts | Array | 所属アカウント一覧（各アカウントのavailability含む） |
| accounts[].availability | String | 設定された可用性状態 |
| accounts[].availability_status | String | プレゼンスを考慮した実際の可用性状態 |

### 出力先

- JSON形式でHTTPレスポンスとして返却

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ POST /api/v1/profile/availability
2. 認証検証
   └─ current_userから@userを設定
3. AccountUser取得
   └─ account_idで対象のAccountUserを検索
4. 可用性更新
   └─ availabilityカラムを更新
5. Redisステータス更新
   └─ OnlineStatusTracker.set_status呼び出し
6. レスポンス生成
   └─ 更新後のユーザー情報をJSON返却
```

### フローチャート

```mermaid
flowchart TD
    A[POST /api/v1/profile/availability] --> B{認証済み?}
    B -->|No| C[401 Unauthorized]
    B -->|Yes| D[AccountUser検索]
    D --> E{存在する?}
    E -->|No| F[404 Not Found]
    E -->|Yes| G[availability更新]
    G --> H{更新成功?}
    H -->|No| I[422 Unprocessable Entity]
    H -->|Yes| J[Redisステータス更新]
    J --> K[JSON レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-173-01 | アカウント所属確認 | ユーザーが所属するアカウントに対してのみ可用性を設定可能 | account_id指定時 |
| BR-173-02 | Redis同期 | 可用性変更時はRedis上のステータスも同期更新 | availability保存成功時 |
| BR-173-03 | 可用性enumの制限 | 許可される値はonline(0), offline(1), busy(2)のみ | availability設定時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| AccountUser検索 | account_users | SELECT | account_idでユーザーのAccountUserを取得 |
| 可用性更新 | account_users | UPDATE | availabilityカラムの更新 |

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

#### account_users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | user_id = current_user.id AND account_id = params[:account_id] | AccountUser取得 |
| UPDATE | availability | 0(online), 1(offline), 2(busy) | enum値として保存 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | Unauthorized | 認証トークンが無効 | 再ログイン |
| 404 | Not Found | 指定されたaccount_idに対応するAccountUserが存在しない | 正しいaccount_idを指定 |
| 422 | Unprocessable Entity | 不正なavailability値 | online/offline/busyのいずれかを指定 |

### リトライ仕様

特になし

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

AccountUserの更新は暗黙のトランザクション内で実行される。更新成功後にRedisへの同期が実行される。

## パフォーマンス要件

- レスポンス時間: 300ms以内
- Redis更新: 非同期またはfire-and-forget

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

- 認証トークンによるアクセス制御
- 自分が所属するアカウントのみ更新可能

## 備考

- availability_statusはRedisのプレゼンス情報と組み合わせて算出される
- auto_offlineがtrueの場合、プレゼンスがないとofflineとして扱われる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | account_user.rb | `app/models/account_user.rb` | AccountUserモデルのスキーマ、availability enumの定義 |
| 1-2 | availability_statusable.rb | `app/models/concerns/availability_statusable.rb` | プレゼンスを考慮した可用性状態の算出ロジック |

**読解のコツ**: AccountUserの`availability`はデータベースに保存される設定値であり、`availability_status`はRedisのプレゼンス情報と組み合わせて算出される実際の状態である。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | profiles_controller.rb | `app/controllers/api/v1/profiles_controller.rb` | availabilityアクションの実装 |

**主要処理フロー**:
1. **27行目**: `availability`アクション定義
2. **28行目**: `@user.account_users.find_by!(account_id: ...)` - 対象AccountUserを検索
3. **28行目**: `.update!(availability: ...)` - 可用性状態を更新
4. **52-54行目**: `availability_params` - 許可されるパラメータの定義

#### Step 3: コールバックとRedis同期を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | account_user.rb | `app/models/account_user.rb` | after_saveコールバックでのRedis更新 |

**主要処理フロー**:
- **41行目**: `after_save :update_presence_in_redis, if: :saved_change_to_availability?`
- **79-81行目**: `update_presence_in_redis` - OnlineStatusTracker.set_statusを呼び出し

#### Step 4: ビューテンプレートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | availability.jbuilder | `app/views/api/v1/profiles/availability.jbuilder` | レスポンスJSON構造 |
| 4-2 | _user.json.jbuilder | `app/views/api/v1/models/_user.json.jbuilder` | accountsのavailability情報 |

**主要処理フロー**:
- **_user.json.jbuilder 29-32行目**: accounts配列内でavailability, availability_status, auto_offlineを出力

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

```
Api::V1::ProfilesController#availability
    │
    ├─ @user.account_users.find_by!(account_id: ...)
    │      └─ AccountUser検索
    │
    └─ AccountUser#update!(availability: ...)
           │
           ├─ ActiveRecord::Base#save!
           │      └─ account_users UPDATE
           │
           └─ AccountUser#update_presence_in_redis (after_save callback)
                  └─ OnlineStatusTracker.set_status(account_id, user_id, availability)
                         └─ Redis SET
```

### データフロー図

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

POST リクエスト ───────▶ ProfilesController#availability ───────▶ JSON Response
(account_id,               │
 availability)             │
                           ▼
                     AccountUser
                           │
                           ├─▶ account_users UPDATE
                           │
                           └─▶ Redis SET (OnlineStatusTracker)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| profiles_controller.rb | `app/controllers/api/v1/profiles_controller.rb` | コントローラー | availabilityアクションの定義（27-29行目） |
| account_user.rb | `app/models/account_user.rb` | モデル | AccountUserモデル、availability enum定義 |
| availability_statusable.rb | `app/models/concerns/availability_statusable.rb` | concern | プレゼンスを考慮した可用性状態の算出 |
| availability.jbuilder | `app/views/api/v1/profiles/availability.jbuilder` | ビュー | レスポンステンプレート |
| _user.json.jbuilder | `app/views/api/v1/models/_user.json.jbuilder` | ビュー | ユーザー情報のpartialテンプレート |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（371行目） |
