# GenerateVariants

## Permission Scope

product

## Overview

generateVariants creates product variants from the cartesian product of attribute values assigned to an ACTIVE product. Each new variant creates a corresponding Item in item-management with a SKU produced by the injectable SKU generation strategy (default: sequential numbering based on product code). Generation is idempotent — existing axis value combinations are skipped.

The SKU generation strategy is injectable at module configuration time. The default strategy produces SKUs like `CLASSIC-TSHIRT-001`, `CLASSIC-TSHIRT-002` using sequential numbering per product. This avoids coupling SKUs to attribute value labels, ensuring label changes do not create inconsistencies. Custom strategies can implement any pattern (attribute-value slug, brand prefix, hash-based, etc.).

## Business Rules

- Target product must exist and be in ACTIVE status
- Product must have at least one attribute with assigned values
- Each unique combination of attribute values produces one variant
- Existing combinations are skipped (idempotent generation)
- Each new variant creates exactly one Item in item-management via createItem
- Generated Items are created in DRAFT status
- Generated Items inherit the product's configured UoM
- SKU is produced by the configured SKU generation strategy (receives product code, axis values, and current variant count for sequential numbering)
- ProductVariant records store productId, axis value combination, and generated itemId
- Generation fails atomically if any Item creation fails (no partial generation)

## Process Flow

```mermaid
flowchart TD
    A[Receive generate request] --> B{Product exists?}
    B -->|No| C[Return error: PRODUCT_NOT_FOUND]
    B -->|Yes| D{Status is ACTIVE?}
    D -->|No| E[Return error: INVALID_PRODUCT_STATUS]
    D -->|Yes| F[Collect all attribute assignments and values]
    F --> G{Any attributes assigned?}
    G -->|No| H[Return error: NO_VARIANT_AXES]
    G -->|Yes| I[Compute cartesian product of attribute values]
    I --> J{For each combination}
    J --> K{Variant already exists?}
    K -->|Yes| L[Skip]
    K -->|No| M[Generate SKU via strategy]
    M --> N[Create Item in item-management]
    N --> O[Create ProductVariant record]
    O --> J
    J -->|All done| P[Return generated variants]
```

## External Dependencies

- [item-management::createItem](../../../item-management/docs/commands/CreateItem.md) - Creates an Item for each new variant with generated SKU and inherited UoM

## Error Scenarios

- **PRODUCT_NOT_FOUND**: Specified product ID does not exist
- **INVALID_PRODUCT_STATUS**: Product is not in ACTIVE status (DRAFT or ARCHIVED)
- **NO_VARIANT_AXES**: Product has no attributes with assigned values
- **ATTRIBUTE_NOT_FOUND**: Specified attribute ID does not exist
- **ATTRIBUTE_VALUE_NOT_FOUND**: Referenced attribute value no longer exists (data integrity check)
- **ITEM_CREATION_FAILED**: Item creation in item-management failed (e.g., duplicate SKU) — entire generation is rolled back

## Test Cases

- should return ProductNotFoundError when product does not exist
- should return InvalidProductStatusError when product is not ACTIVE
- should return NoVariantAxesError when no attribute assignments exist
- should return AttributeNotFoundError when referenced attribute no longer exists
- should return AttributeValueNotFoundError when referenced value no longer exists
- should skip existing variant combinations (idempotency)
- should return ItemCreationFailedError when item creation fails
- should generate multi-axis cartesian product variants
- should only generate new combinations when some already exist
- should generate variants successfully
