# Inventory Adjustment

## Overview

Inventory adjustments are manual corrections to on-hand stock quantities that reconcile system records with physical reality. Discrepancies arise from damage, theft, counting errors, receiving mistakes, or production variances. Adjustments are modeled as a `StockAdjustment` with `adjustmentType=CORRECTION`. Each adjustment specifies a reason code, the affected item and storage location, a quantity (always positive), and an adjustmentDirection (INCREASE or DECREASE) on its StockAdjustmentLines. When confirmed, the StockAdjustment posts through `postInventoryLedger`, generating InventoryLedger entries with `sourceType=STOCK_ADJUSTMENT`, updating the on-hand balance and impacting inventory valuation.

Adjustments may originate from a standalone correction (e.g., a worker discovers damaged goods) or as a follow-up to an inventory count that reveals a variance. Organizations can optionally enforce an approval workflow for adjustments that exceed a configurable quantity or value threshold. The erp-kit module provides a DRAFT → SUBMITTED → CONFIRMED lifecycle (with SUBMITTED → REJECTED → DRAFT for rework, and DRAFT → CANCELLED for abandonment). Applications route submitted adjustments through their own approval logic before calling confirmStockAdjustment or rejectStockAdjustment.

## Business Purpose

- **Accuracy**: Corrects system stock levels to match actual physical inventory, preventing downstream issues in order fulfillment and purchasing
- **Traceability**: Every adjustment records a reason code and creates InventoryLedger entries, satisfying regulatory and internal audit requirements
- **Valuation integrity**: Adjustments flow through to inventory valuation so that financial reports reflect the true cost of goods on hand
- **Loss visibility**: Categorizing adjustments by reason code (damage, shrinkage, counting error) enables analysis of inventory loss patterns and root-cause investigation
- **Integration with physical inventory**: Provides the mechanism to act on count variances discovered during cycle counts or full physical inventories

## Process Flow

```mermaid
flowchart TD
    A[Identify Discrepancy] --> B[createStockAdjustment with adjustmentType=CORRECTION]
    B --> C[Specify Item, Storage Location, Quantity, and adjustmentDirection on StockAdjustmentLine]
    C --> D[Assign Reason Code]
    D --> E[submitStockAdjustment]
    E --> F{Application approval workflow?}
    F -- No --> H[confirmStockAdjustment]
    F -- Yes --> G[Application: Custom Approval]
    G --> G1{Approved?}
    G1 -- Yes --> H
    G1 -- No --> I[rejectStockAdjustment]
    I --> J[Update and resubmit or cancelStockAdjustment]
    H --> K[Post through postInventoryLedger to create InventoryLedger entries with sourceType=STOCK_ADJUSTMENT]
    K --> L[Update On-Hand Quantity via StockLevel]
    L --> M[Update Inventory Valuation]
```

## Scenario Patterns

- **Damage write-down**: A site count reveals physically damaged units. A StockAdjustment(CORRECTION) with adjustmentDirection=DECREASE and reason code "Damage" removes the affected quantity from on-hand stock.
- **Shrinkage / theft**: Periodic checks or count results show missing inventory with no corresponding shipment. A StockAdjustment(CORRECTION) with adjustmentDirection=DECREASE and reason code "Shrinkage" records the loss.
- **Counting error correction**: A cycle count reveals more units on the shelf than the system shows. A StockAdjustment(CORRECTION) with adjustmentDirection=INCREASE and reason code "Counting Error" increases the on-hand balance.
- **Receiving error correction**: Goods receipt recorded the wrong quantity. A StockAdjustment(CORRECTION) with the appropriate adjustmentDirection (INCREASE or DECREASE) and reason code "Receiving Error" corrects the discrepancy.
- **Production variance fallback**: Actual yield differs from expected output, but the site is not using the manufacturing module or the discrepancy is discovered with no resolvable production-order or work-order source document. In that limited case, a StockAdjustment(CORRECTION) with the appropriate adjustmentDirection and reason code "Production Variance" reconciles the difference.
- **Threshold-based approval (application-level)**: A StockAdjustment(CORRECTION) exceeding a configured quantity or value limit is submitted and routed to a supervisor for approval before confirmation. The approval workflow is implemented at the application layer; the module transitions through SUBMITTED → CONFIRMED or SUBMITTED → REJECTED.
- **Bulk post-count adjustment**: After a full physical inventory count, the system generates one StockAdjustment(CORRECTION) per variance line, allowing batch review, reason-code assignment, submission, and confirmation.

## Test Cases

- An INCREASE adjustment increases on-hand quantity by the specified amount at the given location
- A DECREASE adjustment decreases on-hand quantity by the specified amount at the given location
- A DECREASE adjustment cannot reduce on-hand quantity below zero (unless the organization permits negative stock)
- Every confirmed StockAdjustment(CORRECTION) creates InventoryLedger entries carrying sourceType=STOCK_ADJUSTMENT that reference the originating StockAdjustment
- A reason code is required on every StockAdjustmentLine; confirmation without a reason code is rejected
- StockAdjustments in DRAFT status do not affect on-hand quantity or valuation until confirmed
- A StockAdjustment must be submitted before it can be confirmed; calling confirmStockAdjustment on a DRAFT is rejected
- When approval workflow is enabled (application-level), submitted StockAdjustments above the threshold remain in SUBMITTED until the application confirms or rejects them
- A rejected StockAdjustment returns to DRAFT status and can be updated and resubmitted
- A cancelled StockAdjustment does not generate InventoryLedger entries or change on-hand quantity
- Adjustments originating from a physical inventory link back via reasonCode for traceability
- Confirmed adjustments update inventory valuation consistent with the organization's costing method
- InventoryLedger entries are immutable after creation; corrections require a new, offsetting StockAdjustment(CORRECTION)
- A StockAdjustment(CORRECTION) with reason code `Production Variance` must be rejected or rerouted when a resolvable manufacturing `productionOrderReference` or `workOrderReference` exists; those cases must enter inventory through `ManufacturingScrapHandoff`

## Reference Links

- [SAP Goods Movement - Adjustment Posting (Movement Types 501/502)](https://help.sap.com/docs/SAP_S4HANA_ON-PREMISE/f42e93de3a7c4de2abb5ffb817785bef/4023cff7ddba1d65e10000000a174cb4.html)
- [Oracle Inventory Adjustments](https://docs.oracle.com/en/cloud/saas/supply-chain-and-manufacturing/25a/famoh/inventory-adjustments.html)
- [NetSuite Inventory Adjustment](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_N1624498.html)
