# AverageCost

## Description

AverageCost is an append-only history of the moving average per item and company, one row per costed event. Each row carries the state before (`quantityBefore`, `unitCostBefore`), the event applied to it (`eventType`, `quantity`, `unitCost`), and the state after (`quantityAfter`, `unitCostAfter`); rows are ordered by a 1-based `sequence` per item and company, and the greatest-sequence row is the current average. A RECEIPT folds in at its actual cost (`quantity` positive), an ISSUE draws quantity down at the average in effect (`quantity` negative) and never changes the average. A COST_ADJUSTMENT — appended by [postAcquisitionCostAdjustment](../command/PostAcquisitionCostAdjustment.md) when an invoice-driven adjustment reprices on-hand stock — moves value without quantity: its `quantity` is zero, its `unitCost` is null, the pool quantity is unchanged, and the value added is read from the before/after states (`quantityAfter × unitCostAfter − quantityBefore × unitCostBefore`).

AverageCost is price state only; quantities are tracked by [CostLayer](./CostLayer.md) and [CostLayerConsumption](./CostLayerConsumption.md). The two cross-check: the current row's `quantityAfter` equals the company's total layer remaining quantity.

Rows exist only under AVERAGE policies.

## Domain Model Definitions

### Model type

Standard

### Command Definitions

- Rows are appended internally by [postInventoryLedger](../command/PostInventoryLedger.md) and by [postAcquisitionCostAdjustment](../command/PostAcquisitionCostAdjustment.md) (COST_ADJUSTMENT events); no direct command

### Query Definitions

- The current average is resolved internally by costing as the greatest-sequence row; no read query yet

### Models

- AverageCost

### Invariants

- Rows are append-only with a unique 1-based sequence per item and company; the greatest sequence is the current moving-average state, and each row chains from the previous (quantityBefore/unitCostBefore equal the prior row's after values)
- The value equation holds for RECEIPT and ISSUE rows: `quantityAfter × unitCostAfter = quantityBefore × unitCostBefore + quantity × unitCost`; COST_ADJUSTMENT rows move value without quantity, so their added value is `quantityAfter × unitCostAfter − quantityBefore × unitCostBefore`
- Quantity chaining depends on the event: RECEIPT and ISSUE rows move stock (`quantityAfter = quantityBefore + quantity`); COST_ADJUSTMENT rows reprice it (`quantityAfter = quantityBefore`, `quantity` zero)
- RECEIPT rows carry a positive quantity at the actual acquisition cost; ISSUE rows carry a negative quantity at the average in effect and leave the average unchanged; COST_ADJUSTMENT rows carry no event unit cost (`unitCost` null, the only rows that do)
- COST_ADJUSTMENT rows may move the average down; the resulting `unitCostAfter` is zero or greater
- An issue never exceeds the current on-hand quantity; belongs to the item and the company of the movement location's site

### Relationships

- **References Item**: Each row belongs to an Item from the item-management module
- **References Company**: Each row belongs to a Company from the organization module
