What it is
How fast each variant sells, and how long the stock lasts. Sold 30/90/180d are raw units. Sales/day (weighted) blends those windows — recent weeks count more. Sales/day (season removed) is the same rate with the seasonal swing taken out, so periods are comparable. Planned demand/day is what procurement actually plans with: the weighted rate times the season factor of the period a purchase placed today would cover, times lifecycle and any manual factor. Days of Stock is stock divided by planned demand. Every factor is exposed as its own column, so an agent can cite the exact calculation path for any number it reports.demand_status (READY / LOW_HISTORY / NO_SALES_HISTORY / MANUAL_FORECAST / INSUFFICIENT_DATA) and demand_confidence (high / medium / low) say how much history backs the rate: under 180 days of history the windows shrink and the weights renormalize (READY); under 30 days the rate is measured since launch (LOW_HISTORY); no sales plus a manual target becomes MANUAL_FORECAST.
How it gets data
Computed view — derived automatically from Orders / Order Line Items, Products, and Procurement Config. Read-only; no ingest endpoint. To change the numbers, change the inputs (sales data, product master data, config). Sales are counted per variant onorders.placed_at, with refunded/expired/voided orders excluded via financial_status. Both shops are summed when several feed one workspace.
The view lists every active product, including products that procurement does not track (procurement_trackable = false, e.g. families bought manually). It is a sales statistic, not an order list — the tracking filter lives only in the Procurement Queue.
Fields
Identity & stock
Raw sales windows
Demand rates & blend weights
Seasonality & coverage window
Planned demand & its factors
Trend & momentum (per SKU)
These three columns answer one question: is this SKU selling faster or slower than it was? They compare the last 28 days (four complete weeks) with the last 90 days, both with the seasonal swing removed, so a December spike does not read as a trend.
Worked example: Marquis 3021 sold 21 units in 28 days (0.75/day) and 45 in 90 days (0.50/day). 0.75 ÷ 0.50 = 1.50; after removing the season, momentum reads 152, so
RISING. With 21 units it is medium confidence.
| momentum_delta_pct | Momentum Δ vs 90d % | number | The same momentum as a growth delta: momentum_pct − 100. +52 means 52 % above the 90-day pace, −30 means 30 % below. Read this one; keep momentum_pct for thresholds |
Prior year & 90-day outlook
The buyer’s second question: how does this SKU run against last year, and what did the coming quarter look like last time? Prior-year windows are the same calendar windows shifted back exactly 365 days.
Read them left to right: momentum (now) → YoY (against last year) → next 90d prior year (what came) → forecast (what to expect) → stock and days of stock (does it last). Backtest on company level: prior year alone missed actual orders by 27–43 %, prior year × momentum by 5–22 %.
The trend never changes Planned demand/day. Trend is a signal; the order quantity comes from the weighted rate and the season factor, so a spike is not counted twice. Family-level versions of the same three columns live in Family Trend.
All columns are read-only. The view also carries
tenant_id / workspace_id for tenant isolation — filtered automatically, never selected.
How last year’s season enters the plan
There is no “last year” column on this view, yet last year’s Black Friday is in every planned number. It arrives through two pieces:- The seasonal factor per month. Seasonality measures, from this tenant’s own sales history, how much each calendar month sells relative to an average month — November at 1.6 means November sells 60 % above average. Every past year of history feeds that factor, and the factor is damped when only one or two years exist.
- The coverage window. An order placed today does not sell today. It arrives after the lead time (
coverage_window_start) and has to last until the target stock days run out (coverage_window_end). The season factors of the months inside that window are averaged intocoverage_window_factor.
forecast_daily_demand = deseasonalized_daily_demand × coverage_window_factor × lifecycle_multiplier × manual_demand_multiplier.
So when a purchase manager asks in September “what do I need for Black Friday?”, the engine already answers it: the window of an order placed now reaches into November, and November’s factor lifts the planned rate by exactly what November did in previous years. Reading 365-day columns is not needed for that; they exist for volume context (units_sold_365d), not for the plan.
