# CreateItem

## Permission Scope

item

## Overview

createItem establishes a new item in the system with a unique SKU, name, unit of measure, and optional barcode. Items can be created in either DRAFT or ACTIVE status. DRAFT items allow review and correction before activation, while ACTIVE items are immediately available for transactions.

This command supports both careful item onboarding workflows (create as DRAFT, review, then activate) and rapid setup scenarios (create directly as ACTIVE).

## Business Rules

- SKU is required, must be globally unique across all items (active, inactive, and draft)
- SKU is immutable after creation — it cannot be changed once assigned
- Name is required
- Barcode must be unique across all items when provided
- UoM (unit of measure) is required and must reference an existing active Unit from the primitives module
- Default status is DRAFT if not specified

## Process Flow

```mermaid
flowchart TD
    A[Receive create request] --> B{Validate SKU format}
    B -->|Invalid| C[Return error: invalid SKU]
    B -->|Valid| D{SKU unique?}
    D -->|No| E[Return error: duplicate SKU]
    D -->|Yes| F{Barcode provided?}
    F -->|Yes| G{Barcode unique?}
    G -->|No| H[Return error: duplicate barcode]
    G -->|Yes| I{Validate UoM}
    F -->|No| I
    I -->|Invalid| J[Return error: invalid UoM]
    I -->|Valid| K[Create item record]
    K --> L[Return created item]
```

## External Dependencies

- [primitives::Unit](../../../primitives/docs/model/Unit.md) - Validates that the referenced UoM exists and is active

## Error Scenarios

- **DUPLICATE_SKU**: An item with the same SKU already exists
- **DUPLICATE_BARCODE**: An item with the same barcode already exists
- **UNIT_NOT_FOUND**: Referenced unit does not exist or is inactive

## Test Cases

- returns error when SKU already exists
- returns error when barcode already exists
- returns error when UoM does not exist
- creates item in DRAFT status by default
- creates item in ACTIVE status
- skips barcode uniqueness check when barcode is not provided
- passes custom fields through to insert
