# LotStockLevel

## Description

LotStockLevel tracks the on-hand and blocked quantities of a specific lot at a specific storage location. It provides the lot-level granularity needed for traceability, FEFO (First Expired, First Out) picking strategies, and lot-scoped inspection/quality holds.

Two quantity buckets are maintained: `onHand` (the total physical quantity of the lot at the location) and `blocked` (the portion of onHand that is under inspection hold or quality quarantine). The available quantity at the lot level is derived as `onHand - blocked`. Lot stock levels are updated internally when stock movements referencing a lot are executed (receiveStock, issueStock, confirmStockAdjustment).

## Domain Model Definitions

### Model type

Standard

### Command Definitions

- Lot stock levels are updated internally by stock movement commands when a lotId is specified:
  - [receiveStock](../commands/ReceiveStock.md) - Increments onHand; also increments blocked when toBlocked=true
  - [issueStock](../commands/IssueStock.md) - Decrements onHand; also decrements blocked when fromBlocked=true
  - [confirmStockAdjustment](../commands/ConfirmStockAdjustment.md) - Updates onHand/blocked based on adjustmentType and fromStockCategory

### Query Definitions

- Lot stock levels are included in lot queries

### Models

- LotStockLevel

### Invariants

- Unique per lot-storageLocation pair
- `onHand` is the total physical quantity of the lot at the location (includes blocked portion)
- `blocked` is the portion of onHand under inspection or quarantine; 0 <= blocked <= onHand
- Available at the lot level = `onHand - blocked` (computed, never negative)
- Goods issue from available cannot exceed `onHand - blocked`
- Goods issue from blocked cannot exceed `blocked`
- Internal transfer preserves the lot association

### Relationships

- **Belongs to Lot**: Each lot stock level belongs to a single lot
- **References StorageLocation**: Each lot stock level tracks quantity at a specific storage location
