# 機能設計書 172-アバター管理

## 概要

本ドキュメントは、Chatwootにおけるユーザーアバター管理機能の設計仕様を定義する。この機能は、ユーザーがプロフィール画像（アバター）を削除するためのAPIを提供する。

### 本機能の処理概要

**業務上の目的・背景**：
カスタマーサポートチームにおいて、エージェントのプロフィール画像は顧客との対話において重要な視覚的要素である。ユーザーが誤った画像をアップロードした場合や、画像を変更したい場合に、既存のアバターを削除できる機能が必要である。アバター削除後はGravatarからの自動取得やデフォルト表示に切り替わる。

**機能の利用シーン**：
- ユーザーが現在のプロフィール画像を削除して、デフォルト状態に戻したい場合
- 新しいアバターをアップロードする前に、既存のアバターを削除したい場合
- 不適切な画像をアップロードしてしまい、すぐに削除したい場合

**主要な処理内容**：
1. 認証済みユーザーの確認
2. アバター画像の添付有無確認
3. ActiveStorageからのアバター削除
4. ユーザー情報のリロードと返却

**関連システム・外部連携**：
- ActiveStorage: 画像ファイルの保存・削除管理
- Gravatar: アバター削除後、メールアドレスに基づく画像取得の可能性

**権限による制御**：
認証済みユーザーのみが自身のアバターを削除可能。他のユーザーのアバターは削除不可。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 89 | プロフィール設定画面 | 主画面 | ユーザーアバターの設定・削除 |

## 機能種別

CRUD操作（Delete）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| なし | - | - | 認証トークンのみで識別 | - |

### 入力データソース

- 認証トークンからのユーザー識別

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | Integer | ユーザーID |
| name | String | ユーザー名 |
| avatar_url | String | アバターURL（削除後は空文字列） |
| その他 | - | プロフィール情報全体を返却 |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ DELETE /api/v1/profile/avatar
2. 認証検証
   └─ current_userから@userを設定
3. アバター確認
   └─ アバターが添付されているか確認
4. アバター削除
   └─ avatar.attachment.destroy!
5. ユーザーリロード
   └─ @user.reload
6. レスポンス生成
   └─ 更新後のユーザー情報をJSON返却
```

### フローチャート

```mermaid
flowchart TD
    A[DELETE /api/v1/profile/avatar] --> B{認証済み?}
    B -->|No| C[401 Unauthorized]
    B -->|Yes| D{アバター添付済み?}
    D -->|No| E[何もしない]
    D -->|Yes| F[アバター削除]
    F --> G[ユーザーリロード]
    E --> G
    G --> H[JSON レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-172-01 | アバター添付確認 | アバターが添付されている場合のみ削除処理を実行 | avatar.attached?がtrueの場合 |
| BR-172-02 | リロード必須 | 削除後はユーザー情報をリロードして最新状態を返却 | 削除処理後 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| アバター削除 | active_storage_attachments | DELETE | アバター添付情報の削除 |
| アバター削除 | active_storage_blobs | DELETE | アバターファイル情報の削除 |

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

#### active_storage_attachments

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | record_id, record_type, name | user.id, 'User', 'avatar' | ユーザーのアバター添付レコードを削除 |

## エラー処理

### エラーケース一覧

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

### リトライ仕様

特になし

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

ActiveStorageの削除処理は暗黙のトランザクション内で実行される。

## パフォーマンス要件

- レスポンス時間: 500ms以内
- 同時アクセス: 特別な制限なし

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

- 認証トークンによるアクセス制御
- 自身のアバターのみ削除可能

## 備考

- アバターはActiveStorageを使用して管理
- アバター削除後、avatar_urlは空文字列を返却
- Gravatarからの自動取得はメールアドレス変更時のみ発動

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | avatarable.rb | `app/models/concerns/avatarable.rb` | アバター機能の実装詳細、has_one_attached :avatar |

**読解のコツ**: Avatarableモジュールは`has_one_attached :avatar`でActiveStorageを使用している。バリデーションは15MB以下、JPEG/PNG/GIFのみ許可。

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

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

**主要処理フロー**:
1. **18行目**: `avatar`アクション定義
2. **19行目**: `@user.avatar.attachment.destroy!` - アバターが添付されている場合のみ削除
3. **20行目**: `@user.reload` - 削除後のユーザー情報をリロード

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | avatar.json.jbuilder | `app/views/api/v1/profiles/avatar.json.jbuilder` | レスポンスJSON構造 |

**主要処理フロー**:
- **1行目**: `_user.json.jbuilder`のpartialを呼び出し、完全なユーザー情報を返却

#### Step 4: ルーティングを確認する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | routes.rb | `config/routes.rb` | avatarルートの定義 |

**主要処理フロー**:
- **369行目**: `delete :avatar, on: :collection` - プロフィールリソースのコレクションにDELETEルートを定義

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

```
Api::V1::ProfilesController#avatar
    │
    ├─ @user.avatar.attached?
    │      └─ ActiveStorage::Attached::One#attached?
    │
    ├─ @user.avatar.attachment.destroy!
    │      └─ ActiveStorage::Attachment#destroy!
    │             └─ active_storage_attachments DELETE
    │             └─ active_storage_blobs DELETE (purge後)
    │
    └─ @user.reload
           └─ User#reload
                  └─ avatar_url (空文字列を返却)
```

### データフロー図

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

DELETE リクエスト ───────▶ ProfilesController#avatar ───────▶ JSON Response
                              │
                              ▼
                        ActiveStorage
                              │
                              ├─▶ active_storage_attachments DELETE
                              │
                              └─▶ active_storage_blobs DELETE
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| profiles_controller.rb | `app/controllers/api/v1/profiles_controller.rb` | コントローラー | avatarアクションの定義（18-21行目） |
| avatarable.rb | `app/models/concerns/avatarable.rb` | concern | アバター機能の実装 |
| user.rb | `app/models/user.rb` | モデル | Avatarableをinclude（50行目） |
| avatar.json.jbuilder | `app/views/api/v1/profiles/avatar.json.jbuilder` | ビュー | レスポンステンプレート |
| _user.json.jbuilder | `app/views/api/v1/models/_user.json.jbuilder` | ビュー | ユーザー情報のpartialテンプレート |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（369行目） |
