# ReceiveTransferOrder

## Permission Scope

transferOrder

## Overview

receiveTransferOrder posts transfer receipt execution for an OPEN TransferOrder. It moves stock from IN_TRANSIT stock into destination-site AVAILABLE stock and increments TransferOrderLine `receivedQuantity`.

The caller supplies the transit storage location being consumed. 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
- Receipt quantity must be greater than zero
- Receipt quantity cannot exceed `shippedQuantity - receivedQuantity`
- Transit storage location must exist and hold enough IN_TRANSIT stock
- Transit IN_TRANSIT stock must be available for the same transfer line and transit storage location
- Destination storage location must belong to the TransferOrder destination site
- Receipt consumes matching TransferOrder InventorySupplyPlan quantity
- Receipt creates a POSTED InventoryExecution with `executionType=GOODS_RECEIPT` and `sourceDocumentType=TRANSFER_ORDER`
- Receipt creates two InventoryExecutionLine rows per transfer line: transit IN_TRANSIT OUT and destination AVAILABLE IN
- Receipt creates two InventoryLedger rows per transfer line: transit IN_TRANSIT credit and destination AVAILABLE debit
- Receipt updates transit and destination StockLevel balances
- Receipt increments TransferOrderLine `receivedQuantity`

## Process Flow

```mermaid
flowchart TD
    A[Receive transfer receipt request] --> B[Lock TransferOrder]
    B --> C{TransferOrder is OPEN?}
    C -->|No| D[Return not found or state error]
    C -->|Yes| E[Create posted transfer receipt execution]
    E --> F[Validate each line and location]
    F --> G[Consume transit stock and destination supply plan]
    G --> H[Create execution lines and ledger rows]
    H --> I[Increase destination stock]
    I --> J[Increment receivedQuantity]
    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 receipt progress
- [inventory::InventorySupplyPlan](../model/InventorySupplyPlan.md) - Destination supply projection is consumed
- [inventory::StockLevel](../model/StockLevel.md) - Transit IN_TRANSIT and destination AVAILABLE balances are updated
- [inventory::InventoryExecution](../model/InventoryExecution.md) - Records posted transfer receipt 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 in-transit quantity for the line
- **INVALID_TRANSFER_LOCATIONS**: Destination storage location is not in the destination site
- **STORAGE_LOCATION_NOT_FOUND**: Transit or destination storage location does not exist
- **INSUFFICIENT_STOCK**: Transit stock cannot cover the receipt

## Test Cases

- receives in-transit stock into the destination site
- receives the same transfer line from multiple transit locations
- returns error when receiving more than in-transit transfer quantity
- returns error when transit stock belongs to another transfer line
- returns error when no lines are provided
