# Inventory reversal for sales returns

## Pattern: compensation, not mutation

- **Never update or delete** prior `inventory_stock_movements` rows. The table is append-only by design.
- Reversal is modeled as a **new `stock_in`** that **compensates** a specific prior **`stock_out`** using `reverses_movement_id` pointing at the original movement’s primary key.

## Direction

- Forward fulfillment (consume path) posts **`stock_out`** against the warehouse/item projection.
- Return processing posts **`stock_in`** for the same warehouse/item, for the compensated quantity, with **`reverses_movement_id`** set.

## Idempotent reversal

- Each compensating movement carries an **idempotency key** scoped to return id, return line, underlying stock-out movement, and quantity slice, so retries do not double-post stock.

## Linkage

- `reverses_movement_id` provides an immutable audit edge **compensation → original outward movement**.
- Additional context (sales order id, sales order line id, return id) is carried in **metadata** and reference fields for reporting joins.

## Ordering

- Compensation consumes **FIFO by original stock-out movement id** for the line, respecting portions already reversed by earlier compensating `stock_in` rows linked to the same stock-out id.
