# Inventory

The Inventory API tracks stock across multiple physical locations — warehouses, stores, or branches — with full movement history and batch/lot traceability.

---

## Core concepts

### Locations
A location is any place where stock is held: a warehouse, a store, a shelf area, or a branch. Each location has a `name`, optional `code` (short label like `WH-01`), and can be linked to a seller `account_id` for multi-branch setups.

### Stock
Each listing has a stock quantity per location (`inventory_stock`). This is the live total — the sum of all batches at that location. It updates automatically on every receive, transfer, or adjustment.

### Batches / Lots
A batch is a specific physical delivery of a product with its own `lot_number` and `expiry_date`. The same listing can have multiple batches at the same location with different expiry dates.

**FEFO ordering:** All batch listings are returned sorted by expiry date ascending (soonest first) — First Expired, First Out. This ensures near-expiry stock is always actioned first.

### Movements (ledger)
Every stock change — receive, transfer, adjustment, sale, return — creates an immutable row in `inventory_movements`. The ledger is append-only and traces each movement to its batch, location, and the user who triggered it.

### Stock transfers
A transfer moves stock from one location to another. Stock is deducted from the source immediately on creation (status: `in_transit`). The destination is credited when the transfer is received. Cancelling a transfer in transit returns the stock to the source.

### Purchase orders
A purchase order (PO) records inbound stock from a supplier. POs support partial receiving — each line item tracks `quantity_ordered` vs `quantity_received`. Receiving a PO line creates inventory_movements and optionally creates/increments a batch (if `lot_number` or `expiry_date` is provided at receive time).

---

## Stock statuses

| Status | How it happens |
|---|---|
| In location | Batch/stock quantity > 0 at a location |
| In transit | Stock deducted from source, transfer not yet received |
| Damaged | Adjustment with negative delta and reason `damage` |

---

## Authentication

All inventory endpoints require admin access (`admin: 1` set by the gateway from JWT `user_roles`). Pass `tenant_id` on every request.
