# 画面設計書 75-価格表設定画面

## 概要

本ドキュメントは、Medusa Admin Dashboardにおける「価格表設定画面」の画面設計書です。価格表（Price List）の有効期間と顧客グループルールを設定するためのドロワー形式の画面について記述します。

### 本画面の処理概要

この画面では、価格表の開始日時、終了日時、適用対象の顧客グループを設定・編集します。基本情報（タイトル、タイプ、説明等）は別画面（価格表編集画面）で編集します。

**業務上の目的・背景**：価格表の設定画面は、価格表の適用条件を管理するための重要な画面です。時限セールの開始・終了タイミングの設定や、特定の顧客グループ（VIP会員、法人顧客など）への限定適用を行う際に使用されます。これらの設定は運用中に変更されることが多いため、専用の画面として分離されています。

**画面へのアクセス方法**：価格表詳細画面のConfiguration Sectionの「Edit」ボタンをクリック、またはURL `/price-lists/{id}/configuration` に直接アクセスすることで表示されます。

**主要な操作・処理内容**：
1. 開始日時の設定・変更
2. 終了日時の設定・変更
3. 顧客グループの追加・削除
4. 変更内容の保存

**画面遷移**：
- 遷移元：価格表詳細画面
- 遷移先：保存成功時・キャンセル時に価格表詳細画面に戻る

**権限による表示制御**：認証済みユーザーのみアクセス可能です。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 53 | 価格リスト管理 | 主機能 | 価格表設定情報の更新 |

## 画面種別

ドロワー形式（RouteDrawer）

## URL/ルーティング

`/price-lists/:id/configuration`

## 入出力項目

### パスパラメータ（入力）

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|-----|------|------|
| id | string | Yes | 価格表のID |

### フォーム項目

| 項目名 | フィールド名 | 型 | 必須 | バリデーション | 説明 |
|--------|-------------|-----|------|---------------|------|
| 開始日時 | starts_at | Date | No | null可 | 価格表の有効開始日時 |
| 終了日時 | ends_at | Date | No | null可 | 価格表の有効終了日時 |
| 顧客グループ | customer_group_id | array | No | - | 適用対象の顧客グループ |

## 表示項目

### ヘッダー部

| 項目名 | コンポーネント | 説明 |
|--------|--------------|------|
| タイトル | Heading | "Edit configuration" |

### フォーム部

| 項目名 | コンポーネント | 説明 |
|--------|--------------|------|
| 開始日時 | DatePicker | 日時選択（分単位、任意） |
| 終了日時 | DatePicker | 日時選択（分単位、任意） |
| 顧客グループ | StackedDrawer | グループ選択モーダル |
| 選択済みグループ | Chip一覧 | 選択済みグループの表示・削除 |

### フッター部

| 項目名 | コンポーネント | 説明 |
|--------|--------------|------|
| キャンセルボタン | Button (secondary) | ドロワーを閉じる |
| 保存ボタン | Button (primary) | 変更を保存 |

## イベント仕様

### 1-開始日時変更

DatePickerで開始日時を選択します。null（未設定）も許可されます。granularity="minute"で分単位の選択が可能です。

### 2-終了日時変更

DatePickerで終了日時を選択します。null（未設定）も許可されます。granularity="minute"で分単位の選択が可能です。

### 3-顧客グループ選択モーダル表示

「Browse」ボタンまたは検索フィールドをクリックすると、StackedDrawerが開き、顧客グループを検索・選択できます。

### 4-顧客グループ追加

モーダル内でグループを選択し、確定すると選択済みグループに追加されます。既存の選択状態は保持されます。

### 5-顧客グループ削除

選択済みグループの横にある×ボタンをクリックすると、そのグループが選択から削除されます。

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

フォームをバリデーションし、`useUpdatePriceList`フックを使用してAPIを呼び出します。rulesオブジェクトに顧客グループIDを設定します。成功時はトーストを表示し、ドロワーを閉じます。

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

変更を破棄し、ドロワーを閉じて詳細画面に戻ります。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | price_list | SELECT | 価格表詳細の取得 |
| 画面表示 | customer_group | SELECT | 顧客グループ情報の取得 |
| 保存押下 | price_list | UPDATE | 価格表設定情報の更新 |

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

#### price_list

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | starts_at | フォーム入力値（ISO8601形式）またはnull | |
| UPDATE | ends_at | フォーム入力値（ISO8601形式）またはnull | |
| UPDATE | rules | `{ "customer.groups.id": [...ids] }` または既存rulesから削除 | |

## メッセージ仕様

| 種別 | 条件 | メッセージ |
|------|------|-----------|
| 成功 | 更新成功時 | Configuration successfully updated. |
| エラー | API呼び出し失敗時 | エラーメッセージをトースト表示 |

## 例外処理

| 状態 | 処理 |
|------|------|
| 価格表が存在しない場合 | エラーをスローし、エラーバウンダリーで捕捉 |
| 顧客グループ取得エラー | エラーをスローし、エラーバウンダリーで捕捉 |
| データ取得中 | フォームを表示しない（ready判定） |
| API エラー発生時 | エラーメッセージをトースト表示 |

## 備考

- 既存のrulesは保持され、customer.groups.idのみが更新される
- 顧客グループを全て削除した場合、rulesからcustomer.groups.idキーが削除される
- StackedDrawerを使用したネストドロワー形式
- useFieldArrayで顧客グループ配列を管理

---

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

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

### 推奨読解順序

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

ページコンポーネントとデータ取得処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | price-list-configuration.tsx | `packages/admin/dashboard/src/routes/price-lists/price-list-configuration/price-list-configuration.tsx` | RouteDrawer構成、データ取得 |

**主要処理フロー**:
1. **12行目**: useParamsでURLからid取得
2. **13行目**: usePriceListで価格表データ取得
3. **15-17行目**: rulesからcustomerGroupIds抽出
4. **19-29行目**: useCustomerGroupsで顧客グループ名を取得
5. **37-42行目**: ready判定（価格表・顧客グループ両方の取得完了）

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

設定フォームの実装を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | price-list-configuration-form.tsx | `packages/admin/dashboard/src/routes/price-lists/price-list-configuration/components/price-list-configuration-form/price-list-configuration-form.tsx` | フォーム構成、顧客グループ管理 |

**主要処理フロー**:
- **32-41行目**: PriceListConfigurationSchema - zodスキーマ
- **53-60行目**: useFormでフォーム初期化
- **62-66行目**: useFieldArrayで顧客グループ配列管理
- **68-89行目**: handleAddCustomerGroup - グループ追加・削除ロジック
- **93-117行目**: handleSubmit - rulesの構築とAPI呼び出し

#### Step 3: 顧客グループ選択を理解する

ネストドロワーでの顧客グループ選択を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | price-list-customer-group-rule-form.tsx | `packages/admin/dashboard/src/routes/price-lists/common/components/price-list-customer-group-rule-form/price-list-customer-group-rule-form.tsx` | 顧客グループ選択UI |

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

```
PriceListConfiguration (price-list-configuration.tsx)
    │
    ├─ usePriceList() - 価格表詳細取得
    │
    ├─ useCustomerGroups() - 顧客グループ取得
    │      └─ 条件: customerGroupIds存在時のみ
    │
    └─ RouteDrawer
           │
           ├─ RouteDrawer.Header
           │      └─ Heading ("Edit configuration")
           │
           └─ PriceListConfigurationForm
                  │
                  ├─ useForm()
                  │      └─ zodResolver(PriceListConfigurationSchema)
                  │
                  ├─ useFieldArray() - 顧客グループ配列
                  │
                  ├─ useUpdatePriceList()
                  │
                  ├─ KeyboundForm
                  │      │
                  │      ├─ DatePicker (starts_at)
                  │      │
                  │      ├─ DatePicker (ends_at)
                  │      │
                  │      └─ StackedDrawer (顧客グループ)
                  │             └─ PriceListCustomerGroupRuleForm
                  │
                  └─ RouteDrawer.Footer
```

### データフロー図

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

URL param (id) ──────▶ usePriceList() ──────▶ price_list
                                                   │
                                                   ▼
price_list.rules ──────▶ customerGroupIds抽出
                              │
                              ▼
customerGroupIds ──────▶ useCustomerGroups() ──────▶ customer_groups
                                                          │
                                                          ▼
                              ┌────────────────────────────────────┐
                              │ useForm() defaultValues            │
                              │   starts_at: price_list.starts_at  │
                              │   ends_at: price_list.ends_at      │
                              │   customer_group_id: groups        │
                              └────────────────────────────────────┘

Save押下 ──────▶ handleSubmit()
                    │
                    ├─▶ rulesオブジェクト構築
                    │      └─ { "customer.groups.id": [...ids] }
                    │
                    └─▶ useUpdatePriceList()
                           │
                           └─▶ sdk.admin.priceList.update()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| price-list-configuration.tsx | `packages/admin/dashboard/src/routes/price-lists/price-list-configuration/price-list-configuration.tsx` | ソース | ページコンポーネント |
| price-list-configuration-form.tsx | `packages/admin/dashboard/src/routes/price-lists/price-list-configuration/components/price-list-configuration-form/price-list-configuration-form.tsx` | ソース | 設定フォーム |
| price-list-customer-group-rule-form.tsx | `packages/admin/dashboard/src/routes/price-lists/common/components/price-list-customer-group-rule-form/price-list-customer-group-rule-form.tsx` | ソース | 顧客グループ選択 |
| price-lists.tsx | `packages/admin/dashboard/src/hooks/api/price-lists.tsx` | ソース | API呼び出しフック |
