# ConfirmInventoryAdjustment

## Permission Scope

inventoryControl

## Overview

confirmInventoryAdjustment confirms an inventory adjustment, generating a stock movement and updating on-hand quantities and valuation. This command can be called from either DRAFT (bypassing the approval workflow) or APPROVED status. Once confirmed, the adjustment is immutable. The behavior varies by adjustmentType:

- **CORRECTION**: Generates a stock movement to/from a virtual adjustment location.
- **SCRAP**: Generates a stock movement to a virtual scrap location. Updates lot stock levels if a lot is specified. Transitions serial number to SCRAPPED state if a serial number is specified.

## Business Rules

- Adjustment must exist and be in DRAFT or APPROVED status
- For negative adjustments: on-hand quantity must be sufficient (unless the organization permits negative stock)
- CORRECTION: generates a stock movement to/from virtual adjustment location
- SCRAP: generates a stock movement to virtual scrap location
- SCRAP with lot: updates lot stock levels
- SCRAP with serial number: transitions serial to SCRAPPED state
- Updates on-hand quantity on the StockLevel record
- Updates inventory valuation
- Adjustment becomes immutable after confirmation

## Process Flow

```mermaid
flowchart TD
    A[Receive confirm request] --> B{Adjustment exists?}
    B -->|No| C[Return error: ADJUSTMENT_NOT_FOUND]
    B -->|Yes| D{Status is DRAFT or APPROVED?}
    D -->|No| E[Return error: ADJUSTMENT_INVALID_STATUS]
    D -->|Yes| F{Sufficient on-hand stock?}
    F -->|No| H[Return error: INSUFFICIENT_ON_HAND]
    F -->|Yes| I{adjustmentType?}
    I -->|CORRECTION| J[Generate stock movement to/from virtual adjustment location]
    I -->|SCRAP| K[Generate stock movement to virtual scrap location]
    K --> K1{Lot specified?}
    K1 -->|Yes| K2[Update lot stock levels]
    K2 --> K3{Serial specified?}
    K1 -->|No| K3
    K3 -->|Yes| K4[Transition serial to SCRAPPED]
    K3 -->|No| L
    K4 --> L
    J --> L[Update on-hand quantity]
    L --> M[Update inventory valuation]
    M --> N[Update status to CONFIRMED]
    N --> O[Return confirmed adjustment]
```

## External Dependencies

- None (internal models: [StockMovement](../models/StockMovement.md), [StockLevel](../models/StockLevel.md), [LotStockLevel](../models/LotStockLevel.md), [SerialNumber](../models/SerialNumber.md), [ItemValuation](../models/ItemValuation.md))

## Error Scenarios

- **ADJUSTMENT_NOT_FOUND**: Referenced adjustment does not exist
- **ADJUSTMENT_INVALID_STATUS**: Adjustment is not in DRAFT or APPROVED status
- **INSUFFICIENT_ON_HAND**: Negative adjustment would reduce on-hand below zero

## Test Cases

- returns error when not found
- returns error when already confirmed
- returns error when negative adjustment exceeds on-hand
- confirms CORRECTION from DRAFT (no approval)
- confirms CORRECTION from APPROVED
- confirms SCRAP from DRAFT
- confirms SCRAP from APPROVED
- CORRECTION generates stock movement to virtual adjustment location
- SCRAP generates stock movement to virtual scrap location
- SCRAP updates lot stock when applicable
- SCRAP transitions serial to SCRAPPED when applicable
- updates on-hand quantity
- updates inventory valuation
