# CreateGoodsReceipt

## Permission Scope

inventoryOperation

## Overview

createGoodsReceipt creates a DRAFT InventoryExecution with `executionType=GOODS_RECEIPT`.
Each line records the inbound stock effect that will be posted later by postGoodsReceipt.

For purchase receipts, prefer `purchase.commands.createGoodsReceipt` instead of calling `inventory.commands.createGoodsReceipt` directly. The purchase command is the public purchase-facing entrypoint and keeps callers aligned with the purchase module boundary.

## Business Rules

- At least one line is required
- effectiveDate is required and is stored as the intended receipt posting date
- sourceDocumentType and sourceDocumentId are required and become immutable source references
- Each line quantity must be greater than zero
- Each line item must exist; inactive items are accepted because receipts may post long after the source purchase document was created
- Each line storage location must exist; inactive locations are accepted for historical purchase execution continuity
- quantity and unitId preserve the source/business receipt unit, such as the purchase 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
- unitCost is optional and is used by goods receipt valuation during posting
- unitCost must be zero or greater when provided
- No StockLevel, InventoryLedger, LotStockLevel, SerialNumber, or valuation changes occur while the execution is DRAFT

## Process Flow

```mermaid
flowchart TD
    A[Create goods receipt request] --> D{At least one line?}
    D -->|No| E0[Return error: EMPTY_RECEIPT_LINES]
    D -->|Yes| E[Validate each line]
    E --> F0{All quantities positive?}
    F0 -->|No| F[Return error: INVALID_QUANTITY]
    F0 -->|Yes| G{Items and locations valid?}
    G -->|No| H[Return validation error]
    G -->|Yes| I[Create DRAFT InventoryExecution]
    I --> J[Create IN InventoryExecutionLine rows]
    J --> K[Return execution and lines]
```

## External Dependencies

- [item-management::Item](../../../item-management/docs/model/Item.md) - Validates referenced items
- [inventory::StorageLocation](../model/StorageLocation.md) - Validates receiving locations
- [inventory::InventoryExecution](../model/InventoryExecution.md) - Creates the goods receipt execution header and inbound execution lines

## Error Scenarios

- **EMPTY_RECEIPT_LINES**: No goods receipt 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
- **INVALID_UNIT_COST**: Unit cost is negative
- **ITEM_NOT_FOUND**: Referenced item does not exist
- **STORAGE_LOCATION_NOT_FOUND**: Referenced storage location does not exist
- **LOT_NOT_FOUND**: Referenced lot does not exist
- **SERIAL_NOT_FOUND**: Referenced serial number 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 line unit cost is negative
- returns error when item does not exist
- returns error when primary unit differs from item primary unit
- creates a DRAFT goods receipt execution with inbound lines
- accepts inactive item and location references
