Stock
Availability per SKU, expressed as a status code derived from the date new stock is expected. It is a catalogue attribute, not a financial one, and it feeds no margin figure.
Stock is how many of a SKU are on hand, how many are available to sell, and when the next delivery is expected. It arrives from the Azure middleware as a CSV and is replaced wholesale on every run.
Where it comes from
app/jobs/azure/getproductstock.php consumes the azure_getproductstock batch type. It reads the SKU list from products, fetches the CSV, and writes productstock_new with insertmultiple(), because a full catalogue is tens of thousands of rows and a row per statement would not finish inside max_execution_time.
The table is then swapped in: productstock becomes productstock_old, productstock_new becomes productstock. The swap is guarded on row count and refuses when the new table has lost a larger share of the live table than ingest.swaptolerance in config/settings.json allows, so a truncated feed leaves yesterday's stock in place rather than emptying the catalogue, while a day on which the catalogue loses more SKUs than it gains still publishes.
The status code is derived, not delivered
The feed carries the date new stock is expected. middlewareazure->getstockstatus() turns that date into a code by how many days away it is:
| Days until new stock | Status | Reads as |
|---|---|---|
| -3 to 3 | 2 | ± 3 days |
| 4 to 7 | 3 | ± 1 week |
| 8 to 15 | 4 | ± 2 weeks |
| 16 to 23 | 5 | ± 3 weeks |
| 24 to 35 | 6 | ± 1 month |
| 36 to 66 | 7 | ± 2 months |
| 67 or more | 8 | Not available |
| -4 or earlier | 9 | Unknown |
| No usable date | 99 | Undefined |
Status 1, In stock, comes from the feed rather than from the date. The names live in config/reference/productstockstatus.json and are re-applied on every deploy.
The day bands are not configurable, and that is deliberate. They are the definition of the status codes: changing a band changes what "± 1 week" means, so it is a change to the meaning of the data, not a setting.
The status is relative to the day it was computed. It is recalculated on every run, so a stale run leaves a status that no longer describes the current distance to the expected date.
Tables
| Table | Holds |
|---|---|
productstock | One row per SKU: stock, available, expected date, status |
productstockstatus | The status names |
productstock is one of the tables not defined in install.php: it is created by the job that fills it, so a schema change to it is made there.
Where to look
Stock has no screen of its own. It is joined into the product views at /entities/products and is read by the downstream tools directly.
Related
- Azure middleware
- Products
- Prices, the other per-SKU feed on the same shape
Evidence
Import, the bulk insert and the guarded swap from app/jobs/azure/getproductstock.php. The day bands from middlewareazure->getstockstatus(). Status names from config/reference/productstockstatus.json. The bands being deliberately hardcoded from AGENTS.md, Configuration and .env. Tables created outside install.php from AGENTS.md, Models and database. Basis: code-checked at 30f5313.
- Type
object - Status
active - Updated
2026-09-15 - Created
2026-09-13