Purchase lots, a product catalogue, and the supplier manifest
Modelling stock that is bought before it is counted — a product catalogue, declared sub-lot specifications, pre-arrival expected quantities, and a browser-side importer for the inconsistent spreadsheets suppliers actually send — plus the TypeORM migration-ordering hazard that had already caused an outage.
Status
Shipped, 10 July 2026.
The problem
Stock arrives as a purchase lot — a pallet or a van-load bought from a supplier, described in advance by a spreadsheet, and only later unpacked and counted. Before this, the system had assets but no concept of what was expected, so there was nothing to reconcile against.
What was built
A product catalogue, and assets linked to it. The point is that a hundred identical ThinkPads should share one product record carrying the specification, rather than each device carrying its own free text. Sub-lots gained a declared specification — what the seller said this tranche would be.
Pre-arrival fields on the purchase lot so a lot exists, with expected quantities and a supplier, before a single device is touched.
The supplier manifest: the expected inventory, and a client-side CSV/XLSX importer for the list the supplier emails over. Parsing in the browser rather than on the server was deliberate — the files are small, the formats are inconsistent, and the operator needs to see what was understood before it is committed.
Vocabulary. "Purchase Lot" and "Sub-lot" were fixed here and have held ever since. Naming the domain early is why later features could be described in the operator's own words.
The deploy guardrail documented the deploy process and, more importantly, the
migration-ordering hazard: TypeORM SELECTs every mapped column, so
deploying an entity that declares a new column before its migration adds that
column makes every query on that table 500. This had already caused a an early phase
outage taking /assets, /lots and /notifications down.
It is written down because it is not intuitive and it recurs.
What was deliberately not built
No supplier portal, no EDI. The manifest is a spreadsheet because that is what suppliers actually send.
Open questions
None outstanding. The reconciliation engine that consumes the manifest followed the next day.
A published copy. Commit references and internal identifiers have been removed and the operator is not named; the engineering, the counts and the stated limits are unchanged.