# 機能設計書 36-在庫移動管理

## 概要

本ドキュメントは、在庫管理モジュールにおける在庫移動管理機能の設計仕様を定義するものです。倉庫内のロケーション間での在庫移動（内部移動）を管理し、倉庫内の在庫配置を最適化します。

### 本機能の処理概要

在庫移動管理機能は、倉庫内の異なるロケーション間で在庫を移動するための機能です。ピッキング、保管場所の変更、在庫の再配置などの倉庫内作業を記録・管理します。

**業務上の目的・背景**：倉庫運営において、在庫は様々な理由で保管場所を変更する必要があります。入荷後の棚入れ、ピッキングエリアへの補充、レイアウト変更に伴う在庫移動など、多様な作業が発生します。本機能は、これらの在庫移動を正確に記録し、在庫のロケーション情報をリアルタイムに把握できるようにします。

**機能の利用シーン**：
- 入荷商品を保管エリアに移動する場面
- ピッキングエリアへ在庫を補充する場面
- 倉庫レイアウト変更に伴い在庫を移動する場面
- 品質検査後に在庫を適切なロケーションに移動する場面

**主要な処理内容**：
1. 内部移動オペレーションの作成・編集・削除
2. 移動元・移動先ロケーションの指定
3. 移動対象商品と数量の指定
4. 移動ステータスの管理（ドラフト/確認済/完了）
5. 移動明細（Move）の管理

**関連システム・外部連携**：ロケーション管理機能と連携し、有効なロケーションのみを選択肢として表示します。在庫数量管理機能と連携して、移動による在庫数の増減を反映します。オペレーションタイプ管理機能と連携し、内部移動タイプのオペレーションを管理します。

**権限による制御**：在庫オペレーション権限を持つユーザーのみが在庫移動の作成・編集・削除を行えます。WarehouseSettings設定でenable_locationsがtrueの場合のみ本機能が有効化されます。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| SCR-INV-005 | InternalResource | 主画面 | 内部移動一覧表示・検索・フィルタ |
| SCR-INV-005 | InternalResource/Create | 参照画面 | 新規内部移動の作成 |
| SCR-INV-005 | InternalResource/Edit | 参照画面 | 既存内部移動の編集 |
| SCR-INV-005 | InternalResource/View | 参照画面 | 内部移動詳細の表示 |
| SCR-INV-005 | ManageMoves | 参照画面 | 移動明細の管理 |

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | string | No | 移動名称 | 自動採番 |
| operation_type_id | integer | Yes | オペレーションタイプID | 内部移動タイプであること |
| source_location_id | integer | Yes | 移動元ロケーションID | 有効なロケーション |
| destination_location_id | integer | Yes | 移動先ロケーションID | 有効なロケーション |
| partner_id | integer | No | 取引先ID | 存在するパートナー |
| scheduled_at | datetime | No | 予定日時 | 日時形式 |
| moves | array | No | 移動明細 | 配列形式 |
| moves.*.product_id | integer | Yes | 商品ID | 存在する商品 |
| moves.*.quantity | decimal | Yes | 数量 | 0より大きい数値 |
| moves.*.uom_id | integer | No | 単位ID | 存在する単位 |

### 入力データソース

- 画面入力：内部移動登録・編集フォームからのユーザー入力
- DBテーブル：inventories_operation_types、inventories_locations、partners、products_products

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | integer | 内部移動ID |
| name | string | 移動名称 |
| state | enum | ステータス |
| operationType.name | string | オペレーションタイプ名 |
| sourceLocation.full_name | string | 移動元ロケーション |
| destinationLocation.full_name | string | 移動先ロケーション |
| partner.name | string | 取引先名 |
| scheduled_at | datetime | 予定日時 |
| moves | array | 移動明細一覧 |
| created_at | datetime | 作成日時 |
| updated_at | datetime | 更新日時 |

### 出力先

- 画面表示：内部移動一覧画面、詳細画面
- DBテーブル：inventories_operations、inventories_moves

## 処理フロー

### 処理シーケンス

```
1. 内部移動一覧表示
   └─ inventories_operationsテーブルからデータ取得
   └─ operation_type.type = INTERNAL でフィルタ
   └─ フィルター・ソート条件を適用
   └─ ページネーション処理
   └─ 一覧画面に表示

2. 内部移動作成
   └─ OperationResourceのフォームを使用
   └─ オペレーションタイプ選択
   └─ 移動元・移動先ロケーション選択
   └─ 移動明細追加
   └─ バリデーション実行
   └─ inventories_operationsテーブルにINSERT
   └─ inventories_movesテーブルに明細INSERT
   └─ 成功通知表示

3. 内部移動編集
   └─ 既存データを取得してフォームに表示
   └─ データ編集（state=DONEの場合は編集不可）
   └─ バリデーション実行
   └─ inventories_operationsテーブルをUPDATE
   └─ 成功通知表示

4. 内部移動削除
   └─ 削除確認ダイアログ表示（state=DONEの場合は削除不可）
   └─ inventories_operationsテーブルからDELETE
   └─ 成功/エラー通知表示

5. 移動実行（確定）
   └─ 移動明細の在庫を更新
   └─ 移動元ロケーションの在庫減少
   └─ 移動先ロケーションの在庫増加
   └─ state = DONE に更新
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{操作種別}
    B -->|一覧表示| C[データ取得]
    C --> D[INTERNAL タイプでフィルタ]
    D --> E[フィルタ・ソート適用]
    E --> F[一覧表示]

    B -->|作成| G[入力フォーム表示]
    G --> H[基本情報入力]
    H --> I[移動明細追加]
    I --> J{バリデーション}
    J -->|OK| K[オペレーション作成]
    K --> L[移動明細作成]
    J -->|NG| H
    L --> M[成功通知]

    B -->|編集| N{state確認}
    N -->|DONE| O[編集不可]
    N -->|その他| P[編集フォーム表示]
    P --> Q[データ編集]
    Q --> R{バリデーション}
    R -->|OK| S[DBを更新]
    R -->|NG| Q
    S --> T[成功通知]

    B -->|削除| U{state確認}
    U -->|DONE| V[削除不可]
    U -->|その他| W[削除確認]
    W -->|確認| X[削除実行]
    W -->|キャンセル| F
    X --> Y[成功通知]

    B -->|移動実行| Z[在庫更新]
    Z --> AA[移動元減少]
    AA --> AB[移動先増加]
    AB --> AC[state=DONE]

    F --> AD[終了]
    M --> AD
    T --> AD
    O --> AD
    V --> AD
    Y --> AD
    AC --> AD
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-036-001 | INTERNAL タイプ限定 | operation_type.type = INTERNAL の オペレーションのみ表示 | 一覧表示時 |
| BR-036-002 | DONE状態編集禁止 | state=DONEのオペレーションは編集不可 | 編集時 |
| BR-036-003 | DONE状態削除禁止 | state=DONEのオペレーションは削除不可 | 削除時 |
| BR-036-004 | 機能有効化条件 | enable_locations設定がtrueの場合のみ機能有効 | 画面表示時 |
| BR-036-005 | ID降順ソート | デフォルトでID降順でソート | 一覧表示時 |

### 計算ロジック

**在庫移動の反映**：
```
移動元ロケーション在庫 = 現在在庫 - 移動数量
移動先ロケーション在庫 = 現在在庫 + 移動数量
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 一覧表示 | inventories_operations | SELECT | オペレーション一覧の取得 |
| 作成 | inventories_operations | INSERT | 新規オペレーションの登録 |
| 作成 | inventories_moves | INSERT | 移動明細の登録 |
| 編集 | inventories_operations | UPDATE | 既存オペレーションの更新 |
| 削除 | inventories_operations | DELETE | オペレーションの削除 |
| 移動実行 | inventories_product_quantities | UPDATE | 在庫数の更新 |

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

#### inventories_operations

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name | 自動採番 | オペレーション名 |
| INSERT | state | DRAFT | 初期ステータス |
| INSERT | operation_type_id | フォーム入力値 | オペレーションタイプ |
| INSERT | source_location_id | フォーム入力値 | 移動元ロケーション |
| INSERT | destination_location_id | フォーム入力値 | 移動先ロケーション |
| INSERT | partner_id | フォーム入力値 | 取引先 |
| INSERT | scheduled_at | フォーム入力値 | 予定日時 |
| UPDATE | state | DONE | 移動実行時 |

#### inventories_moves

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | operation_id | 親オペレーションID | オペレーションへの紐付け |
| INSERT | product_id | フォーム入力値 | 商品ID |
| INSERT | quantity | フォーム入力値 | 数量 |
| INSERT | uom_id | フォーム入力値 | 単位ID |
| INSERT | source_location_id | 親から継承 | 移動元ロケーション |
| INSERT | destination_location_id | 親から継承 | 移動先ロケーション |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ERR-036-001 | バリデーションエラー | 必須項目未入力 | エラーメッセージ表示、入力画面に戻る |
| ERR-036-002 | 編集禁止エラー | DONE状態のオペレーションを編集 | エラーメッセージ表示 |
| ERR-036-003 | 削除禁止エラー | DONE状態のオペレーションを削除 | 削除ボタン非表示 |
| ERR-036-004 | 在庫不足エラー | 移動元ロケーションの在庫が不足 | エラー通知表示 |
| ERR-036-005 | 権限エラー | 操作権限がない | アクセス拒否メッセージ表示 |

### リトライ仕様

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

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

- オペレーションと移動明細の作成は1トランザクションで処理
- 移動実行（在庫更新）は1トランザクションで処理し、エラー時は全てロールバック

## パフォーマンス要件

- 一覧表示：1秒以内にレスポンス
- 作成・更新：2秒以内に完了
- 移動実行：3秒以内に完了（明細100件まで）

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

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

## 備考

- InternalResourceはOperationResourceのフォーム/テーブル/インフォリストを再利用
- InternalTransferモデル（Operationモデルの特化）を使用
- OperationState列挙型（DRAFT/WAITING/READY/DONE/CANCELLED）
- OperationType列挙型でINTERNALタイプをフィルタ
