# 画面設計書 140-配送オプション編集画面

## 概要

本ドキュメントは、Medusa Admin Dashboardにおける配送オプション編集画面の設計仕様を定義するものである。

### 本画面の処理概要

配送オプション編集画面は、既存の配送オプション（配送方法）の基本情報を編集するための画面である。

**業務上の目的・背景**：ECサイト運営において、配送オプションの名称、料金タイプ、配送プロファイル、ストア表示設定などを後から変更する必要が生じることがある。例えば、「通常配送」を「標準配送（3-5営業日）」に名称変更したり、料金体系を固定料金から計算式に変更するケースに対応する。なお、フルフィルメントプロバイダーの変更は本画面ではできず、読み取り専用で表示される。価格の変更は別画面で行う。

**画面へのアクセス方法**：ロケーション詳細画面 > 配送オプションのアクションメニュー > 「Edit Details」をクリックすることでアクセスできる。URLパスは `/settings/locations/{location_id}/shipping-option/{so_id}/edit`。

**主要な操作・処理内容**：
1. 料金タイプの変更（固定料金/計算式）※Pickup以外
2. 配送オプション名の編集
3. 配送プロファイルの変更
4. 配送オプションタイプの変更
5. ストア表示設定の変更
6. 「保存」ボタンで変更を反映

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

**権限による表示制御**：管理者権限を持つユーザーのみがこの画面にアクセスし、配送オプションを編集できる。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 43 | 配送オプション管理 | 主機能 | 配送オプションの編集 |

## 画面種別

編集画面（ドロワー形式）

## URL/ルーティング

- パス: `/settings/locations/:location_id/shipping-option/:so_id/edit`
- コンポーネント: `LocationServiceZoneShippingOptionEdit`
- ルートファイル: `packages/admin/dashboard/src/routes/locations/location-service-zone-shipping-option-edit/location-service-zone-shipping-option-edit.tsx`

## 入出力項目

| 項目名 | 項目ID | 入出力 | 型 | 必須 | バリデーション | 説明 |
|--------|--------|--------|-----|------|---------------|------|
| 料金タイプ | price_type | 入力 | enum | Yes | - | `flat_rate`または`calculated` |
| 配送オプション名 | name | 入力 | string | Yes | 1文字以上 | 配送オプションの名称 |
| 配送プロファイル | shipping_profile_id | 入力 | string | Yes | - | 配送プロファイルのID |
| 配送オプションタイプ | shipping_option_type_id | 入力 | string | Yes | - | 配送オプションタイプのID |
| フルフィルメントプロバイダー | provider_id | 表示 | string | - | - | プロバイダーID（読み取り専用） |
| ストア表示 | enabled_in_store | 入力 | boolean | No | - | ストアで表示するかどうか |

## 表示項目

| 項目名 | 説明 |
|--------|------|
| ヘッダータイトル | タイプに応じた動的タイトル（「Edit Shipping Option」/「Edit Pickup Option」） |

### 料金タイプ選択（Shipping時のみ）

| 項目名 | 説明 |
|--------|------|
| 固定料金 | `flat_rate` - 通貨/リージョン別に固定料金を設定 |
| 計算式 | `calculated` - プロバイダーの計算ロジックを使用 |

### フルフィルメントプロバイダー（読み取り専用）

| 項目名 | 説明 |
|--------|------|
| プロバイダー名 | フォーマットされたプロバイダー名とフルフィルメントオプションID |

## イベント仕様

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

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

**処理フロー**:
1. フォームバリデーションを実行
2. 既存のrulesを取得し、enabled_in_storeルールを更新
3. `useUpdateShippingOptions`フックを通じてAPIを呼び出し
4. APIリクエスト: `POST /admin/shipping-options/{so_id}`
5. 成功時: トースト通知を表示し、ロケーション詳細画面へ遷移
6. 失敗時: エラーメッセージをトースト通知で表示

**送信データ**:
```typescript
{
  name: string,
  price_type: "flat_rate" | "calculated",
  shipping_profile_id: string,
  rules: Array<{
    id?: string,
    attribute: string,
    operator: string,
    value: string
  }>,
  type_id: string
}
```

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

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

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

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 保存ボタン押下 | shipping_option | UPDATE | 配送オプションレコードの更新 |
| 保存ボタン押下 | shipping_option_rule | UPDATE/INSERT | ルールの更新または追加 |

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

#### shipping_option

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | name | フォーム入力値 | 配送オプション名 |
| UPDATE | price_type | フォーム入力値 | `flat_rate`または`calculated` |
| UPDATE | shipping_profile_id | フォーム入力値 | 外部キー |
| UPDATE | type_id | フォーム入力値 | 配送オプションタイプ |
| UPDATE | updated_at | システム自動設定 | 更新日時 |

#### shipping_option_rule

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | value | `true`または`false` | enabled_in_storeルールの値 |
| INSERT | attribute | `enabled_in_store` | ルールが存在しない場合に追加 |
| INSERT | operator | `eq` | ルールが存在しない場合に追加 |
| INSERT | value | `true`または`false` | ルールが存在しない場合に追加 |

## メッセージ仕様

| メッセージ種別 | メッセージキー | 表示条件 | 表示内容 |
|--------------|---------------|----------|---------|
| 成功 | stockLocations.shippingOptions.edit.successToast | 配送オプション更新成功時 | 「{name} updated successfully」 |
| エラー | - | API呼び出し失敗時 | APIから返却されたエラーメッセージ |
| バリデーション | - | 必須項目未入力時 | 該当フィールドにエラー表示 |

## 例外処理

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

## 備考

- 画面はドロワー（`RouteDrawer`）として実装されている
- フォームは`react-hook-form`と`zod`によるバリデーションを使用
- フルフィルメントプロバイダーは編集不可（読み取り専用で表示）
- プロバイダー変更が必要な場合は配送オプションの再作成が必要
- Pickupタイプの場合、料金タイプ選択は非表示
- `isOptionEnabledInStore`関数で既存のenabled_in_storeルール値を取得
- rulesの更新時、既存ルールのIDを保持して更新
- enabled_in_storeルールが存在しない場合は新規追加

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | edit-shipping-option-form.tsx | `packages/admin/dashboard/src/routes/locations/location-service-zone-shipping-option-edit/components/edit-region-form/edit-shipping-option-form.tsx` | L31-38: `EditShippingOptionSchema`でフォームスキーマを定義 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | location-service-zone-shipping-option-edit.tsx | `packages/admin/dashboard/src/routes/locations/location-service-zone-shipping-option-edit/location-service-zone-shipping-option-edit.tsx` | L10-59: URLパラメータ取得、配送オプションデータフェッチ、タイプ判定 |

**主要処理フロー**:
1. **L13**: `useParams`でURLパラメータ（location_id, so_id）を取得
2. **L15-19**: `useShippingOptions`で配送オプションデータを取得（service_zone.fulfillment_set.typeを含む）
3. **L21**: so_idに一致する配送オプションを検索
4. **L23-28**: 配送オプションが見つからない場合は404エラー
5. **L34-36**: Pickupタイプかどうかを判定
6. **L48-55**: フォームコンポーネントに必要なプロパティを渡す

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | edit-shipping-option-form.tsx | `packages/admin/dashboard/src/routes/locations/location-service-zone-shipping-option-edit/components/edit-region-form/edit-shipping-option-form.tsx` | L40-314: フォーム初期化、API呼び出し |

**主要処理フロー**:
- **L50-59**: `useComboboxData`で配送プロファイル一覧を取得（デフォルト値設定あり）
- **L61-69**: `useComboboxData`で配送オプションタイプ一覧を取得
- **L71-81**: `useForm`でフォーム状態を初期化、既存データをデフォルト値に設定
- **L75**: `isOptionEnabledInStore`で既存のenabled_in_storeルール値を取得
- **L83-85**: `useUpdateShippingOptions`フックでAPI呼び出し関数を取得
- **L87-127**: `handleSubmit`でrulesを構築しAPI呼び出し
- **L88-90**: 既存rulesをコピー
- **L92-103**: enabled_in_storeルールを更新または追加

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

```
LocationServiceZoneShippingOptionEdit (location-service-zone-shipping-option-edit.tsx)
    │
    ├─ useShippingOptions (配送オプションデータ取得)
    │      └─ fields: "+service_zone.fulfillment_set.type"
    │
    └─ EditShippingOptionForm (edit-shipping-option-form.tsx)
           │
           ├─ useForm (react-hook-form)
           │      └─ zodResolver (EditShippingOptionSchema)
           │
           ├─ useComboboxData (shippingProfiles)
           │
           ├─ useComboboxData (shippingOptionTypes)
           │
           ├─ isOptionEnabledInStore (既存ルール値取得)
           │
           └─ useUpdateShippingOptions
                  └─ POST /admin/shipping-options/{so_id}
```

### データフロー図

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

配送オプション取得 ───▶ useShippingOptions ───▶ フォーム初期値設定
                                                     │
                                          ┌──────────┤
                                          ▼          ▼
                               既存rules取得   enabled_in_store取得
                                          │          │
                                          └────┬─────┘
                                               ▼
フォーム編集 ──────────▶ zodバリデーション ───▶ バリデーションエラー表示
      │
      └─(save)──▶ rules構築（enabled_in_store更新/追加）
                          │
                          ▼
               useUpdateShippingOptions
                          │
                          ├─(success)──▶ toast.success + 詳細画面遷移
                          │
                          └─(error)──▶ toast.error
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| location-service-zone-shipping-option-edit.tsx | `packages/admin/dashboard/src/routes/locations/location-service-zone-shipping-option-edit/location-service-zone-shipping-option-edit.tsx` | ソース | 画面エントリーポイント |
| edit-shipping-option-form.tsx | `packages/admin/dashboard/src/routes/locations/location-service-zone-shipping-option-edit/components/edit-region-form/edit-shipping-option-form.tsx` | ソース | フォームコンポーネント |
| shipping-options.tsx | `packages/admin/dashboard/src/hooks/api/shipping-options.tsx` | ソース | 配送オプションAPI |
| shipping-options.ts | `packages/admin/dashboard/src/lib/shipping-options.ts` | ソース | ユーティリティ関数（isOptionEnabledInStore等） |
| constants.ts | `packages/admin/dashboard/src/routes/locations/common/constants.ts` | ソース | 定数定義（ShippingOptionPriceType等） |
