# CloseTransferOrder

## Permission Scope

transferOrder

## Overview

closeTransferOrder transitions a DRAFT or OPEN TransferOrder to CLOSED. For OPEN orders, it supports short close when all shipped transfer quantity has already been received and no in-transit quantity remains.

## Business Rules

- DRAFT and OPEN transfer orders can be closed
- OPEN transfer orders can be closed only when every line has `shippedQuantity = receivedQuantity`
- Closing does not require every line to be fully shipped or fully received; unshipped remainder is short closed
- Closing an OPEN order closes remaining OPEN StockReservation rows created from the transfer order
- Closing an OPEN order closes remaining OPEN InventorySupplyPlan rows created from the transfer order
- `closedAt` is set when the order is closed
- No stock execution or ledger posting occurs

## Process Flow

```mermaid
flowchart TD
    A[Receive close request] --> B[Lock TransferOrder]
    B --> C{TransferOrder exists and is DRAFT or OPEN?}
    C -->|No| D[Return not found or state error]
    C -->|Yes| E[Load TransferOrderLine rows]
    E --> F{No in-transit quantity remains?}
    F -->|No| G[Return TRANSFER_ORDER_IN_TRANSIT]
    F -->|Yes| H[Close transfer reservations and supply plans]
    H --> I[Set status to CLOSED and stamp closedAt]
    I --> J[Return transfer order and closed planning rows]
```

## External Dependencies

- [inventory::TransferOrder](../model/TransferOrder.md) - Transitions the transfer order lifecycle
- [inventory::TransferOrderLine](../model/TransferOrderLine.md) - Provides shipped and received quantities for in-transit validation
- [inventory::StockReservation](../model/StockReservation.md) - Remaining transfer reservations are closed
- [inventory::InventorySupplyPlan](../model/InventorySupplyPlan.md) - Remaining transfer supply plans are closed

## Error Scenarios

- **TRANSFER_ORDER_NOT_FOUND**: Transfer order does not exist
- **INVALID_STATE_TRANSITION**: Transfer order lifecycle transition is not allowed
- **TRANSFER_ORDER_IN_TRANSIT**: One or more lines still have in-transit quantity

## Test Cases

- closes an OPEN transfer order when in-transit quantity is zero
- closes a DRAFT transfer order without planning rows
- returns error when in-transit quantity remains
