# 機能設計書 175-アクティブアカウント切り替え

## 概要

本ドキュメントは、Chatwootにおけるアクティブアカウント切り替え機能の設計仕様を定義する。この機能は、複数のアカウントに所属するユーザーが、現在アクティブなアカウントを切り替えるためのAPIを提供する。

### 本機能の処理概要

**業務上の目的・背景**：
Chatwootでは、1人のユーザーが複数の組織（アカウント）に所属することが可能である。各アカウントは異なるビジネスや部門を表し、ユーザーは適切なコンテキストで作業するために、アクティブなアカウントを切り替える必要がある。この機能により、ユーザーの最終アクティブ時刻を記録し、デフォルトのログインアカウントを管理する。

**機能の利用シーン**：
- ユーザーが複数のアカウントを持ち、異なるアカウントに切り替えて作業する場合
- ダッシュボードからアカウントセレクタでアカウントを変更する場合
- 再ログイン時に最後に使用していたアカウントを自動選択する場合

**主要な処理内容**：
1. 認証済みユーザーの確認
2. 指定されたアカウントのAccountUser取得
3. active_at（最終アクティブ時刻）の更新
4. 204 No Content レスポンス返却

**関連システム・外部連携**：
特になし

**権限による制御**：
認証済みユーザーのみが自身のアクティブアカウントを切り替え可能。自分が所属するアカウントに対してのみ設定可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 89 | プロフィール設定画面 | 主画面 | アクティブアカウントの切り替え |

## 機能種別

CRUD操作（Update）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| profile[account_id] | Integer | Yes | 対象アカウントID | 所属アカウントであること |

### 入力データソース

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

## 出力仕様

### 出力データ

レスポンスボディは空（204 No Content）

### 出力先

- HTTPステータスコード 200 OK（head :ok）

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ PUT /api/v1/profile/set_active_account
2. 認証検証
   └─ current_userから@userを設定
3. AccountUser取得
   └─ account_idで対象のAccountUserを検索
4. active_at更新
   └─ active_atカラムを現在時刻に更新
5. レスポンス返却
   └─ head :ok（200 OK）
```

### フローチャート

```mermaid
flowchart TD
    A[PUT /api/v1/profile/set_active_account] --> B{認証済み?}
    B -->|No| C[401 Unauthorized]
    B -->|Yes| D[AccountUser検索]
    D --> E{存在する?}
    E -->|No| F[処理をスキップ]
    E -->|Yes| G[active_at更新]
    G --> H[200 OK]
    F --> H
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-175-01 | アカウント所属確認 | ユーザーが所属するアカウントに対してのみ設定可能 | account_id指定時 |
| BR-175-02 | 現在時刻の記録 | active_atには現在のUTC時刻を設定 | 更新時 |
| BR-175-03 | find_by使用 | 存在しないアカウントの場合はエラーを発生させない | 検索時 |

### 計算ロジック

**アクティブアカウントの決定**:
- ユーザーのaccount_usersの中で、active_atが最も新しいものがアクティブアカウントとなる
- _user.json.jbuilderのactive_account_userメソッドで取得される

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

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

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

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

#### account_users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | user_id = current_user.id AND account_id = params[:account_id] | AccountUser取得 |
| UPDATE | active_at | Time.now.utc | 現在のUTC時刻 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | Unauthorized | 認証トークンが無効 | 再ログイン |

### リトライ仕様

特になし

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

AccountUserの更新は暗黙のトランザクション内で実行される。

## パフォーマンス要件

- レスポンス時間: 200ms以内

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

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

## 備考

- find_byを使用しているため、存在しないaccount_idを指定してもエラーにならない
- active_atはUIでのアカウント選択順序や自動ログインアカウント決定に使用される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | account_user.rb | `app/models/account_user.rb` | AccountUserモデルのスキーマ、active_atカラム |

**読解のコツ**: active_atカラムはdatetime型で、ユーザーがそのアカウントで最後にアクティブだった時刻を記録する。

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

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

**主要処理フロー**:
1. **31行目**: `set_active_account`アクション定義
2. **32行目**: `@user.account_users.find_by(account_id: ...)` - 対象AccountUserを検索（find_by使用）
3. **32行目**: `.update(active_at: Time.now.utc)` - active_atを更新
4. **33行目**: `head :ok` - 200 OKを返却

#### Step 3: active_account_userの使用箇所を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | _user.json.jbuilder | `app/views/api/v1/models/_user.json.jbuilder` | active_account_userの参照 |

**主要処理フロー**:
- **2行目**: `resource.active_account_user&.account_id` - 最新のアクティブアカウントIDを出力
- **11行目**: `resource.active_account_user&.inviter_id` - アクティブアカウントの招待者ID
- **16行目**: `resource.active_account_user&.role` - アクティブアカウントでのロール

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

```
Api::V1::ProfilesController#set_active_account
    │
    ├─ @user.account_users.find_by(account_id: ...)
    │      └─ AccountUser検索（nilを返す可能性あり）
    │
    └─ AccountUser#update(active_at: Time.now.utc)
           └─ ActiveRecord::Base#save
                  └─ account_users UPDATE
```

### データフロー図

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

PUT リクエスト ───────▶ ProfilesController#set_active_account ───────▶ 200 OK
(account_id)               │
                           ▼
                     AccountUser
                           │
                           └─▶ account_users UPDATE (active_at)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| profiles_controller.rb | `app/controllers/api/v1/profiles_controller.rb` | コントローラー | set_active_accountアクションの定義（31-34行目） |
| account_user.rb | `app/models/account_user.rb` | モデル | AccountUserモデル、active_atカラム定義 |
| _user.json.jbuilder | `app/views/api/v1/models/_user.json.jbuilder` | ビュー | active_account_userの参照 |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（373行目） |
