# Outbound Shipment — Models & Action Visibility Matrix

## Models Involved

Source of truth: native `outbound-shipment.OutboundShipment` (erp-kit 0.45 `outbound-shipment`).

| Model | erp-kit module | Role in this flow |
|---|---|---|
| OutboundShipment | (erp-kit `outbound-shipment`, native) | Issue header; owns `status`, native `docNumber` serial (`OSH-%d`), issue-from storage location, and effective (issue) date |
| OutboundShipmentLine | (erp-kit `outbound-shipment`, native) | Per-line `itemId`, storage location, quantity, and the source-document link: `sourceDocumentType` (SALES_ORDER), `sourceDocumentId` (the sales order), and `sourceLineId` (the sales order line) |
| StockLevel | (erp-kit `inventory`, native) | AVAILABLE balances reduced when the outbound shipment is posted |
| SalesOrder / SalesOrderLine | (erp-kit `sales`, native) | Source order; settling advances `fulfilledQuantity` and rolls up the order's shipped `status` via a posted Shipment |
| Shipment | (erp-kit `sales`, native) | Recorded + posted by `settleOutboundShipment` for the issued quantities so the sales order advances |
| Item | (erp-kit `item-management`) | Line item reference |

### Status Axis

| Field | Values |
|---|---|
| `status` | `DRAFT` → `POSTED` \| `CANCELLED` |

The status state machine is owned by native erp-kit `outbound-shipment`. This template exposes create + settle (post) + cancel. Posting is terminal — a POSTED outbound shipment cannot be cancelled or re-posted.

## Action Visibility Matrix

The `outbound-shipment-detail` screen's action panel gates each button on `status`.

Legend: ✓ visible+enabled · ◐ visible but disabled · blank = hidden.

| Action | Resolver / target | DRAFT | POSTED | CANCELLED | Extra condition | Role |
|---|---|:-:|:-:|:-:|---|---|
| Post / Settle | `settleOutboundShipment` | ✓ |  |  | reduces AVAILABLE stock | inventory-manager |
| Cancel | `cancelOutboundShipment` | ✓ |  |  | a posted outbound shipment cannot be cancelled | inventory-manager |
| Back | _navigate to list_ | ✓ | ✓ | ✓ | — | — |

## Notes on Stock & Fulfilment

Nothing leaves stock until the outbound shipment is settled. `settleOutboundShipment` posts the shipment through the outbound-shipment `postOutboundShipment` command, which reduces AVAILABLE stock (ledger + StockLevel, consuming any matching reservations) and moves the shipment to POSTED.

Posting reflects `SALES_ORDER` source lines back onto the linked order by advancing `SalesOrderLine.fulfilledQuantity` and deriving `fulfillmentStatus` as `PARTIALLY_FULFILLED` or `FULFILLED`. This is transactional with inventory posting.
