# 画面設計書 101-予約作成画面

## 概要

本ドキュメントは、Medusa Admin Dashboard における予約作成画面の設計仕様を定義する。

### 本画面の処理概要

予約作成画面は、在庫アイテムに対する新規予約を作成するためのモーダル形式の画面である。

**業務上の目的・背景**：ECサイト運営において、注文処理前に特定の在庫を確保（予約）することで、在庫の二重販売を防止し、顧客への確実な商品提供を実現する。特に人気商品や限定商品の在庫管理において、事前に在庫を確保することで、注文確定時の在庫切れを防ぐ重要な役割を果たす。

**画面へのアクセス方法**：予約一覧画面（/reservations）の「新規作成」ボタンをクリック、または在庫詳細画面からのリンク経由でアクセスする。URLパラメータ`item_id`が指定されている場合は、該当する在庫アイテムが事前選択された状態で画面が開く。

**主要な操作・処理内容**：
1. 在庫アイテムの選択（Comboboxによる検索・選択）
2. ロケーション（倉庫）の選択（選択した在庫アイテムに紐づくロケーションのみ表示）
3. 予約数量の入力（利用可能数量の範囲内で指定）
4. 説明（オプション）の入力
5. 予約の作成実行

**画面遷移**：
- 遷移元：予約一覧画面、在庫詳細画面
- 遷移先：作成成功時は予約詳細画面（/reservations/{id}）または在庫詳細画面（/inventory/{item_id}）

**権限による表示制御**：認証済みの管理者ユーザーのみアクセス可能。特定のロールによる制限は本画面では実装されていない。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 50 | 在庫予約管理 | 主機能 | 新規予約の作成 |
| 51 | 在庫確認 | API連携 | 利用可能在庫の確認 |

## 画面種別

登録（モーダル形式）

## URL/ルーティング

- パス: `/reservations/create`
- クエリパラメータ: `item_id`（オプション）- 事前選択する在庫アイテムID

## 入出力項目

| 項目名 | 項目ID | 入力/出力 | 必須 | データ型 | バリデーション | 備考 |
|--------|--------|----------|------|---------|---------------|------|
| 在庫アイテム | inventory_item_id | 入力 | 必須 | string | 最小1文字 | Comboboxで検索・選択 |
| ロケーション | location_id | 入力 | 必須 | string | 最小1文字 | 在庫アイテム選択後に有効化 |
| 数量 | quantity | 入力 | 必須 | number | 1以上、利用可能数量以下 | 在庫アイテム・ロケーション選択後に有効化 |
| 説明 | description | 入力 | 任意 | string | - | 予約の用途や理由を記載 |

## 表示項目

| 項目名 | データソース | 表示形式 | 備考 |
|--------|-------------|---------|------|
| タイトル | selectedInventoryItem.title / sku | テキスト | 在庫アイテム選択後に表示 |
| SKU | selectedInventoryItem.sku | テキスト | 在庫アイテム選択後に表示 |
| 在庫数 | selectedLocationLevel.stocked_quantity | テキスト | ロケーション選択後に表示 |
| 利用可能数 | selectedLocationLevel.available_quantity - quantity | テキスト | リアルタイム計算、予約数量入力に応じて更新 |

## イベント仕様

### 1-在庫アイテム選択

- トリガー：Comboboxで在庫アイテムを選択
- 処理内容：
  1. 選択した在庫アイテムに紐づくロケーションレベル情報を取得
  2. ロケーションComboboxに該当するロケーションを設定
  3. 在庫情報（タイトル、SKU、在庫数）を表示エリアに反映
- 状態変化：ロケーションComboboxが有効化される

### 2-ロケーション選択

- トリガー：ロケーションComboboxでロケーションを選択
- 処理内容：
  1. 選択したロケーションの在庫レベル情報を取得
  2. 在庫数、利用可能数を表示エリアに反映
- 状態変化：数量入力フィールドが有効化される

### 3-数量入力

- トリガー：数量フィールドへの入力
- 処理内容：
  1. 入力値をリアルタイムで監視
  2. 利用可能数を動的に再計算（available_quantity - 入力数量）
- 状態変化：利用可能数の表示が更新される

### 4-作成ボタン押下

- トリガー：「作成」ボタンをクリック
- 処理内容：
  1. フォームバリデーション実行
  2. 利用可能数量のチェック（available_quantity が0の場合エラー）
  3. 数量範囲チェック（1 <= quantity <= available_quantity）
  4. バリデーション成功時、予約作成APIを呼び出し
  5. 成功時：トースト通知を表示し、遷移先画面へリダイレクト
  6. 失敗時：エラートースト通知を表示
- 画面遷移：
  - item_idパラメータあり：/inventory/{item_id}
  - item_idパラメータなし：/reservations/{新規作成された予約ID}

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

- トリガー：「キャンセル」ボタンをクリック
- 処理内容：モーダルを閉じる
- 画面遷移：元の画面に戻る

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 作成ボタン押下 | reservation | INSERT | 新規予約レコードを作成 |
| 作成ボタン押下 | inventory_level | UPDATE | reserved_quantity を増加 |

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

#### reservation

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | inventory_item_id | フォーム入力値 | 在庫アイテムID |
| INSERT | location_id | フォーム入力値 | ロケーションID |
| INSERT | quantity | フォーム入力値 | 予約数量 |
| INSERT | description | フォーム入力値（オプション） | 説明 |

#### inventory_level

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | reserved_quantity | 現在値 + 予約数量 | 予約作成により増加 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|---------|
| inventory.reservation.successToast | 成功 | 予約が正常に作成されました | 予約作成成功時 |
| inventory.reservation.errors.noAvaliableQuantity | エラー | 利用可能な在庫がありません | 利用可能数量が0の場合 |
| inventory.reservation.errors.quantityOutOfRange | エラー | 数量は1から{max}の範囲で指定してください | 数量が範囲外の場合 |
| (APIエラー) | エラー | エラーメッセージ（API応答） | API呼び出し失敗時 |

## 例外処理

| 例外条件 | 処理内容 | ユーザーへの通知 |
|---------|---------|----------------|
| 在庫アイテムが見つからない | Comboboxに表示されない | - |
| ロケーションが見つからない | Comboboxに表示されない | - |
| 利用可能数量が0 | フォーム送信をブロック | エラーメッセージ表示 |
| 数量が範囲外 | フォーム送信をブロック | エラーメッセージ表示 |
| API通信エラー | 処理を中断 | エラートースト表示 |

## 備考

- モーダル形式のためRouteFocusModalコンポーネントを使用
- zodによるスキーマバリデーションを実装
- react-hook-formによるフォーム管理
- 在庫アイテム検索時は非同期でAPIを呼び出し
- ロケーションは在庫アイテムのlocation_levelsに紐づくもののみ表示

---

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

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

### 推奨読解順序

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

まず、予約作成に関するデータ構造とバリデーションスキーマを理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | reservation-create-from.tsx | `packages/admin/dashboard/src/routes/reservations/reservation-create/components/reservation-create-from/reservation-create-from.tsx` | 21-26行目のCreateReservationSchemaでフォームのバリデーションルールを確認 |

**読解のコツ**: zodライブラリを使用したスキーマ定義。z.object()でオブジェクト構造、z.string().min(1)で必須文字列、z.number().min(1)で1以上の数値を定義。

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

処理の起点となるコンポーネントを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | reservation-create.tsx | `packages/admin/dashboard/src/routes/reservations/reservation-create/reservation-create.tsx` | URLパラメータからitem_idを取得し、ReservationCreateFormに渡す流れを確認 |

**主要処理フロー**:
1. **7-9行目**: useSearchParamsでURLパラメータを取得
2. **11-14行目**: RouteFocusModalでモーダル表示、ReservationCreateFormをレンダリング

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

フォームの実装詳細を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | reservation-create-from.tsx | `packages/admin/dashboard/src/routes/reservations/reservation-create/components/reservation-create-from/reservation-create-from.tsx` | フォーム全体の実装、状態管理、バリデーション、API呼び出しを確認 |

**主要処理フロー**:
- **54-62行目**: useFormでフォーム初期化、zodResolverでバリデーション設定
- **64-66行目**: useInventoryItemsで在庫アイテム一覧を取得
- **68-76行目**: 選択した在庫アイテムとロケーションレベルの取得
- **80-90行目**: useStockLocationsでロケーション一覧を取得
- **92行目**: useCreateReservationItemで予約作成mutation取得
- **94-133行目**: handleSubmitで数量バリデーションとAPI呼び出し

#### Step 4: API hooks を理解する

APIとの通信処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | reservations.tsx | `packages/admin/dashboard/src/hooks/api/reservations.tsx` | 96-120行目のuseCreateReservationItemで予約作成APIの呼び出し方法とキャッシュ無効化を確認 |

**主要処理フロー**:
- **104-105行目**: sdk.admin.reservation.createでAPI呼び出し
- **106-116行目**: 成功時のキャッシュ無効化（予約一覧、在庫詳細、在庫レベル）

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

```
ReservationCreate (reservation-create.tsx)
    │
    └─ ReservationCreateForm (reservation-create-from.tsx)
           │
           ├─ useInventoryItems (inventory.tsx)
           │      └─ sdk.admin.inventoryItem.list
           │
           ├─ useStockLocations (stock-locations.tsx)
           │      └─ sdk.admin.stockLocation.list
           │
           └─ useCreateReservationItem (reservations.tsx)
                  └─ sdk.admin.reservation.create
```

### データフロー図

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

在庫アイテム選択 ───▶ useInventoryItems ───▶ 在庫情報表示
         │
         ▼
ロケーション選択 ───▶ useStockLocations ───▶ ロケーション一覧
         │
         ▼
数量入力 ───────────▶ バリデーション ────▶ 利用可能数計算・表示
         │
         ▼
作成ボタン ─────────▶ useCreateReservationItem ───▶ 予約詳細画面/在庫詳細画面
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| reservation-create.tsx | `packages/admin/dashboard/src/routes/reservations/reservation-create/reservation-create.tsx` | ソース | エントリーポイント、URLパラメータ処理 |
| reservation-create-from.tsx | `packages/admin/dashboard/src/routes/reservations/reservation-create/components/reservation-create-from/reservation-create-from.tsx` | ソース | フォーム実装、バリデーション、API呼び出し |
| reservations.tsx | `packages/admin/dashboard/src/hooks/api/reservations.tsx` | ソース | 予約関連API hooks |
| inventory.tsx | `packages/admin/dashboard/src/hooks/api/inventory.tsx` | ソース | 在庫アイテムAPI hooks |
| stock-locations.tsx | `packages/admin/dashboard/src/hooks/api/stock-locations.tsx` | ソース | ロケーションAPI hooks |
| index.ts | `packages/admin/dashboard/src/routes/reservations/reservation-create/index.ts` | ソース | エクスポート定義 |
