# CreateTransferOrder

## Permission Scope

transferOrder

## Overview

createTransferOrder creates a DRAFT TransferOrder and one or more TransferOrderLine rows.

## Business Rules

- Source and destination sites are required and must exist
- Source and destination sites must differ
- Source and destination sites must belong to the same company; cross-company transfers are not supported
- `plannedShipmentDate` and `expectedReceiptDate` are required and stored on the header for later reservation and supply planning
- At least one line is required
- Each line item must exist
- Each line `unitId` is derived from the referenced item primary unit; callers do not choose a transfer-specific unit
- Each line ordered quantity must be greater than zero
- Lines are initialized with `shippedQuantity = 0` and `receivedQuantity = 0`
- No InventoryLedger, StockLevel, StockReservation, or InventorySupplyPlan rows are created

## Process Flow

```mermaid
flowchart TD
    A[Receive create transfer order request] --> B{Source and destination sites valid, different, and in the same company?}
    B -->|No| C[Return validation error]
    B -->|Yes| D{At least one valid item line?}
    D -->|No| E[Return line validation error]
    D -->|Yes| F[Insert DRAFT TransferOrder]
    F --> G[Insert TransferOrderLine rows with zero shipped and received quantities]
    G --> H[Return transfer order and lines]
```

## External Dependencies

- [organization::Site](../../../organization/docs/model/Site.md) - Validates source and destination sites
- [item-management::Item](../../../item-management/docs/model/Item.md) - Validates referenced line items and derives each line primary unit
- [inventory::TransferOrder](../model/TransferOrder.md) - Creates the transfer order header
- [inventory::TransferOrderLine](../model/TransferOrderLine.md) - Creates the transfer order lines

## Error Scenarios

- **TRANSFER_ORDER_NOT_FOUND**: Transfer order does not exist
- **EMPTY_TRANSFER_LINES**: No transfer lines were provided
- **INVALID_QUANTITY**: Quantity is zero or negative
- **INVALID_STATE_TRANSITION**: Transfer order lifecycle transition is not allowed
- **INVALID_TRANSFER_LOCATIONS**: Transfer location or site is invalid
- **CROSS_COMPANY_TRANSFER_NOT_SUPPORTED**: Transfer between sites of different companies is not supported
- **ITEM_NOT_FOUND**: Referenced item does not exist
- **SITE_NOT_FOUND**: Referenced site does not exist
- **INVALID_ARGUMENT**: Argument is invalid

## Test Cases

- creates a DRAFT transfer order with lines
- persists custom header and line fields
- returns error when no lines are provided
- returns error when source and destination sites are the same
- returns error when source and destination sites belong to different companies
- returns error when ordered quantity is zero or negative
