# CreateStockMovement

## Permission Scope

stockOperation

## Overview

createStockMovement creates a new stock movement in DRAFT status with one or more move lines. Stock movements track the physical flow of goods through the warehouse system and support multiple movement types: goods receipt, goods issue, internal transfer, block, and unblock.

## Business Rules

- movementType is required and must be one of: GOODS_RECEIPT, GOODS_ISSUE, INTERNAL_TRANSFER, BLOCK, UNBLOCK
- At least one move line is required
- Each move line: quantity must be greater than zero
- Each move line: source location must not equal destination location
- Each move line: referenced item must exist but does not need to be ACTIVE — stock movements may originate from in-progress fulfillment (e.g. goods receipt posting) where the item was deactivated after the order was committed, so blocking on item status would prevent completing already-committed transactions
- BLOCK and UNBLOCK movement types require a reasonCode
- For lot-tracked items, each move line must specify a lotId
- Movement is created in DRAFT status

## Process Flow

```mermaid
flowchart TD
    A[Receive create request] --> B{Valid movementType?}
    B -->|No| C[Return error: INVALID_MOVEMENT_TYPE]
    B -->|Yes| D{Move lines provided?}
    D -->|No| E[Return error: EMPTY_MOVE_LINES]
    D -->|Yes| F{Validate each line}
    F --> G{Item exists?}
    G -->|No| H[Return error: ITEM_NOT_FOUND]
    G -->|Yes| J{Quantity > 0?}
    J -->|No| K[Return error: INVALID_QUANTITY]
    J -->|Yes| L{Source ≠ destination?}
    L -->|No| M[Return error: SAME_SOURCE_DESTINATION]
    L -->|Yes| N{Location exists?}
    N -->|No| O[Return error: STORAGE_LOCATION_NOT_FOUND]
    N -->|Yes| P{Lot-tracked item?}
    P -->|Yes| Q{lotId provided?}
    Q -->|No| R[Return error: LOT_REQUIRED_FOR_TRACKED_ITEM]
    Q -->|Yes| S{Block/unblock type?}
    P -->|No| S
    S -->|Yes| T{reasonCode provided?}
    T -->|No| U[Return error: REASON_CODE_REQUIRED]
    T -->|Yes| V[Create movement + lines in DRAFT]
    S -->|No| V
    V --> W[Return created movement]
```

## External Dependencies

- [item-management::Item](../../../item-management/docs/models/Item.md) - Validates that each referenced item exists and checks whether the item is lot-tracked (ACTIVE status is not required)

## Error Scenarios

- **INVALID_MOVEMENT_TYPE**: movementType is not a recognized value
- **EMPTY_MOVE_LINES**: No move lines were provided
- **ITEM_NOT_FOUND**: Referenced item does not exist
- **INVALID_QUANTITY**: Move line quantity is zero or negative
- **SAME_SOURCE_DESTINATION**: Source and destination locations are the same
- **STORAGE_LOCATION_NOT_FOUND**: Referenced storage location does not exist
- **REASON_CODE_REQUIRED**: Block or unblock movement type requires a reason code
- **LOT_REQUIRED_FOR_TRACKED_ITEM**: Move line references a lot-tracked item but no lotId was provided

## Test Cases

- returns error when no move lines
- returns error when invalid movement type
- returns error when item not found
- accepts inactive item without error
- returns error when quantity is zero or negative
- returns error when source equals destination
- returns error when storage location not found
- returns error when block without reason code
- creates movement in DRAFT status
- returns error when lot-tracked item has no lotId
- creates movement with multiple lines
