# Batch / Lot / Expiry / FEFO Foundation v23

## Lots

Inventory may now be tracked by lot/batch.

Each lot belongs to:
- tenant
- variant
- optional variant unit

Lot attributes:
- lot code
- manufactured date
- expiry date
- status
- metadata

Statuses:
- active
- quarantined
- recalled
- expired
- closed

## Lot balances

`inventory.lot_balances` stores rebuildable operational quantity by:
- warehouse
- lot

The existing `inventory.balances` remains the total operational balance for the variant/unit.

A lot-aware movement updates both balances atomically.

## Ledger

`inventory.movements.lot_id` is nullable.

The immutable movement ledger remains the inventory source of truth.

## FEFO

FEFO = First Expired, First Out.

The allocator chooses:
1. active lots only
2. positive stock only
3. non-expired lots only
4. earliest expiry first
5. lots without expiry last

Quarantined and recalled lots are never eligible.

## Foundation boundary

v23 provides FEFO allocation/preview but does not yet automatically allocate sale lines.

Automatic sale allocation will be added when batch-aware sale posting and purchasing receipts
are connected.

## APIs

- POST /api/v1/inventory/lots
- POST /api/v1/inventory/fefo/preview

## Permission

- inventory.lot.manage
- inventory.view for FEFO preview

## Traceability direction

Because movements retain lot IDs and immutable source references, the platform can later answer:
- where a lot came from
- which warehouses received it
- which sales consumed it
- recall / where-used queries

## Next

v24:
- weighted-average inventory valuation
- quantity + value ledger
- cost layers / receipt valuation boundary
- sale cost snapshot foundation
