# 機能設計書 51-在庫確認

## 概要

本ドキュメントは、Medusa ECプラットフォームにおける在庫確認機能の設計を記述する。在庫数量・利用可能数量の確認機能の詳細仕様を定義する。

### 本機能の処理概要

在庫確認機能は、商品の在庫状況をリアルタイムで確認するための機能である。在庫アイテムに対して、在庫数量（stocked_quantity）、予約数量（reserved_quantity）、利用可能数量（available_quantity）を取得し、在庫の十分性を確認できる。

**業務上の目的・背景**：ECサイトにおいて、顧客が商品を購入する際に在庫切れを防ぎ、正確な在庫情報を提供することは顧客満足度と売上に直結する。また、在庫管理者が適切な補充判断を行うためにも、リアルタイムな在庫状況の把握が必要である。

**機能の利用シーン**：
1. カートへの商品追加時に在庫の有無を確認
2. 注文確定時に必要数量が確保可能か検証
3. 管理画面での在庫状況の一覧表示
4. 在庫割当処理前の利用可能数量確認

**主要な処理内容**：
1. 在庫アイテムIDとロケーションIDを指定して在庫レベルを取得する
2. 利用可能数量（stocked_quantity - reserved_quantity）を計算して返却する
3. 指定した数量が確保可能かどうかを判定する（confirmInventory）
4. 複数ロケーションにまたがる在庫数量の合算計算を行う

**関連システム・外部連携**：在庫モジュールは注文モジュール、カートモジュール、フルフィルメントモジュールと連携し、在庫確認結果を基に各種処理の可否を判定する。

**権限による制御**：管理者は全ロケーションの在庫確認が可能。ストアフロントAPIでは販売チャネルに紐づくロケーションのみ確認可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 91 | 在庫一覧画面 | 補助機能 | 在庫数量・ステータスの表示 |
| 52 | 在庫割当画面 | API連携 | 利用可能在庫の確認 |
| 101 | 予約作成画面 | API連携 | 利用可能在庫の確認 |

## 機能種別

計算処理 / データ取得

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| inventoryItemId | string | Yes | 在庫アイテムID | 存在チェック、ilev_プレフィックス |
| locationIds | string[] | Yes | ロケーションIDの配列 | 空配列の場合は0を返却 |
| quantity | BigNumberInput | No | 確認したい数量（confirmInventory用） | 0以上の数値 |

### 入力データソース

- リクエストパラメータ（API経由）
- InventoryItemテーブル（在庫アイテムの存在確認）
- InventoryLevelテーブル（在庫レベルデータ）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| availableQuantity | BigNumber | 利用可能数量（retrieveAvailableQuantity） |
| stockedQuantity | BigNumber | 在庫数量（retrieveStockedQuantity） |
| reservedQuantity | BigNumber | 予約済み数量（retrieveReservedQuantity） |
| isAvailable | boolean | 指定数量が確保可能か（confirmInventory） |

### 出力先

- API レスポンス（JSON形式）
- 呼び出し元のワークフロー/サービス

## 処理フロー

### 処理シーケンス

```
1. 入力パラメータの検証
   └─ inventoryItemIdの存在確認、locationIdsの空チェック
2. 在庫アイテムの取得
   └─ inventoryItemService_.retrieveで在庫アイテムの存在を確認
3. 在庫レベルの取得
   └─ inventoryLevelService_.listで該当ロケーションの在庫レベルを取得
4. 数量の計算
   └─ 各ロケーションのstocked_quantity/reserved_quantityを合算
5. 結果の返却
   └─ BigNumber形式で計算結果を返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[inventoryItemIdの存在確認]
    B --> C{在庫アイテムが存在?}
    C -->|No| D[NOT_FOUNDエラー]
    C -->|Yes| E{locationIdsが空?}
    E -->|Yes| F[BigNumber(0)を返却]
    E -->|No| G[在庫レベルを取得]
    G --> H[数量を合算計算]
    H --> I[結果を返却]
    D --> J[終了]
    F --> J
    I --> J
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-51-01 | 利用可能数量計算 | available_quantity = stocked_quantity - reserved_quantity | 在庫レベル取得時に常時 |
| BR-51-02 | ロケーション空配列 | locationIdsが空配列の場合は0を返却 | retrieveAvailableQuantity, retrieveStockedQuantity呼び出し時 |
| BR-51-03 | 存在確認必須 | 在庫アイテムが存在しない場合はエラー | 全ての確認メソッド呼び出し時 |
| BR-51-04 | 複数ロケーション合算 | 複数ロケーション指定時は各数量を合算 | locationIdsに複数IDが含まれる場合 |

### 計算ロジック

```typescript
// 利用可能数量の計算
availableQuantity = sum(inventoryLevel.stocked_quantity) - sum(inventoryLevel.reserved_quantity)

// 在庫確認（confirmInventory）
isAvailable = availableQuantity >= requestedQuantity
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 在庫確認 | inventory_item | SELECT | 在庫アイテムの存在確認 |
| 在庫確認 | inventory_level | SELECT | 在庫レベルの取得 |

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

#### inventory_item

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id | WHERE id = :inventoryItemId | 存在確認のみ |

#### inventory_level

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | stocked_quantity, reserved_quantity | WHERE inventory_item_id = :inventoryItemId AND location_id IN (:locationIds) | 複数ロケーション対応 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| NOT_FOUND | MedusaError | 在庫アイテムが存在しない | 正しいIDを指定する |
| NOT_FOUND | MedusaError | 在庫レベルが存在しない | ロケーションに在庫レベルを作成する |

### リトライ仕様

在庫確認は読み取り専用操作のため、リトライは不要。一時的なDB接続エラーの場合はアプリケーション層で再試行可能。

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

在庫確認は読み取り専用操作であり、トランザクション管理は不要。@InjectManagerデコレータにより読み取り用コンテキストが注入される。

## パフォーマンス要件

- 単一アイテム確認: 100ms以内
- 複数ロケーション確認: 200ms以内
- インデックス: IDX_inventory_level_location_id_inventory_item_id を使用

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

- 認証: Admin APIは認証必須、Store APIはオプション
- 認可: 販売チャネルに紐づくロケーションのみ確認可能（Store API）
- 監査ログ: 在庫確認は監査ログ対象外（読み取り専用）

## 備考

- 在庫確認結果はキャッシュされない（リアルタイム性重視）
- 大量の在庫確認が必要な場合はバッチ処理を検討

---

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

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

### 推奨読解順序

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

まず、在庫レベルのデータモデルを理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | inventory-level.ts | `packages/modules/inventory/src/models/inventory-level.ts` | stocked_quantity, reserved_quantity, available_quantityの定義を確認 |

**読解のコツ**: Medusaのモデル定義はmodel.defineを使用する。bigNumber型は高精度な数値計算に対応。available_quantityはcomputed()で計算フィールドとして定義されている。

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

在庫確認のメインメソッドを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | inventory-module.ts | `packages/modules/inventory/src/services/inventory-module.ts` | retrieveAvailableQuantity, confirmInventoryメソッドの実装 |

**主要処理フロー**:
1. **1032-1058行目**: retrieveAvailableQuantity - 利用可能数量の取得
2. **1068-1095行目**: retrieveStockedQuantity - 在庫数量の取得
3. **1105-1132行目**: retrieveReservedQuantity - 予約済み数量の取得
4. **1142-1155行目**: confirmInventory - 在庫の十分性確認

#### Step 3: 在庫レベルサービスを理解する

数量計算の詳細実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | inventory-level.ts | `packages/modules/inventory/src/services/inventory-level.ts` | getAvailableQuantity, getReservedQuantity, retrieveStockedQuantityの実装 |

**主要処理フロー**:
- 各メソッドでロケーションIDに基づく在庫レベルの集約計算を実行

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

```
InventoryModuleService.retrieveAvailableQuantity()
    │
    ├─ inventoryItemService_.retrieve()
    │      └─ 在庫アイテムの存在確認
    │
    └─ inventoryLevelService_.getAvailableQuantity()
           └─ 在庫レベルの取得と計算

InventoryModuleService.confirmInventory()
    │
    └─ retrieveAvailableQuantity()
           └─ 利用可能数量を取得してquantityと比較
```

### データフロー図

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

inventoryItemId ───▶ inventoryItemService_    ───▶ 存在確認
        │            .retrieve()
        │
        ▼
locationIds    ───▶ inventoryLevelService_   ───▶ BigNumber
                    .getAvailableQuantity()        (利用可能数量)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| inventory-module.ts | `packages/modules/inventory/src/services/inventory-module.ts` | ソース | 在庫モジュールのメインサービス |
| inventory-level.ts | `packages/modules/inventory/src/services/inventory-level.ts` | ソース | 在庫レベル関連の処理 |
| inventory-level.ts | `packages/modules/inventory/src/models/inventory-level.ts` | ソース | 在庫レベルのデータモデル |
| inventory-item.ts | `packages/modules/inventory/src/models/inventory-item.ts` | ソース | 在庫アイテムのデータモデル |
| index.ts | `packages/modules/inventory/src/models/index.ts` | ソース | モデルのエクスポート |
