NOVUS / RESTAURANT

Documentation

How a price change is detected

The four-part key a purchase price must match before a change is calculated, the window behind weekly impact, and when a figure is withheld instead of estimated.

Last reviewed against the product on .

The price changes surface at /app/price-changes reads your own imported invoices, not the market. This page sets out the one comparison it makes, where the numbers in it come from, and the situations in which it refuses to produce a figure at all.

What is compared with what

A price change is the difference between the two most recent unit prices in a group, and a group is narrow on purpose.

The four things that must match before a change is calculated
Part of the keyHow it is derivedIf it is missing
SupplierThe supplier record the row was imported againstThe row cannot be stored at all
ItemItem name lowercased, with punctuation collapsed to single spacesThe row is rejected at import
UnitUnit text trimmed and lowercasedRecorded as unspecified and never compared
CurrencyThree letters, uppercasedRecorded as unspecified and never compared

Measured from comparisonKey, normalizedUnit and normalizedCurrency in src/lib/purchasing/intelligence.ts.

Two prices from different suppliers are never compared here, however similar the item. That is a different question with different evidence behind it, and it belongs to what a saving is.

Where a unit price comes from

The importer prefers a unit price column when the file carries one and the value is not negative. Where it does not, a unit price is derived by dividing the line total by the quantity, and only when the quantity is greater than zero. Where neither route works, the product carries no unit price and the table prints "Unavailable" rather than a number.

One price is kept per purchase date, and the most recent 52 dates are retained. The change you see is between the last two of them, so a week with three deliveries at three prices contributes one price to the comparison, not three.

Weekly impact, and the window behind it

The default sort is absolute weekly financial impact, not percentage movement. A small rise on something you buy every day outranks a large rise on something you buy twice a year, which is the ordering a kitchen can act on.

Usage window
56 days
ending at your latest purchase date, never shorter than 7
Price dates kept
52
one unit price per distinct purchase date
Prices compared
2
the latest and the one before it
Purchase rows read
10,000
the most recent rows for your organization

Measured from buildPurchasingIntelligence in src/lib/purchasing/intelligence.ts and QUERY_LIMIT in src/lib/purchasing/queries.ts.

The formula is the price difference multiplied by the observed weekly quantity, where weekly quantity is the total quantity bought inside that window divided by the number of weeks in it. The seven-day floor matters more than it looks: if every purchase of an item sits on one day, the window is still treated as a week, so a single large delivery reads as a week of usage.

The anchor is your latest invoice, not today

Every window on the page is measured backwards from the most recent purchase date in your organization, and the header prints that date. Stopping imports therefore does not make the page calm, it freezes it. A quiet page with an old anchor is a reporting gap, not a stable month.

Where a figure is withheld

The weekly increase total in the summary row is the sum of positive weekly impacts only, kept separately per currency. Two currencies are never added together, here or anywhere else on this site.

What a price change does not tell you

It does not tell you why. A supplier who shrinks the case while keeping the same unit text on the invoice produces a rise on this page that is really a pack change, and nothing in the imported data can tell the two apart. Checking the pack is the first thing to do with any row that surprises you.

It also does not tell you what you consumed. Weekly quantity is what you bought in the window, so a stock-up before a closure inflates it and a week of running down the walk-in deflates it.

Finally, two prices are a step and not a trend. The page retains a long history per product but compares only the last two dates in it, so a return to a normal price after a brief spike shows as a fall.

Where to look next

The import contract is what decides whether a row arrives with a usable unit and currency in the first place, and it is where most unavailable cells are actually resolved. For market movements rather than your own, see reading analytics.