# 画面設計書 134-販売チャネル設定画面

## 概要

本ドキュメントは、Medusa Admin Dashboardにおけるロケーションの販売チャネル設定画面の設計仕様を定義するものである。

### 本画面の処理概要

販売チャネル設定画面は、特定のロケーションに紐付ける販売チャネルを選択・管理するための画面である。

**業務上の目的・背景**：ECサイト運営において、複数の販売チャネル（Webサイト、モバイルアプリ、マーケットプレイスなど）を運営している場合、各ロケーション（倉庫、店舗）がどの販売チャネルの注文を処理できるかを設定する必要がある。これにより、注文時に適切なロケーションからフルフィルメントが行われるようになる。

**画面へのアクセス方法**：ロケーション詳細画面 > サイドバーの「Sales Channels」セクション > 「Edit」ボタンをクリックすることでアクセスできる。URLパスは `/settings/locations/{location_id}/sales-channels`。

**主要な操作・処理内容**：
1. 利用可能な販売チャネルの一覧を表示
2. チェックボックスで紐付ける販売チャネルを選択
3. 検索・フィルタ機能で販売チャネルを絞り込み
4. 「保存」ボタンで設定を更新
5. 「キャンセル」ボタンで操作を中断

**画面遷移**：
- 遷移元：ロケーション詳細画面（`/settings/locations/{location_id}`）
- 遷移先：保存完了後、ロケーション詳細画面へ自動的に戻る

**権限による表示制御**：管理者権限を持つユーザーのみがこの画面にアクセスし、販売チャネルの紐付けを変更できる。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 70 | 販売チャネルCRUD | 主機能 | ロケーションの販売チャネル設定 |

## 画面種別

設定画面（フルページモーダル形式）

## URL/ルーティング

- パス: `/settings/locations/:location_id/sales-channels`
- コンポーネント: `LocationSalesChannels`
- ルートファイル: `packages/admin/dashboard/src/routes/locations/location-sales-channels/location-sales-channels.tsx`

## 入出力項目

| 項目名 | 項目ID | 入出力 | 型 | 必須 | バリデーション | 説明 |
|--------|--------|--------|-----|------|---------------|------|
| 販売チャネル選択 | sales_channels | 入力 | string[] | No | - | 選択された販売チャネルIDの配列 |

## 表示項目

### 販売チャネル一覧テーブル

| 項目名 | 説明 |
|--------|------|
| チェックボックス | 販売チャネルの選択状態 |
| チャネル名 | 販売チャネルの名称 |
| 説明 | 販売チャネルの説明 |

### その他

| 項目名 | 説明 |
|--------|------|
| 検索ボックス | 販売チャネル名での検索 |
| フィルター | 販売チャネルのフィルタリング |
| ページネーション | 20件ずつ表示 |

## イベント仕様

### 1-保存ボタン押下

**トリガー**: 「Save」ボタンのクリック、または `Cmd/Ctrl + Enter` キーボードショートカット

**処理フロー**:
1. 選択状態の変更を検出
2. 新規追加するチャネルIDと削除するチャネルIDを算出
3. `useUpdateStockLocationSalesChannels`フックを通じてAPIを呼び出し
4. APIリクエスト: `POST /admin/stock-locations/{location_id}/sales-channels`
5. 成功時: トースト通知を表示し、ロケーション詳細画面へ遷移
6. 失敗時: エラーメッセージをトースト通知で表示

**送信データ**:
```typescript
{
  add: string[],    // 新たに紐付けるチャネルID
  remove: string[]  // 紐付けを解除するチャネルID
}
```

### 2-キャンセルボタン押下

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

**処理フロー**:
1. モーダルを閉じる
2. ロケーション詳細画面に戻る

### 3-行選択変更

**トリガー**: チェックボックスのクリック

**処理フロー**:
1. `rowSelection`ステートを更新
2. フォームの`sales_channels`値を更新（`shouldDirty: true`）

### 4-検索・フィルタ

**トリガー**: 検索ボックス入力、フィルター変更

**処理フロー**:
1. `searchParams`を更新
2. `useSalesChannels`フックが新しいパラメータでデータを再取得

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 保存ボタン押下 | stock_location_sales_channel | INSERT/DELETE | ロケーションと販売チャネルの紐付け更新 |

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

#### stock_location_sales_channel（中間テーブル）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | stock_location_id | 対象ロケーションのID | 外部キー |
| INSERT | sales_channel_id | 追加するチャネルのID | 外部キー |
| DELETE | - | WHERE stock_location_id = ? AND sales_channel_id IN (?) | 削除対象 |

## メッセージ仕様

| メッセージ種別 | メッセージキー | 表示条件 | 表示内容 |
|--------------|---------------|----------|---------|
| 成功 | stockLocations.salesChannels.successToast | 設定更新成功時 | 「Sales channels updated」 |
| エラー | - | API呼び出し失敗時 | APIから返却されたエラーメッセージ |

## 例外処理

| 例外状況 | 処理内容 |
|---------|---------|
| ロケーションが見つからない | エラーをスロー、エラー画面を表示 |
| 販売チャネル取得エラー | エラーをスロー、エラー画面を表示 |
| ネットワークエラー | トースト通知でエラーメッセージを表示 |
| 認証エラー（401） | ログイン画面へリダイレクト |

## 備考

- 画面はフルページモーダル（`RouteFocusModal`）として実装されている
- データテーブル（`DataTable`）コンポーネントを使用
- ページサイズは20件（`PAGE_SIZE = 20`）
- 検索・フィルタパラメータはURLクエリとして管理（プレフィックス: `sc`）
- 初期選択状態は既存の紐付け情報から自動設定
- `placeholderData: keepPreviousData`でページ切り替え時のちらつきを防止

---

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

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

### 推奨読解順序

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

フォームとAPIリクエストの型定義を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | edit-sales-channels-form.tsx | `packages/admin/dashboard/src/routes/locations/location-sales-channels/components/edit-sales-channels-form/edit-sales-channels-form.tsx` | L30-32: `EditSalesChannelsSchema`でフォームスキーマを定義 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | location-sales-channels.tsx | `packages/admin/dashboard/src/routes/locations/location-sales-channels/location-sales-channels.tsx` | L7-27: URLパラメータからlocation_idを取得し、データをフェッチ |

**主要処理フロー**:
1. **L8**: `useParams`でURLからlocation_idを取得
2. **L9-14**: `useStockLocation`でロケーションデータを取得（`*sales_channels`を含む）
3. **L23-25**: データ取得完了時にフォームコンポーネントを表示

#### Step 3: フォームコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | edit-sales-channels-form.tsx | `packages/admin/dashboard/src/routes/locations/location-sales-channels/components/edit-sales-channels-form/edit-sales-channels-form.tsx` | L37-106: フォーム初期化、行選択状態管理、API呼び出し |

**主要処理フロー**:
- **L43-48**: `useForm`でフォーム状態を初期化
- **L52-54**: `getInitialState`で既存の紐付けから初期選択状態を設定
- **L56-63**: `onRowSelectionChange`で選択変更時にフォーム値を更新
- **L86-106**: `handleSubmit`で新規追加・削除するチャネルを算出してAPI呼び出し

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

```
LocationSalesChannels (location-sales-channels.tsx)
    │
    ├─ useStockLocation (既存紐付け取得)
    │
    └─ LocationEditSalesChannelsForm (edit-sales-channels-form.tsx)
           │
           ├─ useForm (react-hook-form)
           │
           ├─ useSalesChannels (販売チャネル一覧取得)
           │
           ├─ DataTable (選択UI)
           │
           └─ useUpdateStockLocationSalesChannels
                  └─ POST /admin/stock-locations/{id}/sales-channels
```

### データフロー図

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

既存紐付け取得 ───▶ getInitialState ───▶ rowSelection初期値
                                              │
販売チャネル取得 ─────────────────────▶ DataTable表示
                                              │
チェックボックス変更 ───▶ onRowSelectionChange ───▶ form.sales_channels更新
      │
      └─(save)──▶ add/remove算出 ───▶ useUpdateStockLocationSalesChannels
                          │
                          ├─(success)──▶ toast.success + 詳細画面遷移
                          │
                          └─(error)──▶ toast.error
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| location-sales-channels.tsx | `packages/admin/dashboard/src/routes/locations/location-sales-channels/location-sales-channels.tsx` | ソース | 画面エントリーポイント |
| edit-sales-channels-form.tsx | `packages/admin/dashboard/src/routes/locations/location-sales-channels/components/edit-sales-channels-form/edit-sales-channels-form.tsx` | ソース | フォームコンポーネント |
| stock-locations.tsx | `packages/admin/dashboard/src/hooks/api/stock-locations.tsx` | ソース | ロケーションAPI |
| sales-channels.tsx | `packages/admin/dashboard/src/hooks/api/sales-channels.tsx` | ソース | 販売チャネルAPI |
