# ShipTransferOrder

## Permission Scope

transferOrder

## Overview

shipTransferOrder posts transfer shipment execution for an OPEN TransferOrder. It moves stock from source-site AVAILABLE stock into IN_TRANSIT stock and increments TransferOrderLine `shippedQuantity`.

The caller supplies the transit storage location used for the IN_TRANSIT side of the shipment. erp-kit records and validates that execution fact, but does not choose the transit location. Applications can pass a global default in-transit location or a site-specific in-transit location when users do not need to distinguish transit locations.

## Business Rules

- The TransferOrder must exist and be OPEN
- Each transfer line must belong to the TransferOrder
- Shipment quantity must be greater than zero
- Shipment quantity cannot exceed `orderedQuantity - shippedQuantity`
- Source storage location must belong to the TransferOrder source site
- Transit storage location must exist
- Shipment consumes matching TransferOrder StockReservation quantity
- Shipment creates a POSTED InventoryExecution with `executionType=GOODS_ISSUE` and `sourceDocumentType=TRANSFER_ORDER`
- Shipment creates two InventoryExecutionLine rows per transfer line: source AVAILABLE OUT and transit IN_TRANSIT IN
- Shipment creates two InventoryLedger rows per transfer line: source AVAILABLE credit and transit IN_TRANSIT debit
- Shipment updates source and transit StockLevel balances
- Shipment increments TransferOrderLine `shippedQuantity`

## Process Flow

```mermaid
flowchart TD
    A[Receive ship request] --> B[Lock TransferOrder]
    B --> C{TransferOrder is OPEN?}
    C -->|No| D[Return not found or state error]
    C -->|Yes| E[Create posted transfer shipment execution]
    E --> F[Validate each line and location]
    F --> G[Consume source reservation and source available stock]
    G --> H[Create execution lines and ledger rows]
    H --> I[Increase transit stock]
    I --> J[Increment shippedQuantity]
    J --> K[Return execution, ledger, and updated lines]
```

## External Dependencies

- [inventory::TransferOrder](../model/TransferOrder.md) - Must be OPEN
- [inventory::TransferOrderLine](../model/TransferOrderLine.md) - Provides line item, lot, serial, and shipment progress
- [inventory::StockReservation](../model/StockReservation.md) - Source reservation is consumed
- [inventory::StockLevel](../model/StockLevel.md) - Source AVAILABLE and transit IN_TRANSIT balances are updated
- [inventory::InventoryExecution](../model/InventoryExecution.md) - Records posted transfer shipment execution
- [inventory::InventoryLedger](../model/InventoryLedger.md) - Records immutable stock movement entries

## Error Scenarios

- **TRANSFER_ORDER_NOT_FOUND**: Transfer order does not exist
- **TRANSFER_ORDER_LINE_NOT_FOUND**: Transfer order line does not exist or does not belong to the order
- **INVALID_STATE_TRANSITION**: Transfer order is not OPEN
- **INVALID_QUANTITY**: Quantity is zero, negative, or exceeds remaining shippable quantity
- **INVALID_TRANSFER_LOCATIONS**: Source storage location is not in the source site
- **STORAGE_LOCATION_NOT_FOUND**: Source or transit storage location does not exist
- **INSUFFICIENT_STOCK**: Source available stock cannot cover the shipment

## Test Cases

- ships a transfer line into in-transit stock
- returns error when shipping more than remaining ordered quantity
- returns error when no lines are provided
