# 画面設計書 135-フルフィルメントプロバイダー設定画面

## 概要

本ドキュメントは、Medusa Admin Dashboardにおけるロケーションのフルフィルメントプロバイダー設定画面の設計仕様を定義するものである。

### 本画面の処理概要

フルフィルメントプロバイダー設定画面は、特定のロケーションで利用可能なフルフィルメントプロバイダー（配送業者、配送サービス）を選択・管理するための画面である。

**業務上の目的・背景**：ECサイト運営において、各ロケーション（倉庫、店舗）で利用可能な配送プロバイダーは異なる場合がある。例えば、特定の倉庫からは国際配送が可能だが、別の倉庫からは国内配送のみという状況がある。この画面でロケーションごとに利用可能なプロバイダーを設定することで、配送オプション作成時に適切なプロバイダーのみが選択肢として表示される。

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

**主要な操作・処理内容**：
1. 有効なフルフィルメントプロバイダーの一覧を表示
2. チェックボックスで利用するプロバイダーを選択
3. 検索・フィルタ機能でプロバイダーを絞り込み
4. 「保存」ボタンで設定を更新
5. 「キャンセル」ボタンで操作を中断

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

**権限による表示制御**：管理者権限を持つユーザーのみがこの画面にアクセスし、フルフィルメントプロバイダーの設定を変更できる。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 46 | 配送プロバイダー管理 | 主機能 | フルフィルメントプロバイダーの設定 |

## 画面種別

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

## URL/ルーティング

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

## 入出力項目

| 項目名 | 項目ID | 入出力 | 型 | 必須 | バリデーション | 説明 |
|--------|--------|--------|-----|------|---------------|------|
| プロバイダー選択 | fulfillment_providers | 入力 | string[] | No | - | 選択されたプロバイダーIDの配列 |

## 表示項目

### プロバイダー一覧テーブル

| 項目名 | 説明 |
|--------|------|
| チェックボックス | プロバイダーの選択状態 |
| プロバイダーID | フルフィルメントプロバイダーのID |
| プロバイダー名 | フォーマットされたプロバイダー名 |

### その他

| 項目名 | 説明 |
|--------|------|
| 検索ボックス | プロバイダー名での検索（autofocus） |
| フィルター | 日付によるフィルタリング |
| ページネーション | 50件ずつ表示 |
| ソート | IDによるソート |

## イベント仕様

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

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

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

**送信データ**:
```typescript
{
  add: string[],    // 新たに紐付けるプロバイダーID
  remove: string[]  // 紐付けを解除するプロバイダーID
}
```

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

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

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

### 3-行選択変更

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

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

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

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

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

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

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

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

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

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

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

## メッセージ仕様

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

## 例外処理

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

## 備考

- 画面はフルページモーダル（`RouteFocusModal`）として実装されている
- データテーブル（`_DataTable`）コンポーネントを使用
- ページサイズは50件（`PAGE_SIZE = 50`）
- 有効なプロバイダーのみ表示（`is_enabled: true`）
- 初期選択状態は既存の紐付け情報から自動設定
- 検索ボックスは自動フォーカス（`search="autofocus"`）
- `placeholderData: keepPreviousData`でページ切り替え時のちらつきを防止

---

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

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

### 推奨読解順序

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

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

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

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

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

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

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

**主要処理フロー**:
- **L44-50**: `useForm`でフォーム状態を初期化
- **L54-58**: 既存の紐付けから初期選択状態を設定
- **L63-72**: `handleRowSelectionChange`で選択変更時にフォーム値を更新
- **L104-124**: `handleSubmit`で新規追加・削除するプロバイダーを算出してAPI呼び出し

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

```
LocationFulfillmentProviders (location-fulfillment-providers.tsx)
    │
    ├─ useStockLocation (既存紐付け取得)
    │
    └─ LocationEditFulfillmentProvidersForm (edit-fulfillment-providers-form.tsx)
           │
           ├─ useForm (react-hook-form)
           │
           ├─ useFulfillmentProviders (プロバイダー一覧取得)
           │
           ├─ useDataTable (_DataTable用)
           │
           └─ useUpdateStockLocationFulfillmentProviders
                  └─ POST /admin/stock-locations/{id}/fulfillment-providers
```

### データフロー図

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

既存紐付け取得 ───▶ initialState設定 ───▶ rowSelection初期値
                                              │
プロバイダー取得 ─────────────────────▶ _DataTable表示 (is_enabled: true)
                                              │
チェックボックス変更 ───▶ handleRowSelectionChange ───▶ form更新
      │
      └─(save)──▶ add/remove算出 ───▶ useUpdateStockLocationFulfillmentProviders
                          │
                          ├─(success)──▶ toast.success + 詳細画面遷移
                          │
                          └─(error)──▶ toast.error
```

### 関連ファイル一覧

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