# CreateOutboundShipment

## Permission Scope

outboundShipmentOperation

## Overview

createOutboundShipment creates a DRAFT OutboundShipment. Each line records the outbound stock effect that will be posted later by postOutboundShipment.

## Business Rules

- At least one line is required
- effectiveDate is required and is stored as the intended issue posting date
- Each line quantity must be greater than zero
- Each line item must exist; inactive items are accepted because shipments may post long after the source sales or manufacturing document was created
- Each line storage location must exist; inactive locations are accepted for historical dispatch continuity
- quantity and unitId preserve the source/business issue unit, such as the sales order unit
- primaryQuantity must be greater than zero and stores the converted quantity in primaryUnitId
- primaryUnitId must equal Item.unitId
- unitConversionRate must be greater than zero and records the multiplier used to derive primaryQuantity from quantity
- Unit conversion is resolved before calling this command; this command stores both source-unit and primary-unit snapshots
- Outbound valuation derives cost from the active inventory valuation policy during posting; unit cost is not accepted as command input
- Each line must carry source references (sourceDocumentType, sourceDocumentId, sourceLineId); sourceDocumentType must be SALES_ORDER
- Lines are stored with `stockType=AVAILABLE`
- No StockLevel, InventoryLedger, or valuation changes occur while the shipment is DRAFT

## Process Flow

```mermaid
flowchart TD
    A[Create outbound shipment request] --> G{Items and locations valid?}
    G -->|No| H[Return validation error]
    G -->|Yes| D{At least one line?}
    D -->|No| E0[Return error: EMPTY_SHIPMENT_LINES]
    D -->|Yes| F0{All quantities positive?}
    F0 -->|No| F[Return error: INVALID_QUANTITY]
    F0 -->|Yes| I[Create DRAFT OutboundShipment]
    I --> J[Create OutboundShipmentLine rows]
    J --> K[Return created shipment id]
```

## External Dependencies

- [item-management::Item](../../../item-management/docs/model/Item.md) - Validates referenced items
- [inventory::StorageLocation](../../../inventory/docs/model/StorageLocation.md) - Validates issuing locations
- [outbound-shipment::OutboundShipment](../model/OutboundShipment.md) - Creates the shipment header and outbound shipment lines

## Error Scenarios

- **EMPTY_SHIPMENT_LINES**: No outbound shipment lines were provided
- **INVALID_QUANTITY**: Quantity is zero or negative
- **PRIMARY_UNIT_MISMATCH**: primaryUnitId differs from Item.unitId
- **INVALID_UNIT_CONVERSION_RATE**: Unit conversion rate is zero or negative
- **ITEM_NOT_FOUND**: Referenced item does not exist
- **STORAGE_LOCATION_NOT_FOUND**: Referenced storage location does not exist

## Test Cases

- returns error when no lines are provided
- returns error when line quantity is zero or negative
- returns error when line primary quantity is zero or negative
- returns error when line unit conversion rate is zero or negative
- returns error when item does not exist
- returns error when primary unit differs from item primary unit
- returns error when storage location does not exist
- creates a DRAFT outbound shipment with outbound lines
- creates a DRAFT outbound shipment covering lines from multiple source documents
- accepts inactive item and location references
