Skip to main content

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​

ValueComputed as
raw_material_countLive raw materials
raw_material_low_stockMaterials where current_stock <= reorder_level
raw_material_valueΣ (current_stock × last_purchase_price)
product_countLive products
product_out_of_stockProducts whose variations sum to current_stock <= 0
product_stock_valueΣ (variation.current_stock × variation.price)
production_openOrders in DRAFT or IN_PROGRESS
production_completed_monthOrders completed since the start of this calendar month
sales_units_month`Σ
sales_value_month`Σ (
purchase_value_monthSame over PURCHASE rows
wastage_value_monthSame 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_stockReads the ledger
raw_material_low_stocksales_units_month
raw_material_valuesales_value_month
product_out_of_stockpurchase_value_month
product_stock_valuewastage_value_month
Stock value reads zero on a correctly-operated tenant

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 reached

It 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".

Sales value uses the selling price, purchases use cost

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​

DimensionBehaviour
OrganisationAlways scoped to the caller's org
ProjectOptional. When supplied, matches rows for that project or with a NULL project
Monthdate_trunc('month', CURRENT_DATE) — calendar month, not rolling 30 days
The project filter deliberately includes unassigned rows

(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.*.

Cockpit Inventory figures are visible without any Inventory permission

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​

SymptomCause
Stock value is ₹0current_stock is unset; operations do not write it
Everything is low stockSame cause
Sales this month is 0 but the storefront is busyStorefront orders write no ledger row
production_open never counts in-progress workIN_PROGRESS is never assigned
Figures reset at month startFour of them are calendar-month, by design
A tile disagrees with a screenCheck which of the two numbers each is reading