# updateTransferOrder

## Overview

Edits a DRAFT Transfer Order. The GraphQL input takes an optional header patch (source / destination Site, planned-shipment / expected-receipt dates, and notes — omit to leave unchanged, `""` clears notes) plus a full replacement line array. Like `createTransferOrder`, the resolver injects `unitId = each.id` on every line so the GraphQL surface does not expose Unit.

erp-kit ≥ 0.39 made the module command's line edits incremental (`addLines` / `updateLines` keyed by `lineId` / `removeLineIds`) instead of a whole-array replace. The edit form tracks no line IDs and still submits the full line set, so this resolver translates that into `removeLineIds: <all existing lines>` + `addLines: <all submitted lines>` — equivalent to the old whole-array replace. This is safe only because update is DRAFT-only: every line's shipped/received quantity is still `0`, so recreating the rows loses no progress. The module command rejects any non-DRAFT order with `INVALID_STATE_TRANSITION`.

## Modules Commands Used

- [transfer-order] updateTransferOrder

## Exception Handling

These are the `result.error.code` values the resolver switches on before
rethrowing as a human-readable `Error`. They are native `INVENTORY_*` codes
passed through from erp-kit.

| Error Code | Description |
| --- | --- |
| INVENTORY_TRANSFER_ORDER_NOT_FOUND | No transfer order exists for the given id |
| INVENTORY_INVALID_STATE_TRANSITION | The transfer order is not in DRAFT and cannot be edited |
| INVENTORY_INVALID_TRANSFER_LOCATIONS | The source and destination Sites are the same |
| INVENTORY_EMPTY_TRANSFER_LINES | The replacement line set is empty |
| INVENTORY_INVALID_QUANTITY | A line's orderedQuantity is zero or negative |
| INVENTORY_ITEM_NOT_FOUND | A line references a non-existent item |
| INVENTORY_SITE_NOT_FOUND | The new source or destination Site does not exist |
