# UpdateProduct

## Permission Scope

product

## Overview

updateProduct modifies mutable fields of an existing product — name, description, and UoM. The product can be looked up by `id` or `code`. The set of updatable fields may depend on the product's lifecycle status: UoM can only be updated in DRAFT status, while name and description can be updated in any status.

## Business Rules

- Target product must exist (looked up by `id` or `code`)
- Name can be updated in any status (DRAFT, ACTIVE, ARCHIVED); must remain non-empty
- Description can be updated in any status
- UoM can be updated only in DRAFT status — once activated, UoM is locked to preserve variant consistency
- UoM must reference an existing active Unit from the primitives module
- At least one field must be provided for update

## Process Flow

```mermaid
flowchart TD
    A[Receive update request] --> B{Lookup by id or code}
    B -->|Not found| C[Return error: PRODUCT_NOT_FOUND]
    B -->|Found| D{Any field provided?}
    D -->|No| E[Return error: NO_FIELDS_TO_UPDATE]
    D -->|Yes| F{UoM change requested?}
    F -->|Yes| G{Status is DRAFT?}
    G -->|No| H[Return error: UOM_LOCKED]
    G -->|Yes| I{UoM valid and active?}
    I -->|No| J[Return error: INVALID_UOM]
    I -->|Yes| K[Apply updates]
    F -->|No| K
    K --> L[Return updated product]
```

## External Dependencies

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

## Error Scenarios

- **PRODUCT_NOT_FOUND**: Specified product ID does not exist
- **MISSING_REQUIRED_FIELD**: One or more required fields are missing or empty
- **NO_FIELDS_TO_UPDATE**: No updatable fields were provided in the request
- **UOM_LOCKED**: UoM cannot be changed after product has been activated
- **INVALID_UOM**: Referenced unit does not exist or is inactive

## Test Cases

- returns error when product not found
- returns error when no fields provided
- returns error when name is empty
- returns error when UoM locked on non-DRAFT
- returns error when UoM is invalid
- updates description successfully
- updates UoM successfully on DRAFT product
- updates name successfully
- looks up product by code and updates name
- passes custom fields through
