# Sales Order Lifecycle

## Overview

A sales order separates document control from execution progress. `orderStatus`
tracks approval and terminal document decisions. `fulfillmentStatus` and
`billingStatus` are independent projections derived from line-level fulfilled
and billed quantities.

Draft and submitted orders have null execution projections. Confirmation
initializes fulfillment to `NOT_FULFILLED` and billing to `NOT_BILLED`. Posted
outbound shipments advance fulfillment without changing
the document status. A future receivables integration can update billing through
the internal recalculation command.

## Business Purpose

- Preserve one stable document lifecycle while fulfillment and billing progress independently
- Prevent downstream systems from rewriting commercial document control
- Derive fulfillment from posted shipment evidence rather than user-entered progress
- Support physical goods and non-physical service lines on the same order
- Keep Credit Hold and credit-management policy outside the core order lifecycle

## Process Flow

```mermaid
flowchart TD
    A[Create Sales Order] --> B["orderStatus: DRAFT"]
    B -->|submit| C["orderStatus: SUBMITTED"]
    C -->|reject| B
    C -->|confirm| D["orderStatus: CONFIRMED\ninitialize fulfillmentStatus and billingStatus"]
    D -->|post partial outbound shipment| E["fulfillmentStatus: PARTIALLY_FULFILLED"]
    D -->|post complete outbound shipment| F["fulfillmentStatus: FULFILLED"]
    D -->|billing feedback| G["billingStatus: PARTIALLY_BILLED or BILLED"]
    D -->|close after execution| H["orderStatus: CLOSED"]
    B -->|cancel| I["orderStatus: CANCELLED"]
    C -->|cancel| I
    D -->|cancel before progress| I
```

## Scenario Patterns

- **Standard goods order**: Confirmation initializes fulfillment, then one or more posted outbound shipments move it from not fulfilled to partial and fulfilled
- **Service-only order**: Fulfillment remains not fulfilled because there is no physical quantity to fulfill; billing can progress and the order can close without fulfillment quantities
- **Mixed goods and services**: Only physical lines contribute to fulfillment, while all lines contribute to billing
- **Rejected order**: A submitted order returns to draft without initializing execution projections
- **Cancellation before execution**: Draft, submitted, or confirmed orders without fulfilled or billed quantities may be cancelled
- **Independent billing**: Billing can progress independently of fulfillment without changing `orderStatus`

## Test Cases

- New orders use `orderStatus=DRAFT` with null fulfillment and billing projections
- Normal create and update inputs cannot set fulfilled or billed quantities
- Confirmation initializes `fulfillmentStatus` and `billingStatus`
- Confirmation of an order without physical lines sets fulfillment to `NOT_FULFILLED`
- Posted outbound-shipment deltas update line fulfilled quantities and derive fulfillment
- Fulfilled quantities cannot exceed the ordered physical quantity
- Billing feedback updates billed quantities and derives billing independently
- Cancellation fails after fulfillment or billing progress exists
- Closing requires physical lines to be fulfilled and every line to be billed
- A fully billed service line does not require shipment progress for closure

## Reference Links

- [SalesOrder model](../model/SalesOrder.md)
- [RecalculateSalesOrderFulfillmentStatus](../command/RecalculateSalesOrderFulfillmentStatus.md)
- [RecalculateSalesOrderBillingStatus](../command/RecalculateSalesOrderBillingStatus.md)
- [Outbound Shipment posting](../../../outbound-shipment/docs/command/PostOutboundShipment.md)
