# 機能設計書 37-在庫調整

## 概要

本ドキュメントは、在庫管理モジュールにおける在庫調整機能の設計仕様を定義するものです。棚卸や在庫差異の修正を行い、システム上の在庫数と実際の在庫数を一致させます。

### 本機能の処理概要

在庫調整機能は、棚卸結果の反映や在庫差異の修正を行うための機能です。実地棚卸で判明した差異をシステムに反映し、正確な在庫情報を維持します。

**業務上の目的・背景**：在庫管理において、システム上の在庫数と実際の在庫数に差異が生じることがあります。誤出荷、破損、紛失、棚卸差異など、様々な原因で在庫差異が発生します。本機能は、これらの差異を適切に修正し、正確な在庫情報を維持することで、在庫管理の精度向上を支援します。

**機能の利用シーン**：
- 定期棚卸後に実在庫数をシステムに反映する場面
- 在庫差異が発見された際に数量を修正する場面
- 新規在庫を計上する場面
- 不良品や破損品を在庫から除外する場面

**主要な処理内容**：
1. 在庫数量の表示と棚卸数入力
2. 在庫差異（差分）の自動計算
3. 在庫調整の適用（Apply）
4. 調整のクリア（取消）
5. 新規在庫レコードの作成

**関連システム・外部連携**：ロケーション管理機能と連携し、ロケーション別の在庫数量を管理します。商品管理機能と連携し、商品別の在庫情報を表示します。在庫移動管理機能と連携し、調整時に在庫移動レコードを生成します。

**権限による制御**：在庫オペレーション権限を持つユーザーのみが在庫調整を行えます。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| SCR-INV-006 | QuantityResource | 主画面 | 在庫数量一覧表示・検索・フィルタ |
| SCR-INV-006 | ManageQuantities | 参照画面 | 在庫数量の管理・調整 |

## 機能種別

CRUD操作 / トランザクション処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| location_id | integer | Yes | ロケーションID | INTERNALタイプのロケーション |
| product_id | integer | Yes | 商品ID | is_storable=true、非コンフィグ商品 |
| lot_id | integer | No | ロットID | トラッキング設定時のみ |
| package_id | integer | No | パッケージID | パッケージ有効時のみ |
| counted_quantity | decimal | Yes | 棚卸数量 | 0以上、最大99999999999 |
| scheduled_at | date | No | 棚卸予定日 | 日付形式 |

### 入力データソース

- 画面入力：在庫調整フォームからのユーザー入力、テーブル内インライン編集
- DBテーブル：inventories_locations、products_products、inventories_lots、inventories_packages

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | integer | 在庫数量ID |
| location.full_name | string | ロケーション名 |
| storageCategory.name | string | ストレージカテゴリ名 |
| product.name | string | 商品名 |
| product.category.name | string | 商品カテゴリ名 |
| lot.name | string | ロット名 |
| package.name | string | パッケージ名 |
| available_quantity | decimal | 利用可能数量 |
| quantity | decimal | 在庫数量（オンハンド） |
| counted_quantity | decimal | 棚卸数量 |
| inventory_diff_quantity | decimal | 差異数量 |
| scheduled_at | date | 棚卸予定日 |
| user.name | string | 担当者名 |
| company.name | string | 会社名 |

### 出力先

- 画面表示：在庫数量一覧画面
- DBテーブル：inventories_product_quantities、inventories_moves

## 処理フロー

### 処理シーケンス

```
1. 在庫数量一覧表示
   └─ inventories_product_quantitiesテーブルからデータ取得
   └─ location.type = INTERNAL/TRANSIT でフィルタ
   └─ 削除済み商品を除外
   └─ フィルター・ソート条件を適用
   └─ 一覧画面に表示

2. 棚卸数入力（インライン編集）
   └─ counted_quantityをインラインで入力
   └─ inventory_quantity_set = true に更新
   └─ inventory_diff_quantity = counted_quantity - quantity を計算
   └─ 成功通知表示

3. 在庫調整適用（Apply）
   └─ 調整ロケーション（INVENTORY タイプ）を取得
   └─ quantity = counted_quantity に更新
   └─ counted_quantity = 0、inventory_diff_quantity = 0 にリセット
   └─ inventory_quantity_set = false にリセット
   └─ 調整用の在庫移動レコードを作成
   └─ 成功通知表示

4. 調整クリア（Clear）
   └─ inventory_quantity_set = false にリセット
   └─ counted_quantity = 0、inventory_diff_quantity = 0 にリセット
   └─ 成功通知表示

5. 新規在庫レコード作成
   └─ 重複チェック（同一ロケーション・商品・ロット・パッケージ）
   └─ 重複がある場合は警告通知
   └─ inventories_product_quantitiesテーブルにINSERT
   └─ 成功通知表示
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{操作種別}
    B -->|一覧表示| C[データ取得]
    C --> D[INTERNAL/TRANSITでフィルタ]
    D --> E[削除済み商品除外]
    E --> F[一覧表示]

    B -->|棚卸数入力| G[counted_quantity入力]
    G --> H[差異計算]
    H --> I[フラグ更新]
    I --> J[成功通知]

    B -->|適用| K{調整値あり?}
    K -->|Yes| L[調整ロケーション取得]
    L --> M[quantity更新]
    M --> N[カウント値リセット]
    N --> O[在庫移動レコード作成]
    O --> P[成功通知]
    K -->|No| F

    B -->|クリア| Q{調整値あり?}
    Q -->|Yes| R[カウント値リセット]
    R --> S[成功通知]
    Q -->|No| F

    B -->|新規作成| T[重複チェック]
    T -->|重複あり| U[警告通知]
    T -->|重複なし| V[レコード作成]
    V --> W[成功通知]

    F --> X[終了]
    J --> X
    P --> X
    S --> X
    U --> X
    W --> X
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-037-001 | ロケーション表示条件 | enable_locations設定時のみロケーション列を表示 | 画面表示時 |
| BR-037-002 | ロット表示条件 | enable_lots_serial_numbers設定時のみロット列を表示 | 画面表示時 |
| BR-037-003 | パッケージ表示条件 | enable_packages設定時のみパッケージ列を表示 | 画面表示時 |
| BR-037-004 | 適用ボタン表示条件 | inventory_quantity_set=trueの場合のみ表示 | レコードアクション |
| BR-037-005 | クリアボタン表示条件 | inventory_quantity_set=trueの場合のみ表示 | レコードアクション |
| BR-037-006 | 差異計算 | inventory_diff_quantity = counted_quantity - quantity | 棚卸数入力時 |
| BR-037-007 | 差異表示色 | 正の差異は緑、負の差異は赤で表示 | 一覧表示時 |
| BR-037-008 | 重複チェック | 同一ロケーション・商品・ロット・パッケージの組み合わせは不可 | 新規作成時 |
| BR-037-009 | デフォルトロケーション | ロケーション未指定時は倉庫のlot_stock_locationを使用 | 新規作成時 |
| BR-037-010 | 棚卸予定日デフォルト | annual_inventory_day/monthの設定値を使用 | 新規作成時 |

### 計算ロジック

**差異数量の算出**：
```
inventory_diff_quantity = counted_quantity - quantity
```

**調整後の在庫移動**：
```
if (inventory_diff_quantity < 0) {
    // 減少：実在庫 → 調整ロケーション
    source_location = 対象ロケーション
    destination_location = 調整ロケーション
} else {
    // 増加：調整ロケーション → 実在庫
    source_location = 調整ロケーション
    destination_location = 対象ロケーション
}
移動数量 = |inventory_diff_quantity|
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 一覧表示 | inventories_product_quantities | SELECT | 在庫数量一覧の取得 |
| 棚卸数入力 | inventories_product_quantities | UPDATE | 棚卸数・差異の更新 |
| 適用 | inventories_product_quantities | UPDATE | 在庫数量の確定 |
| 適用 | inventories_product_quantities | UPSERT | 調整ロケーションの在庫更新 |
| 適用 | inventories_moves | INSERT | 在庫移動レコード作成 |
| クリア | inventories_product_quantities | UPDATE | 棚卸数・差異のリセット |
| 新規作成 | inventories_product_quantities | INSERT | 新規在庫レコードの作成 |

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

#### inventories_product_quantities

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | counted_quantity | ユーザー入力値 | 棚卸数量 |
| UPDATE | inventory_quantity_set | true | 調整フラグ |
| UPDATE | inventory_diff_quantity | counted - quantity | 差異数量 |
| UPDATE | quantity | counted_quantity | 適用時の在庫数量 |
| UPDATE | counted_quantity | 0 | 適用後リセット |
| UPDATE | inventory_diff_quantity | 0 | 適用後リセット |
| UPDATE | inventory_quantity_set | false | 適用後リセット |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ERR-037-001 | バリデーションエラー | 必須項目未入力 | エラーメッセージ表示 |
| ERR-037-002 | 重複エラー | 同一組み合わせのレコードが存在 | 警告通知表示、処理中断 |
| ERR-037-003 | 権限エラー | 操作権限がない | アクセス拒否メッセージ表示 |

### リトライ仕様

在庫調整処理でエラーが発生した場合、トランザクションをロールバックし、エラーメッセージを表示してユーザーに再操作を促します。

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

- 在庫調整適用は1トランザクションで処理（在庫更新 + 移動レコード作成）
- エラー発生時は全てロールバック

## パフォーマンス要件

- 一覧表示：1秒以内にレスポンス
- インライン編集：即時更新（1秒以内）
- 適用処理：2秒以内に完了

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

- 在庫オペレーション権限による操作制限
- SQLインジェクション対策（Eloquent ORMによるパラメータバインディング）
- CSRF対策（Laravelのトークン検証）

## 備考

- ProductQuantityモデル（Webkul\Inventory\Models\ProductQuantity）を使用
- TextInputColumnによるインライン編集
- LocationType::INVENTORY タイプが調整用ロケーション
- ProductResource::createMoveで在庫移動レコードを生成
- QueryBuilder フィルターでモーダル表示
