# inventory-planner

Inventory, stock-control and supply-chain planning metrics pack for operations, retail, warehouse and procurement teams: compute the Reorder Point (reorderPoint) from demand rate, lead time and...


Inventory & supply-chain planning intelligence pack. Deterministic operations-research math (reorder
point, safety stock, EOQ, ABC, turnover, stockout risk, par levels) for ops, retail, warehouse and
procurement teams, with an optional AI stocking-policy layer on the ABC tool that activates only when
a model is reachable (and silently falls back to the heuristic core otherwise).

**Planning estimates only** — validate against your own demand data and supplier terms.

## Tools

| Tool | Args | Does |
|---|---|---|
| `reorderPoint` | `{demand, leadTime, safety?}` | Reorder point = demand×leadTime + safety. `safety` is units, or `{serviceLevel, demandStdDev}` to derive it. |
| `safetyStock` | `{serviceLevel, demandStdDev, leadTime, leadTimeStdDev?}` | z(SL)×σ×√leadTime; combined demand+lead-time form when `leadTimeStdDev` is given. |
| `eoq` | `{demand, orderCost, holdCost}` | Wilson EOQ + orders/year, cycle days, minimized total annual cost. |
| `abcAnalysis` | `{items:[{name,annualValue}], options?}` | Pareto A/B/C classification + per-class policy. `options.advise` adds AI advice. |
| `turnover` | `{cogs, avgInventory \| beginning+ending}` | Inventory turnover + days-on-hand + grade. |
| `stockoutRisk` | `{meanDemand, demandStdDev, leadTime, onHand}` | P(stockout) during lead time under a normal-demand model + implied service level. |
| `parLevel` | `{demand, leadTime, reviewPeriod, safetyStock? \| demandStdDev}` | Min / par (order-up-to) levels for periodic review. |

Only `abcAnalysis` has an AI path; its result is tagged `{ mode: 'heuristic' | 'llm' }`.

A self-contained normal CDF / inverse-CDF converts service level <-> z-score, so no stats library is needed.

## Example

```js
import pack from './index.js';
await pack.adapters.eoq({ demand: 12000, orderCost: 80, holdCost: 3 });
// { eoq≈800, ordersPerYear:15, cycleDays≈24.3, totalAnnualCost≈2400, … }

await pack.adapters.reorderPoint({ demand: 50, leadTime: 7, safety: { serviceLevel: 95, demandStdDev: 12 } });
// { reorderPoint≈402.2, leadTimeDemand:350, safetyStock≈52.2, safetyBasis:'serviceLevel 95% (z=1.645)' }

await pack.adapters.stockoutRisk({ meanDemand: 50, demandStdDev: 12, leadTime: 7, onHand: 380 });
// { stockoutRiskPct, serviceLevelPct, zScore, grade, … }
```

## DRY boundaries

- **`numbers`** owns generic scalar math and series stats; **`statistics`** owns general
  descriptive/inferential statistics; **`finance`** owns time-value-of-money. This pack owns
  *inventory-science composition* — EOQ, reorder point, safety stock, ABC/Pareto, turnover,
  service-level stockout risk and par levels — which none of those own.
- Self-contained: the only cross-pack import is `../_shared/llm.js` for the optional AI layer.

## Hybrid intelligence

Every deterministic core runs offline with no model. `abcAnalysis` accepts `options.advise:true` to
request LLM stocking-policy advice; with no model configured/reachable it returns the exact same
classification tagged `mode:'heuristic'`. A down model never throws.


---
Source: shared/engines/adapters/domain/inventory-planner/README.md
Canonical: https://docs.leumas.tech/p/adapters/domain/inventory-planner
