# OpenTransferOrder

## Permission Scope

transferOrder

## Overview

openTransferOrder transitions a DRAFT TransferOrder to OPEN, reserves source-site availability, and creates destination-site supply projections so downstream execution can ship and receive stock.

## Business Rules

- Only DRAFT transfer orders can be opened
- Opening does not post stock by itself
- Opening creates one OPEN StockReservation per TransferOrderLine at the source site
- Opening creates one OPEN InventorySupplyPlan per TransferOrderLine at the destination site
- TransferOrder `plannedShipmentDate` is copied to StockReservation `requiredDate`
- TransferOrder `expectedReceiptDate` is copied to InventorySupplyPlan `expectedDate`
- Source-site available stock must cover the transfer demand before the order can open
- Shipment and receipt are posted separately through `postInventoryLedger`, which writes InventoryLedger rows referencing the transfer order with `sourceType=TRANSFER_ORDER`

## Process Flow

```mermaid
flowchart TD
    A[Receive open request] --> B[Lock TransferOrder]
    B --> C{TransferOrder exists and is DRAFT?}
    C -->|No| D[Return not found or state error]
    C -->|Yes| E[Load TransferOrderLine rows]
    E --> F{Source site ATP covers line demand?}
    F -->|No| G[Return insufficient stock error]
    F -->|Yes| H[Set status to OPEN]
    H --> I[Create StockReservation rows]
    I --> J[Create InventorySupplyPlan rows]
    J --> K[Return transfer order and planning rows]
```

## External Dependencies

- [inventory::TransferOrder](../model/TransferOrder.md) - Transitions the transfer order lifecycle
- [inventory::TransferOrderLine](../model/TransferOrderLine.md) - Provides source line quantities for reservations and supply plans
- [inventory::StockReservation](../model/StockReservation.md) - Reserves source-site ATP for each transfer line
- [inventory::InventorySupplyPlan](../model/InventorySupplyPlan.md) - Projects destination-site inbound supply for each transfer line
- [inventory::postInventoryLedger](./PostInventoryLedger.md) - Downstream shipment and receipt postings reference open transfer orders via `sourceType=TRANSFER_ORDER`

## Error Scenarios

- **TRANSFER_ORDER_NOT_FOUND**: Transfer order does not exist
- **INVALID_STATE_TRANSITION**: Transfer order lifecycle transition is not allowed
- **EMPTY_TRANSFER_LINES**: No transfer lines were provided
- **INSUFFICIENT_AVAILABLE_STOCK**: Available stock is less than the requested quantity

## Test Cases

- opens a DRAFT transfer order
- returns error when transfer order is not DRAFT
- returns error when source site available stock cannot cover transfer demand
- aggregates repeated item demand before validating source site availability
