# Variant Generation

## Overview

Variant generation creates product variants from the combination of attribute values on an ACTIVE product. Each variant represents a unique attribute combination (e.g., Red/S, Red/M, Blue/S, Blue/M). Upon generation, each variant creates a corresponding Item in the item-management module with a SKU produced by an injectable SKU generation strategy, inheriting the product's UoM configuration.

## Business Purpose

Variant generation is the bridge between the commercial product view (product-management) and the operational SKU view (item-management):

- Product teams define the product structure (product + attributes) in product-management
- Variant generation materializes this structure into concrete, tradeable Items
- Each Item receives a unique SKU produced by the injectable SKU generation strategy (default: sequential numbering based on product code, e.g., `CLASSIC-TSHIRT-001`)
- Generated Items can then participate in inventory, sales, and purchasing workflows independently

This separation ensures:

- Product structure changes (adding a new color) can be planned before creating SKUs
- Only ACTIVE products can generate variants, preventing premature Item creation
- The relationship between a product and its generated Items is tracked for traceability

## Process Flow

```mermaid
flowchart TD
    A[Product - ACTIVE] --> B[Collect attribute assignments]
    B --> C[Compute attribute value combinations]
    C --> D{For each combination}
    D --> E[Check if variant already exists]
    E -->|Exists| F[Skip]
    E -->|New| G[Create ProductVariant record]
    G --> H[Call item-management createItem]
    H --> I[Link Item to ProductVariant]
    I --> D
    D -->|All done| J[Generation complete]
```

SKU generation logic is **injectable**. Consumers can provide a custom SKU generation strategy when configuring the module; a sensible default is shipped out of the box. The generator receives the product code, axis values, and the current variant count as input and returns a SKU string. The default strategy produces sequential numbering based on the product code, avoiding coupling to attribute value labels:

```mermaid
flowchart LR
    A["Product code: 'CLASSIC-TSHIRT'"] --> B["Variant count: 0"]
    B --> C["SKU: CLASSIC-TSHIRT-001"]
```

Custom strategy examples include attribute-value slug (`CLASSIC-TSHIRT-RED-M`), prefix by brand (`ACME-CTSHIRT-001`), or hash-based (`CT-a3f8b2`).

## Scenario Patterns

- **Full Generation**: A product with Color (Red, Blue) × Size (S, M, L) generates 6 variants. Each variant creates an Item in item-management with a SKU produced by the configured SKU generation strategy (default: `CLASSIC-TSHIRT-001` through `CLASSIC-TSHIRT-006`)
- **Incremental Generation**: A new color (Green) is added to a product. Re-running generation creates only the 3 new variants (Green/S, Green/M, Green/L), skipping existing ones
- **Single Axis**: A product with only one attribute (e.g., Size: S, M, L) generates 3 variants
- **Generation Blocked**: Attempting to generate variants from a DRAFT or ARCHIVED product is rejected
- **Axis Structure Locked**: Once a product is ACTIVE, the set of assigned attributes is locked. New attributes cannot be assigned; only new values can be added to existing attributes
- **Generated Item Independence**: After generation, the Item's lifecycle is independent — deactivating an Item in item-management does not affect the product or other variants
- **Variant Traceability**: Each ProductVariant record links the product, the specific axis values, and the generated Item ID for full traceability

## Test Cases

- Variants can only be generated from ACTIVE products
- Each variant represents a unique combination of attribute values
- Duplicate combinations are skipped during generation (idempotent)
- Each generated variant creates exactly one Item in item-management
- Generated Item SKU is produced by the injectable SKU generation strategy (defaults to sequential numbering based on product code)
- A custom SKU generation strategy can be provided at module configuration time
- The strategy receives product code, axis values, and current variant count, and must return a unique string
- The default strategy avoids coupling SKUs to attribute value labels, ensuring label updates do not create inconsistencies
- Generated Item inherits the product's configured UoM
- Generated Items are created in DRAFT status (requiring explicit activation in item-management)
- ProductVariant records store the product ID, axis value combination, and generated Item ID
- Variant generation fails atomically if any Item creation fails (no partial generation)
- The set of assigned attributes is locked on non-DRAFT products — new attributes cannot be assigned after activation

## Reference Links

- [Odoo Variant Creation Modes](https://www.odoo.com/documentation/19.0/applications/sales/sales/products_prices/products/variants.html)
- [Akeneo Family Variant Levels](https://help.akeneo.com/pim/serenity/articles/what-about-products-variants.html)
