# SalesOrder

## Description

SalesOrder is the primary commercial commitment between one company and one customer. It captures customer, transaction currency, billing, shipping, and pricing context before downstream fulfillment or receivables billing occurs, and it preserves the commercial baseline that fulfillment and accounts-receivable records must reference later. The aggregate includes one or more SalesOrderLine children that track ordered, fulfilled, billed, and remaining quantities per sellable item.

The model separates status into three independent axes. `orderStatus` tracks document control, `fulfillmentStatus` tracks physical fulfillment progress, and `billingStatus` tracks billing progress. Fulfillment and billing progress are projections derived from downstream evidence and never overwrite the document lifecycle.

## Domain Model Definitions

### Model type

Stateful

#### State Transitions

```mermaid
stateDiagram-v2
    [*] --> Draft: createSalesOrder
    Draft --> Submitted: submitSalesOrder
    Submitted --> Draft: rejectSalesOrder
    Submitted --> Confirmed: confirmSalesOrder
    Confirmed --> Cancelled: cancelSalesOrder
    Draft --> Cancelled: cancelSalesOrder
    Submitted --> Cancelled: cancelSalesOrder
    Confirmed --> Closed: closeSalesOrder
```

| Operation | From | To | Command |
|-----------|------|----|---------|
| submit | DRAFT | SUBMITTED | [submitSalesOrder](../command/SubmitSalesOrder.md) |
| reject | SUBMITTED | DRAFT | [rejectSalesOrder](../command/RejectSalesOrder.md) |
| confirm | SUBMITTED | CONFIRMED | [confirmSalesOrder](../command/ConfirmSalesOrder.md) |
| cancel | CONFIRMED, DRAFT, SUBMITTED | CANCELLED | [cancelSalesOrder](../command/CancelSalesOrder.md) |
| close | CONFIRMED | CLOSED | [closeSalesOrder](../command/CloseSalesOrder.md) |

### Command Definitions

- [createSalesOrder](../command/CreateSalesOrder.md) - Create a new draft sales order with initial line-level commercial context.
- [updateSalesOrder](../command/UpdateSalesOrder.md) - Revise mutable draft fields and line details before submission or explicit revision flow.
- [submitSalesOrder](../command/SubmitSalesOrder.md) - Move a draft order into review-ready submitted status.
- [rejectSalesOrder](../command/RejectSalesOrder.md) - Return a submitted order to draft with a preserved rejection reason.
- [confirmSalesOrder](../command/ConfirmSalesOrder.md) - Freeze commercial terms and make the order executable.
- [cancelSalesOrder](../command/CancelSalesOrder.md) - Cancel an order that has not progressed into an irreversible downstream state.
- [closeSalesOrder](../command/CloseSalesOrder.md) - Close the remaining open balance when execution is complete or written off by policy.
- [recalculateSalesOrderFulfillmentStatus](../command/RecalculateSalesOrderFulfillmentStatus.md) - Add posted outbound-shipment quantities and derive fulfillmentStatus.
- [recalculateSalesOrderBillingStatus](../command/RecalculateSalesOrderBillingStatus.md) - Apply receivables billing quantities and derive billingStatus.

### Query Definitions

- [getSalesOrder](../query/GetSalesOrder.md) - Retrieve one sales order with customer, status, line, and progress details.
- [listSalesOrders](../query/ListSalesOrders.md) - List sales orders for operational work queues and sales monitoring.

### Models

- SalesOrder
- SalesOrderLine

### Invariants

- Every sales order belongs to exactly one company and one customer, and all child lines stay within that same company scope.
- A sales order always contains at least one sales order line before it can leave DRAFT.
- Only company-compatible CustomerAccounts available for transactions can be used on a new or confirmed sales order.
- The header carries the transaction currency, which must be the owning company's base currency because the kit does not handle FX.
- Each line preserves the applied unit price and matched price-rule reference so later master-data edits do not rewrite the confirmed commercial baseline.
- `orderStatus`, `fulfillmentStatus`, and `billingStatus` are independent; downstream progress never changes `orderStatus`.
- `fulfillmentStatus` and `billingStatus` are null before confirmation and initialized when the order reaches `CONFIRMED`.
- `fulfillmentStatus` is `NOT_FULFILLED` when no line requires physical fulfillment.
- `quantity`, `unitPrice`, `fulfilledQuantity`, and `billedQuantity` use decimal storage and string command values so fractional quantities and prices do not lose precision.
- `fulfilledQuantity` and `billedQuantity` are downstream-owned projections and cannot be set through normal create or draft-update commands.
- The cumulative fulfilled quantity for each physical line cannot exceed the ordered quantity.
- An order can move to CLOSED only when every physical line is fully fulfilled and every line is fully billed.

### Relationships

- **Owns SalesOrderLine**: SalesOrder is the aggregate root for one or more SalesOrderLine children.
- **References Currency (cross-module)**: `currencyId` references the order's transaction [Currency](../../../primitives/docs/model/Currency.md).
- **References CustomerAccount (cross-module)**: `customerAccountId` references the transaction account. The billing and shipping addresses are supplied by the caller as plain text; the basic account lookup intentionally does not load address usages.
- **Referenced By Fulfillment**: Downstream fulfillment records consume open sales-order quantities and report fulfilled progress back to the order.
- **Referenced By Accounts Receivable**: Customer invoice and credit-note documents point back to the originating commercial commitment from the accounts-receivable module.
