# 画面設計書 77-請求設定画面

## 概要

本ドキュメントはChatwootの請求設定画面に関する設計書です。Cloud版ユーザー向けの課金情報管理と、Stripeベースの請求ポータルへのアクセスを提供する画面について記述しています。

### 本画面の処理概要

本画面では、サブスクリプションの管理、プラン情報の確認、Captain AI（AIアシスタント）のクレジット使用状況の確認、およびクレジットの購入を行います。ユーザーはStripeの請求ポータルにアクセスして、支払い方法の変更やプランの変更などを行うことができます。

**業務上の目的・背景**：Cloud版Chatwootを利用する企業は、サブスクリプションプラン、シート数（ユーザー数）、更新日などの請求情報を管理する必要があります。また、Captain AI機能を使用する場合は、レスポンス数やドキュメント数の使用状況を把握し、必要に応じてクレジットを追加購入する必要があります。

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

**主要な操作・処理内容**：
1. サブスクリプション情報の表示：プラン名、シート数、更新日を確認
2. 請求ポータルへのアクセス：Stripeの請求ポータルで支払い管理
3. Captain AI使用状況の確認：レスポンス数、ドキュメント数の使用量/上限を表示
4. クレジットの購入：追加クレジットの購入モーダル
5. サポートチャットの起動：問い合わせ用のChatwootウィジェット起動

**画面遷移**：
- 遷移元：設定ホーム画面、各種Paywall画面のアップグレードボタン
- 遷移先：Stripeの請求ポータル（外部サイト）、ダッシュボードホーム（セルフホスト版の場合）

**権限による表示制御**：管理者（administrator）権限を持つユーザーのみがアクセス可能です。Cloud版のみで利用可能で、セルフホスト版では自動的にダッシュボードホームにリダイレクトされます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 8 | アカウント作成・管理 | 主機能 | 請求・課金の設定管理 |

## 画面種別

設定

## URL/ルーティング

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

## 入出力項目

この画面は主に表示専用で、入力フィールドは限定的です。

### クレジット購入モーダル（PurchaseCreditsModal）

| 項目名 | 項目ID | 種別 | 型 | 必須 | バリデーション | 説明 |
|--------|--------|------|-----|------|---------------|------|
| クレジット数 | credits | 入力 | Number | Yes | required | 購入するクレジット数 |

## 表示項目

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| プラン名 | customAttributes.plan_name | 現在のサブスクリプションプラン |
| シート数 | customAttributes.subscribed_quantity | 契約ユーザー数 |
| 更新日 | subscriptionRenewsOn | 次回更新日（フォーマット済み） |
| Captain有効状態 | captainEnabled | Captain AIの有効/無効 |
| レスポンス使用量 | responseLimits | AI応答の使用量と上限 |
| ドキュメント使用量 | documentLimits | 学習ドキュメントの使用量と上限 |

## イベント仕様

### 1-請求ポータルボタン押下

**トリガー**: 「Manage Subscription」ボタンのクリック

**処理フロー**:
1. `onClickBillingPortal`を実行
2. `accounts/checkout`アクションを呼び出し
3. Stripeの請求ポータルURLを取得
4. 新しいウィンドウまたは現在のウィンドウで請求ポータルを開く

### 2-クレジット購入ボタン押下

**トリガー**: 「Buy Credits」ボタンのクリック

**処理フロー**:
1. `openPurchaseCreditsModal`を実行
2. PurchaseCreditsModalを開く
3. ユーザーがクレジット数を選択
4. 購入処理を実行
5. 成功時、`handleTopupSuccess`を呼び出しクレジット残高を更新

### 3-クレジット更新ボタン押下

**トリガー**: 「Refresh Credits」ボタンのクリック

**処理フロー**:
1. `fetchLimits`を実行
2. Captain AIの使用量/上限情報を再取得
3. UI表示を更新

### 4-サポートチャット起動

**トリガー**: 「Chat with Us」ボタンのクリック

**処理フロー**:
1. `onToggleChatWindow`を実行
2. `window.$chatwoot.toggle()`でChatwootウィジェットを開閉

### 5-画面マウント（請求情報なしの場合）

**トリガー**: 画面のマウント時にhasABillingPlanがfalse

**処理フロー**:
1. `handleBillingPageLogic`を実行
2. セルフホスト版の場合、ダッシュボードホームにリダイレクト
3. Cloud版でプラン情報がない場合、sessionStorageで1回だけ自動リフレッシュ
4. リフレッシュ後もプラン情報がない場合、「no billing」メッセージを表示

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| プラン情報取得 | accounts | SELECT | アカウントのcustom_attributes取得 |
| クレジット購入 | 外部（Stripe） | - | Stripeの請求処理 |

この画面は主に外部サービス（Stripe）との連携であり、直接的なデータベース更新は限定的です。

## メッセージ仕様

| 種別 | キー | メッセージ | 表示条件 |
|------|-----|-----------|---------|
| ローディング | BILLING_SETTINGS.NO_BILLING_USER | 請求情報を確認中... | 請求プランが見つからない場合 |
| 空状態 | BILLING_SETTINGS.NO_BILLING_USER | 請求情報がありません | リフレッシュ後もプランがない場合 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| 権限不足 | 管理者権限がない場合、画面にアクセスできない |
| セルフホスト版 | 自動的にダッシュボードホーム画面にリダイレクト |
| 請求情報なし | 1回だけ自動リフレッシュを試行、それでもない場合はメッセージ表示 |
| API通信エラー | エラーをキャッチしてログ出力 |

## 備考

- Cloud版のみで利用可能（INSTALLATION_TYPES.CLOUD）
- Captain AI機能は有効なプランでのみ表示
- クレジット購入は「Hacker」プラン以外で利用可能
- 請求ポータルはStripeが提供するホスト型ポータル
- sessionStorageを使用して請求情報の自動リフレッシュを制御
- Chatwootウィジェットによるサポートチャット機能を提供

---

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

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

### 推奨読解順序

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

まず、アカウントの請求関連データ構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | useAccount.js | `app/javascript/dashboard/composables/useAccount.js` | currentAccountとisOnChatwootCloudの取得 |
| 1-2 | useCaptain.js | `app/javascript/dashboard/composables/useCaptain.js` | Captain AI関連の状態とメソッド |

**読解のコツ**: アカウントのcustom_attributesにplan_name, subscribed_quantity, subscription_ends_on等の請求情報が格納される。Captain関連のlimitsはuseCaptain composableで管理。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Index.vue | `app/javascript/dashboard/routes/dashboard/settings/billing/Index.vue` | 請求情報の表示ロジック、Stripeポータル遷移 |

**主要処理フロー**:
1. **行20-28**: `useCaptain` composableでCaptain関連状態を取得
2. **行47-49**: `planName`でカスタム属性からプラン名を取得
3. **行87-119**: `handleBillingPageLogic`で初期化処理とリダイレクト判定
4. **行121-123**: `onClickBillingPortal`でStripeポータルへ遷移

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | BillingCard.vue | `app/javascript/dashboard/routes/dashboard/settings/billing/components/BillingCard.vue` | 請求情報カードの表示 |
| 3-2 | BillingMeter.vue | `app/javascript/dashboard/routes/dashboard/settings/billing/components/BillingMeter.vue` | 使用量メーターの表示 |
| 3-3 | DetailItem.vue | `app/javascript/dashboard/routes/dashboard/settings/billing/components/DetailItem.vue` | 詳細項目の表示 |
| 3-4 | PurchaseCreditsModal.vue | `app/javascript/dashboard/routes/dashboard/settings/billing/components/PurchaseCreditsModal.vue` | クレジット購入モーダル |

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

```
Index.vue (エントリーポイント)
    │
    ├─ onMounted
    │      └─ handleBillingPageLogic
    │             ├─ isOnChatwootCloud判定
    │             │      └─ セルフホスト → router.push('home')
    │             │
    │             ├─ fetchAccountDetails
    │             │      ├─ accounts/subscription (プラン情報がない場合)
    │             │      └─ fetchLimits (Captain使用量)
    │             │
    │             └─ hasABillingPlan判定
    │                    └─ プランなし → sessionStorage確認 → リフレッシュ
    │
    ├─ BillingCard (サブスクリプション管理)
    │      └─ @click → onClickBillingPortal
    │             └─ store.dispatch('accounts/checkout')
    │
    ├─ BillingCard (Captain使用状況)
    │      ├─ BillingMeter (レスポンス)
    │      ├─ BillingMeter (ドキュメント)
    │      └─ @click → fetchLimits / openPurchaseCreditsModal
    │
    ├─ PurchaseCreditsModal
    │      └─ @success → handleTopupSuccess
    │             └─ fetchLimits
    │
    └─ BillingHeader (サポートチャット)
           └─ @click → onToggleChatWindow
                  └─ window.$chatwoot.toggle()
```

### データフロー図

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

アカウント情報 ─────────▶ useAccount ──────────────────▶ currentAccount
       │                        │
       │                        ▼
       │                 custom_attributes ────────────▶ planName, subscribedQuantity等
       │
       └── Captain設定 ──▶ useCaptain ─────────────────▶ captainEnabled, limits

[請求ポータル]

ボタン押下 ─────────────▶ accounts/checkout ────────────▶ Stripe Portal URL
       │                        │
       │                        ▼
       └────────────────── 外部サイト遷移 ─────────────▶ Stripe請求ポータル

[クレジット購入]

モーダル入力 ────────────▶ 購入処理 ─────────────────────▶ クレジット追加
       │                        │
       │                        ▼
       └── handleTopupSuccess ─▶ fetchLimits ──────────▶ 使用量更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Index.vue | `app/javascript/dashboard/routes/dashboard/settings/billing/Index.vue` | ソース | メイン画面コンポーネント |
| BillingCard.vue | `app/javascript/dashboard/routes/dashboard/settings/billing/components/BillingCard.vue` | ソース | 請求情報カード |
| BillingMeter.vue | `app/javascript/dashboard/routes/dashboard/settings/billing/components/BillingMeter.vue` | ソース | 使用量メーター |
| BillingHeader.vue | `app/javascript/dashboard/routes/dashboard/settings/billing/components/BillingHeader.vue` | ソース | ヘッダーコンポーネント |
| DetailItem.vue | `app/javascript/dashboard/routes/dashboard/settings/billing/components/DetailItem.vue` | ソース | 詳細項目コンポーネント |
| PurchaseCreditsModal.vue | `app/javascript/dashboard/routes/dashboard/settings/billing/components/PurchaseCreditsModal.vue` | ソース | クレジット購入モーダル |
| useAccount.js | `app/javascript/dashboard/composables/useAccount.js` | ソース | アカウント情報composable |
| useCaptain.js | `app/javascript/dashboard/composables/useCaptain.js` | ソース | Captain AI composable |
| billing.routes.js | `app/javascript/dashboard/routes/dashboard/settings/billing/billing.routes.js` | ソース | ルーティング定義 |
| accounts.js (store) | `app/javascript/dashboard/store/modules/accounts.js` | ソース | Vuexストアモジュール |
