# 機能設計書 79-在庫ロケーションCRUD

## 概要

本ドキュメントは、Medusaコマースプラットフォームにおける倉庫・店舗等の在庫ロケーションの作成・取得・更新・削除機能について記載する。

### 本機能の処理概要

在庫ロケーションCRUD機能は、商品在庫を管理する物理的な場所（倉庫、店舗、配送センター等）の情報を管理する機能である。各ロケーションには名称、メタデータ、住所情報を設定でき、在庫レベルやフルフィルメントセットとの紐付けが可能である。

**業務上の目的・背景**：
ECサイトでは、複数の倉庫や店舗から商品を出荷することが一般的である。各ロケーションの在庫状況を正確に把握し、適切な場所から出荷することで、配送コストの最適化や在庫回転率の向上が実現できる。本機能は、このようなマルチロケーション在庫管理の基盤を提供する。

**機能の利用シーン**：
- 新規倉庫の登録
- 店舗在庫拠点の追加
- 配送センターの情報更新
- 閉鎖ロケーションの削除
- ロケーション情報の一覧表示・検索

**主要な処理内容**：
1. 在庫ロケーションの作成
2. 在庫ロケーションの一覧取得・詳細取得
3. 在庫ロケーションの更新
4. 在庫ロケーションの削除

**関連システム・外部連携**：
- 在庫モジュール（Inventory Module）との連携
- フルフィルメントモジュールとの連携
- 販売チャネルとの紐付け

**権限による制御**：
- 管理者権限を持つユーザーのみ操作可能
- APIキー認証によるアクセス制御

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 96 | 在庫ロケーション管理画面 | API連携 | ロケーション一覧の取得 |
| 130 | ロケーション一覧画面 | 主画面 | 在庫ロケーション一覧の取得・表示 |
| 131 | ロケーション作成画面 | 主画面 | 新規ロケーションの作成 |
| 132 | ロケーション詳細画面 | 主画面 | ロケーション詳細の表示 |
| 133 | ロケーション編集画面 | 主画面 | ロケーション情報の編集 |

## 機能種別

CRUD操作

## 入力仕様

### 入力パラメータ

#### 作成 (POST /admin/stock-locations)

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | string | Yes | ロケーション名 | 空文字不可 |
| address | object | No | 住所情報 | - |
| metadata | object | No | カスタムメタデータ | - |

#### 更新 (POST /admin/stock-locations/{id})

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | string | No | ロケーション名 | 空文字不可 |
| address | object | No | 住所情報 | - |
| address_id | string | No | 住所ID | 有効なID |
| metadata | object | No | カスタムメタデータ | - |

#### 一覧取得 (GET /admin/stock-locations)

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| q | string | No | 検索クエリ | - |
| id | string[] | No | ID配列フィルタ | - |
| name | string | No | 名前フィルタ | - |
| limit | number | No | 取得件数 | 正の整数 |
| offset | number | No | オフセット | 0以上の整数 |

### 入力データソース

- 管理画面からのREST API呼び出し
- POST /admin/stock-locations（作成）
- GET /admin/stock-locations（一覧）
- GET /admin/stock-locations/{id}（詳細）
- POST /admin/stock-locations/{id}（更新）
- DELETE /admin/stock-locations/{id}（削除）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| stock_location | StockLocationDTO | 在庫ロケーション情報 |
| stock_location.id | string | ロケーションID（sloc_プレフィックス） |
| stock_location.name | string | ロケーション名 |
| stock_location.address | AddressDTO | 住所情報 |
| stock_location.metadata | object | メタデータ |
| stock_location.created_at | Date | 作成日時 |
| stock_location.updated_at | Date | 更新日時 |

### 出力先

- REST APIレスポンス（JSON形式）
- stock_locationテーブル

## 処理フロー

### 処理シーケンス

```
【作成処理】
1. APIリクエスト受信
   └─ POST /admin/stock-locations
2. バリデーション
   └─ name必須チェック
3. ワークフロー実行
   └─ createStockLocationsWorkflow
4. ロケーション作成
   └─ createStockLocationsStep
5. 作成結果取得
   └─ refetchStockLocation
6. レスポンス返却

【更新処理】
1. APIリクエスト受信
   └─ POST /admin/stock-locations/{id}
2. ワークフロー実行
   └─ updateStockLocationsWorkflow
3. ロケーション更新
   └─ updateStockLocationsStep
4. 更新結果取得
5. レスポンス返却

【削除処理】
1. APIリクエスト受信
   └─ DELETE /admin/stock-locations/{id}
2. ワークフロー実行
   └─ deleteStockLocationsWorkflow
3. ロケーション削除
4. 成功レスポンス返却
```

### フローチャート

```mermaid
flowchart TD
    A[APIリクエスト] --> B{操作種別}
    B -->|作成| C[バリデーション]
    B -->|取得| D[クエリ実行]
    B -->|更新| E[更新ワークフロー]
    B -->|削除| F[削除ワークフロー]

    C --> G{name存在?}
    G -->|No| H[エラー]
    G -->|Yes| I[createStockLocationsWorkflow]
    I --> J[createStockLocationsStep]
    J --> K[refetchStockLocation]
    K --> L[レスポンス]

    D --> M[remoteQuery]
    M --> L

    E --> N[updateStockLocationsWorkflow]
    N --> O[updateStockLocationsStep]
    O --> K

    F --> P[deleteStockLocationsWorkflow]
    P --> Q[deleteStockLocationsStep]
    Q --> R[削除成功レスポンス]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-79-01 | 名前必須 | ロケーション名は必須 | 作成時 |
| BR-79-02 | 住所任意 | 住所情報は任意 | 作成・更新時 |
| BR-79-03 | メタデータ自由 | カスタムメタデータを自由に設定可能 | 作成・更新時 |
| BR-79-04 | 検索可能 | name, addressフィールドは検索可能 | 検索時 |

### 計算ロジック

該当なし

## データベース操作仕様

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 作成 | stock_location | INSERT | ロケーション作成 |
| 作成 | stock_location_address | INSERT | 住所作成（オプション） |
| 取得 | stock_location | SELECT | ロケーション取得 |
| 更新 | stock_location | UPDATE | ロケーション更新 |
| 削除 | stock_location | DELETE | ロケーション削除 |

### テーブル別操作詳細

#### stock_location

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | id | 自動生成（sloc_プレフィックス） | - |
| INSERT | name | 入力値 | 検索可能 |
| INSERT | metadata | 入力値（JSON） | - |
| INSERT | address_id | 作成されたaddress_id | オプション |
| UPDATE | name | 入力値 | - |
| UPDATE | metadata | 入力値 | - |
| DELETE | - | id条件 | - |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 400 | INVALID_DATA | 必須項目不足 | 必須項目を入力 |
| 404 | NOT_FOUND | 存在しないID | 正しいIDを指定 |
| 401 | UNAUTHORIZED | 認証失敗 | 有効なトークンを使用 |

### リトライ仕様

トランザクション失敗時は自動ロールバック。クライアント側でリトライ。

## トランザクション仕様

- 各操作はワークフロー内で@InjectTransactionManagerを使用
- 住所作成を含む場合も単一トランザクション
- エラー発生時はロールバック

## パフォーマンス要件

- 一覧取得時のページネーション必須
- nameフィールドに検索インデックス

## セキュリティ考慮事項

- 管理者APIのため認証必須
- 住所情報の適切な取り扱い

## 備考

- 住所情報は別モデル（StockLocationAddress）で管理
- フルフィルメントセットとの連携機能あり
- 販売チャネルとの紐付け機能あり

---

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

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

### 推奨読解順序

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

在庫ロケーションのデータモデルを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | stock-location.ts | `packages/modules/stock-location/src/models/stock-location.ts` | ロケーションモデル |
| 1-2 | stock-location-address.ts | `packages/modules/stock-location/src/models/stock-location-address.ts` | 住所モデル |

**読解のコツ**:
- idプレフィックス "sloc_" を確認
- addressとのbelongsTo関係（nullable）
- searchable設定されたフィールドを確認

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

API呼び出しの起点を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | route.ts | `packages/medusa/src/api/admin/stock-locations/route.ts` | POST/GETハンドラ |
| 2-2 | [id]/route.ts | `packages/medusa/src/api/admin/stock-locations/[id]/route.ts` | 詳細・更新・削除ハンドラ |

**主要処理フロー**:
1. **15-33行目（route.ts）**: POST - createStockLocationsWorkflow呼び出し
2. **35-58行目（route.ts）**: GET - remoteQueryで一覧取得
3. **17-41行目（[id]/route.ts）**: POST - updateStockLocationsWorkflow
4. **65-80行目（[id]/route.ts）**: DELETE - deleteStockLocationsWorkflow

#### Step 3: ワークフローを理解する

CRUD処理のビジネスロジックを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | create-stock-locations.ts | `packages/core/core-flows/src/stock-location/workflows/create-stock-locations.ts` | 作成ワークフロー |
| 3-2 | update-stock-locations.ts | `packages/core/core-flows/src/stock-location/workflows/update-stock-locations.ts` | 更新ワークフロー |
| 3-3 | delete-stock-locations.ts | `packages/core/core-flows/src/stock-location/workflows/delete-stock-locations.ts` | 削除ワークフロー |

**主要処理フロー**:
- **45-58行目（create）**: ワークフロー定義、createStockLocationsステップ呼び出し
- **50-51行目**: stockLocationsCreatedフック

#### Step 4: サービス層を理解する

モジュールサービスの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | stock-location-module.ts | `packages/modules/stock-location/src/services/stock-location-module.ts` | モジュールサービス |

**主要処理フロー**:
- **80-110行目**: createStockLocations - ロケーション作成
- **174-234行目**: updateStockLocations - ロケーション更新
- **236-274行目**: updateStockLocationAddresses - 住所更新

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

```
POST /admin/stock-locations (route.ts)
    │
    └─ createStockLocationsWorkflow
           │
           ├─ createStockLocations (step)
           │      └─ StockLocationModuleService.createStockLocations()
           │             └─ stockLocationService_.create()
           │
           └─ createHook("stockLocationsCreated")

POST /admin/stock-locations/{id} (route.ts)
    │
    └─ updateStockLocationsWorkflow
           │
           └─ updateStockLocationsStep
                  └─ StockLocationModuleService.updateStockLocations()

DELETE /admin/stock-locations/{id} (route.ts)
    │
    └─ deleteStockLocationsWorkflow
           │
           └─ deleteStockLocationsStep
                  └─ StockLocationModuleService.deleteStockLocations()
```

### データフロー図

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

{                         createStockLocationsWorkflow
  name: "Tokyo Warehouse",  │
  address: {                ├─> バリデーション                 {
    address_1: "..."        │                                   stock_location: {
  }                         ├─> createStockLocationsStep         id: "sloc_xxx",
}                           │   StockLocationModuleService        name: "Tokyo...",
                            │   .createStockLocations()           address: {...}
                            │                                   }
                            └─> refetchStockLocation          }
                                remoteQuery
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| route.ts | `packages/medusa/src/api/admin/stock-locations/route.ts` | ソース | 一覧・作成エンドポイント |
| [id]/route.ts | `packages/medusa/src/api/admin/stock-locations/[id]/route.ts` | ソース | 詳細・更新・削除エンドポイント |
| create-stock-locations.ts | `packages/core/core-flows/src/stock-location/workflows/create-stock-locations.ts` | ソース | 作成ワークフロー |
| update-stock-locations.ts | `packages/core/core-flows/src/stock-location/workflows/update-stock-locations.ts` | ソース | 更新ワークフロー |
| delete-stock-locations.ts | `packages/core/core-flows/src/stock-location/workflows/delete-stock-locations.ts` | ソース | 削除ワークフロー |
| stock-location-module.ts | `packages/modules/stock-location/src/services/stock-location-module.ts` | ソース | モジュールサービス |
| stock-location.ts | `packages/modules/stock-location/src/models/stock-location.ts` | ソース | ロケーションモデル |
| stock-location-address.ts | `packages/modules/stock-location/src/models/stock-location-address.ts` | ソース | 住所モデル |
| validators.ts | `packages/medusa/src/api/admin/stock-locations/validators.ts` | ソース | バリデーション定義 |
| helpers.ts | `packages/medusa/src/api/admin/stock-locations/helpers.ts` | ソース | refetchStockLocationヘルパー |
