Inventory in the Cockpit
The Cockpit's Inventory tiles come from one endpoint — GET /api/v1/org/inventory/cockpit-summary
— computed live on request. Nothing is cached or scheduled.
1. The twelve values
| Value | Computed as |
|---|---|
raw_material_count | Live raw materials |
raw_material_low_stock | Materials where current_stock <= reorder_level |
raw_material_value | Σ (current_stock × last_purchase_price) |
product_count | Live products |
product_out_of_stock | Products whose variations sum to current_stock <= 0 |
product_stock_value | Σ (variation.current_stock × variation.price) |
production_open | Orders in DRAFT or IN_PROGRESS |
production_completed_month | Orders completed since the start of this calendar month |
sales_units_month | `Σ |
sales_value_month | `Σ ( |
purchase_value_month | Same over PURCHASE rows |
wastage_value_month | Same over WASTAGE rows |
2. The split runs straight through these tiles
Six read current_stock. Four read the ledger. They will not agree.
Reads current_stock | Reads the ledger |
|---|---|
raw_material_low_stock | sales_units_month |
raw_material_value | sales_value_month |
product_out_of_stock | purchase_value_month |
product_stock_value | wastage_value_month |
raw_material_value and product_stock_value are both current_stock × price. Since no
Inventory operation writes current_stock, a tenant that records every receipt, run and sale
through the operations screens shows a stock value of ₹0 and every material as low stock — while
purchase_value_month beside it reports real money spent.
The tiles are not broken. They are reading the other number. See How stock is counted.
3. Two more things worth knowing
production_open counts a status that cannot be reachedIt filters on DRAFT or IN_PROGRESS. The lifecycle only ever sets DRAFT, COMPLETED or
CANCELLED — IN_PROGRESS is defined in the model and never assigned. The tile is effectively "draft
orders".
unit_cost means different things per row type: on a SALE it holds the unit selling price; on a
PURCHASE it holds the unit cost. So sales_value_month is revenue and purchase_value_month
is spend — correct, but only because the same column is used for two purposes.
4. Scope
| Dimension | Behaviour |
|---|---|
| Organisation | Always scoped to the caller's org |
| Project | Optional. When supplied, matches rows for that project or with a NULL project |
| Month | date_trunc('month', CURRENT_DATE) — calendar month, not rolling 30 days |
(project_id = $2 OR project_id IS NULL). Records created before projects were assigned still count
toward the selected project's tiles.
5. Access
The endpoint is withAuth, not withRBAC — it checks that you are signed in, not that you hold
org.inventory.*.
Any authenticated user of the organisation can read aggregate stock value, low-stock counts and monthly sales and purchase totals from this endpoint. The individual screens are permissioned; this summary is not.
Which tiles a user actually sees is governed by the Cockpit's own widget gating, not by this endpoint.
6. Troubleshooting
| Symptom | Cause |
|---|---|
| Stock value is ₹0 | current_stock is unset; operations do not write it |
| Everything is low stock | Same cause |
| Sales this month is 0 but the storefront is busy | Storefront orders write no ledger row |
production_open never counts in-progress work | IN_PROGRESS is never assigned |
| Figures reset at month start | Four of them are calendar-month, by design |
| A tile disagrees with a screen | Check which of the two numbers each is reading |