# 画面設計書 71-Shopify連携画面

## 概要

本ドキュメントはChatwootのShopify連携画面に関する設計書です。管理者がShopifyストアとの連携を設定・管理するための画面について記述しています。

### 本画面の処理概要

本画面では、ChatwootとShopifyストアを連携するための設定を行います。連携することで、顧客の注文情報をChatwootの会話画面内で直接確認できるようになり、カスタマーサポートの効率化を実現します。

**業務上の目的・背景**：ECサイト運営者がカスタマーサポートを行う際、顧客の注文履歴や購買情報を確認しながら対応することが多い。Shopify連携により、サポート担当者は別画面に切り替えることなく、Chatwoot内で顧客の注文情報を即座に確認でき、対応時間の短縮と顧客満足度の向上を実現できます。

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

**主要な操作・処理内容**：
1. Shopifyストアの接続：ShopifyストアURLを入力して認証フローを開始
2. 連携状態の確認：現在の連携状態（接続済み/未接続）の表示
3. 連携の解除：接続済みの場合、連携を解除する操作

**画面遷移**：
- 遷移元：連携アプリ一覧画面（settings_applications）
- 遷移先：Shopify OAuth認証画面（外部サイト）、連携アプリ一覧画面

**権限による表示制御**：管理者（administrator）権限を持つユーザーのみがアクセス可能です。一般エージェントはこの画面にアクセスできません。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 147 | Shopify統合 | 主機能 | Shopify連携の設定と管理 |

## 画面種別

設定・連携

## URL/ルーティング

| 項目 | 値 |
|------|-----|
| パス | `/app/accounts/:accountId/settings/integrations/shopify` |
| ルート名 | `settings_integrations_shopify` |
| コンポーネント | `Shopify.vue` |

## 入出力項目

| 項目名 | 項目ID | 種別 | 型 | 必須 | バリデーション | 説明 |
|--------|--------|------|-----|------|---------------|------|
| ストアURL | storeUrl | 入力 | String | Yes | `/^[a-zA-Z0-9][a-zA-Z0-9-]*\.myshopify\.com$/` | ShopifyストアのURL（例：your-store.myshopify.com） |
| エラー | error | URL Query | String | No | - | OAuth認証失敗時のエラーメッセージ |

## 表示項目

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| 連携名 | integration.name | Shopify連携の表示名 |
| 説明 | integration.description | Shopify連携の説明文 |
| ロゴ | integration.logo | Shopifyのロゴ画像 |
| 連携状態 | integration.enabled | 連携の有効/無効状態 |

## イベント仕様

### 1-接続ボタン押下

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

**処理フロー**:
1. ストアURLダイアログを表示
2. ユーザーがShopifyストアURLを入力
3. 「Confirm」ボタン押下で入力値をバリデーション
4. バリデーション成功時、`integrationAPI.connectShopify()` を呼び出し
5. レスポンスに含まれるリダイレクトURLにページ遷移
6. Shopify側で認証が完了すると、コールバックURLでChatwootに戻る

### 2-切断ボタン押下

**トリガー**: 連携済み状態で「Disconnect」ボタンのクリック

**処理フロー**:
1. 削除確認ダイアログを表示
2. 確認後、`store.dispatch('integrations/deleteIntegration', integrationId)` を呼び出し
3. 連携削除成功時、アラートメッセージを表示
4. 連携アプリ一覧画面に遷移

### 3-ダイアログキャンセル

**トリガー**: ストアURLダイアログで「Cancel」ボタン押下またはダイアログ外クリック

**処理フロー**:
1. 入力値をリセット（storeUrl、storeUrlError、isSubmitting）
2. ダイアログを閉じる

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 接続完了 | integrations_hooks | INSERT | Shopify連携フックの作成 |
| 切断 | integrations_hooks | DELETE | Shopify連携フックの削除 |

### テーブル別更新項目詳細

#### integrations_hooks

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | app_id | 'shopify' | 連携アプリID |
| INSERT | account_id | 現在のアカウントID | - |
| INSERT | status | 'enabled' | 連携状態 |
| INSERT | settings | OAuth認証情報 | アクセストークン等 |
| DELETE | id | 対象フックID | 連携解除時 |

## メッセージ仕様

| 種別 | キー | メッセージ | 表示条件 |
|------|-----|-----------|---------|
| エラー | INTEGRATION_SETTINGS.SHOPIFY.STORE_URL.ERROR | 無効なストアURL形式 | バリデーション失敗時 |
| エラー | INTEGRATION_SETTINGS.SHOPIFY.ERROR | Shopify連携エラー | OAuth認証失敗時（URLパラメータ） |
| 成功 | INTEGRATION_SETTINGS.DELETE.API.SUCCESS_MESSAGE | 連携が正常に削除されました | 連携解除成功時 |
| エラー | INTEGRATION_SETTINGS.WEBHOOK.DELETE.API.ERROR_MESSAGE | 連携の削除に失敗しました | 連携解除失敗時 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| 権限不足 | 管理者権限がない場合、画面にアクセスできない |
| API通信エラー | エラーメッセージを表示し、処理を中断 |
| OAuth認証失敗 | URLパラメータのerrorを基にエラーメッセージを表示 |
| 無効なストアURL | バリデーションエラーを表示し、送信を阻止 |

## 備考

- Shopify連携はCloud/Enterprise版のみで利用可能
- 連携にはShopifyストアの管理者権限が必要
- OAuth 2.0を使用した認証フローを実装
- 連携後、会話画面のコンタクトパネルに「Shopify Orders」セクションが表示される

---

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

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

### 推奨読解順序

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

まず、連携アプリのデータ構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | integrations.js (store) | `app/javascript/dashboard/store/modules/integrations.js` | stateのrecords配列構造、integration.enabled等のプロパティ |

**読解のコツ**: Vuexストアのstateでintegrationオブジェクトがどのような形式で保持されるか、gettersでどのようにアクセスされるかを確認する。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Shopify.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/Shopify.vue` | setup関数での初期化処理、テンプレート構造 |

**主要処理フロー**:
1. **行29**: `useFunctionGetter`でShopify連携情報を取得
2. **行80-83**: `initializeShopifyIntegration`でマウント時に連携情報を取得
3. **行56-78**: `handleStoreUrlSubmit`でストアURL送信処理
4. **行45-48**: `validateStoreUrl`でURL形式のバリデーション

#### Step 3: APIレイヤーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | integrations.js (API) | `app/javascript/dashboard/api/integrations.js` | connectShopifyメソッドの実装 |

**主要処理フロー**:
- **行36-40**: `connectShopify`メソッドでPOSTリクエストを送信

#### Step 4: 共通コンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Integration.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/Integration.vue` | 連携の基本表示と削除機能 |

**主要処理フロー**:
- **行47-54**: `deleteIntegration`でストア経由の連携削除
- **行98-116**: 連携状態に応じたボタン表示の切り替え

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

```
Shopify.vue (エントリーポイント)
    │
    ├─ onMounted
    │      └─ initializeShopifyIntegration
    │             └─ store.dispatch('integrations/get', 'shopify')
    │                    └─ IntegrationsAPI.get()
    │
    ├─ handleStoreUrlSubmit
    │      ├─ validateStoreUrl
    │      └─ integrationAPI.connectShopify()
    │             └─ window.location.href = redirect_url
    │
    └─ Integration.vue (子コンポーネント)
           └─ deleteIntegration
                  └─ store.dispatch('integrations/deleteIntegration')
                         └─ IntegrationsAPI.delete()
```

### データフロー図

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

StoreURL ─────────────▶ validateStoreUrl ─────────────▶ バリデーション結果
     │                         │
     │                         ▼
     └────────────────▶ integrationAPI.connectShopify ─▶ redirect_url
                               │
                               ▼
                       Shopify OAuth ─────────────────▶ コールバック
                               │
                               ▼
                       integrations store ────────────▶ UI更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Shopify.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/Shopify.vue` | ソース | メイン画面コンポーネント |
| Integration.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/Integration.vue` | ソース | 連携表示の共通コンポーネント |
| integrations.js (API) | `app/javascript/dashboard/api/integrations.js` | ソース | API通信クラス |
| integrations.js (store) | `app/javascript/dashboard/store/modules/integrations.js` | ソース | Vuexストアモジュール |
| integrations.routes.js | `app/javascript/dashboard/routes/dashboard/settings/integrations/integrations.routes.js` | ソース | ルーティング定義 |
| Dialog.vue | `app/javascript/dashboard/components-next/dialog/Dialog.vue` | ソース | ダイアログコンポーネント |
| Input.vue | `app/javascript/dashboard/components-next/input/Input.vue` | ソース | 入力コンポーネント |
| Button.vue | `app/javascript/dashboard/components-next/button/Button.vue` | ソース | ボタンコンポーネント |
