# 機能設計書 185-ポリシーユーザー

## 概要

本ドキュメントは、Chatwootにおける「ポリシーユーザー」機能の設計仕様を定義する。本機能は、エージェント容量ポリシーに所属するユーザー（エージェント）を管理するためのエンタープライズ専用機能である。

### 本機能の処理概要

本機能は、管理者が特定の容量ポリシーにエージェントを割り当て・解除することを可能にする。ポリシーに割り当てられたエージェントは、そのポリシーで定義された容量制限に従って会話が割り当てられる。

**業務上の目的・背景**：エージェントの経験レベルやスキル、勤務形態に応じて異なる容量制限を適用する必要がある。新人エージェントには少なめの容量を、ベテランには多めの容量を設定することで、適切な負荷分散とOJTを両立できる。パートタイムとフルタイムで異なる容量を設定することも可能。

**機能の利用シーン**：新しいエージェントをチームに追加した際に適切なポリシーに割り当てる。エージェントのスキルアップに伴いポリシーを変更する。一時的に容量を制限したい場合にポリシーを変更する。

**主要な処理内容**：
1. ポリシーに所属するユーザー一覧の取得
2. ユーザーをポリシーに割り当て
3. ユーザーをポリシーから解除

**関連システム・外部連携**：容量ポリシー機能（No.184）、自動割り当て機能

**権限による制御**：エンタープライズアカウントの管理者のみがアクセス可能

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 84 | エージェント容量一覧 | 主画面 | ポリシーに属するユーザーの表示 |
| 86 | エージェント容量編集 | 主画面 | ユーザーの割り当て・解除 |

## 機能種別

CRUD操作 / 設定管理 / Enterprise機能

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| agent_capacity_policy_id | Integer | Yes | ポリシーID | URLパスパラメータ |
| user_id | Integer | Yes（create時） | ユーザーID | アカウントに所属するユーザー |
| id | Integer | Yes（destroy時） | ユーザーID | URLパスパラメータ |

### 入力データソース

- APIリクエスト（JSON形式）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | Integer | ユーザーID |
| name | String | ユーザー名 |
| email | String | メールアドレス |
| avatar_url | String | アバターURL |

### 出力先

- HTTPレスポンス（JSON形式）

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ アクション種別を判定

2. ポリシー取得
   └─ agent_capacity_policy_idでポリシーを取得

3. 認可チェック
   └─ AgentCapacityPolicyに対する権限を確認

4. アクション実行
   ├─ index: ポリシーに所属するユーザー一覧取得
   ├─ create: ユーザーをポリシーに割り当て
   └─ destroy: ユーザーをポリシーから解除

5. レスポンス返却
   └─ JSON形式またはhead :ok
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B[fetch_policy]
    B --> C[check_authorization]
    C --> D{アクション}

    D -->|index| E[ユーザー一覧取得]
    D -->|create| F[account_user取得]
    D -->|destroy| G[account_user取得]

    F --> H[ポリシー割り当て更新]
    G --> I[ポリシー割り当て解除]

    E --> J[レスポンス返却]
    H --> K[@userを返却]
    I --> L[head :ok]

    J --> M[終了]
    K --> M
    L --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-185-01 | エンタープライズ専用 | 本機能はエンタープライズエディションでのみ利用可能 | 常時 |
| BR-185-02 | 単一ポリシー | 1ユーザーは同時に1つのポリシーにのみ所属可能 | 常時 |
| BR-185-03 | アカウント境界 | 同一アカウント内のユーザーのみ割り当て可能 | 常時 |
| BR-185-04 | 解除時のnull設定 | 解除時はaccount_user.agent_capacity_policy_idをnullに設定 | 解除時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 一覧取得 | users, account_users | SELECT | ポリシーに所属するユーザー一覧 |
| 割り当て | account_users | UPDATE | agent_capacity_policy_idの更新 |
| 解除 | account_users | UPDATE | agent_capacity_policy_idをnullに |

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

#### users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | account_users.agent_capacity_policy_id = @agent_capacity_policy.id | JOIN経由 |

#### account_users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | account_id = Current.account.id, user_id = params[:user_id] | ユーザー取得 |
| UPDATE | agent_capacity_policy_id | @agent_capacity_policy.id | 割り当て |
| UPDATE | agent_capacity_policy_id | nil | 解除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 403 | Forbidden | 非エンタープライズアカウント | エラーレスポンス返却 |
| 403 | Forbidden | 権限不足 | エラーレスポンス返却 |
| 404 | Not Found | ポリシーが存在しない | エラーレスポンス返却 |
| 404 | Not Found | ユーザーが存在しない | エラーレスポンス返却 |

### リトライ仕様

同期処理のため、リトライ仕様は適用されない。

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

update! による暗黙的なトランザクション制御。

## パフォーマンス要件

- 単純なCRUD操作のため、特別なパフォーマンス要件なし
- 応答時間: 通常100ms以内

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

- エンタープライズエディション専用機能
- AgentCapacityPolicyに対する権限チェック
- アカウント境界の厳守

## 備考

- ユーザーのポリシー所属はaccount_usersテーブルで管理
- 1ユーザーが複数ポリシーに所属することはできない

---

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

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

### 推奨読解順序

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

まず、ユーザーとポリシーの関連を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | agent_capacity_policy.rb | `enterprise/app/models/agent_capacity_policy.rb` | account_usersリレーション |
| 1-2 | account_user.rb | `app/models/account_user.rb` | ポリシー参照の定義 |

**読解のコツ**:
- AgentCapacityPolicyの`has_many :account_users`で1対多の関連
- AccountUserにはagent_capacity_policy_idカラムが存在

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

ユーザー管理APIの実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | users_controller.rb | `enterprise/app/controllers/api/v1/accounts/agent_capacity_policies/users_controller.rb` | CRUD実装 |

**主要処理フロー**:
- **1行目**: EnterpriseAccountsControllerを継承
- **2行目**: check_authorization(AgentCapacityPolicy) - ポリシーに対する権限チェック
- **6-9行目**: indexアクション - JOINクエリでユーザー一覧取得
- **11-15行目**: createアクション - account_userのポリシー更新
- **17-20行目**: destroyアクション - ポリシー解除

#### Step 3: クエリ構造を理解する

indexアクションのクエリ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | users_controller.rb | `enterprise/app/controllers/api/v1/accounts/agent_capacity_policies/users_controller.rb` | indexのクエリ |

**主要処理フロー**:
- **7-8行目**: User.joins(:account_users).where(...) - account_usersを経由したユーザー取得

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

```
APIリクエスト
    │
    ├─ EnterpriseAccountsController (継承)
    │
    └─ AgentCapacityPolicies::UsersController
           │
           ├─ before_action :check_authorization(AgentCapacityPolicy)
           ├─ before_action :fetch_policy
           ├─ before_action :fetch_user (destroyのみ)
           │
           ├─ index
           │      └─ User.joins(:account_users).where(
           │             account_users: {
           │               account_id: Current.account.id,
           │               agent_capacity_policy_id: @agent_capacity_policy.id
           │             }
           │         )
           │
           ├─ create
           │      ├─ account_users.find_by!(user_id: params[:user_id])
           │      └─ @account_user.update!(agent_capacity_policy: @agent_capacity_policy)
           │
           └─ destroy
                  └─ @account_user.update!(agent_capacity_policy: nil)
```

### データフロー図

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

APIリクエスト ─────────▶ UsersController ─────────────────▶ JSON Response
(user_id)                     │
                              ▼
                     fetch_policy
                     (ポリシー取得)
                              │
                              ▼
                     account_user 操作
                     (update!)
                              │
                              ▼
                     account_users テーブル
                     (agent_capacity_policy_id更新)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| users_controller.rb | `enterprise/app/controllers/api/v1/accounts/agent_capacity_policies/users_controller.rb` | コントローラー | ユーザー管理API |
| agent_capacity_policy.rb | `enterprise/app/models/agent_capacity_policy.rb` | モデル | ポリシーモデル |
| account_user.rb | `app/models/account_user.rb` | モデル | アカウント-ユーザー関連 |
| user.rb | `app/models/user.rb` | モデル | ユーザーモデル |
