Rebuilding a quoting estate from raw tables

Spreadsheet costing models do not throw errors. They return zero, and the zero goes out on the quote. This page describes what one of those estates contains when every formula cell in it is read. It covers what replaces the estate, and which of our own numbers did not survive an adversarial pass. The corrections are here in place of the originals, along with the parts that are still unfinished.

What the estate looks like before anything is built

Read the estate before proposing anything. Every formula cell gets extracted into an addressable record and counted by function. That census settles what kind of system it is, before anyone draws an architecture. A lookup chain over flat tables, with part-code string surgery repeated tens of thousands of times, does not need faster arithmetic.

In an estate of well over a hundred thousand formula cells, fewer than one cell in a hundred carries an error guard. A lookup that misses prices the line at nothing. The save gates check every field except the price, so the zero reaches the quote database without a flag.

Three structural problems show up in the same reading.

The cost basis sits two hops outside the quoting tool, on a network share, reachable only by a relative path. Nobody we asked could say where it lives. Both of the tool's own refresh routines abort at their own guards, and have done for the better part of a year. It quotes off frozen data, and nothing surfaces that either.

Field observation

The optimiser behind the annual price rebuild runs in seconds. Feeding it takes weeks, because well over a thousand of its inputs are typed by hand with no source and no date. In one cell, someone had read a dimension out of the part number by eye and typed it into the formula.

What the data looks like when it arrives

The export sets the schedule, so read it before planning anything.

A part-numbering grammar exists on paper and is implemented nowhere. The only decoder in the estate is marked not-validated by its own author, and the file shows it had never once been evaluated. A rebuilt parser reads every distinct sold code but one.

The ERP and the quoting tool are not speaking the same part-code language. On an entire component family, not one code matched. The join a plant assumes it has between quotes, jobs and purchases does not exist anywhere.

Material prices are stale in a way that depends on how you count them. Most dated parts have not been bought in over a year. The input the shop itself says reprices fastest sits at a median of four years since its last purchase. Weighted by dollars rather than by part count, about three quarters of material spend comes from a purchase under a year old. Both halves belong on the page with the basis stated, or the freshness model reads as a contradiction.

A required input is sometimes never delivered at all. It can be recovered arithmetically from cached outputs, with zero variance inside any machine. We have seen the real table surface later and confirm such a recovery on every code.

The word "coverage" takes three different answers in the same system, and the flattering one carries the least information. About nine in ten machine hours carry a rate. Not one unit cost can be computed end to end from a bill and a routing.

Start with a reading of your own files

The first useful thing is a reading of what your files actually contain, before anyone proposes a build.

Start a conversation

What gets built, and in what order

Order matters more than scope here, because each step is the gate on the one after it.

  1. Extract the estate into flat tables with a re-runnable script. The raw tables become the interface: exports today, a live feed later, with the same table shapes and the same formulas on top. Nothing in the engine may depend on a number that exists only in a spreadsheet cell.
  2. Reconcile before claiming anything. Every priced line of the estate's own cached cost arithmetic reproduces to the cent, with no mismatches, before a single new number is trusted. The check recomputes at page load in about eighty milliseconds, so the room watches it run.
  3. Put a basis on every term: observed, derived, assumed, gap or typed. An inherited value is derived and never observed. An ambiguous one refuses. Every derived value carries its observation count, its age, its source and a status, and the count is gated after outlier trimming rather than before.
  4. Register the sources, keeping freshness and trust on separate axes, and carry an absent source as a row rather than as a blank.
  5. Hold one definition of cost, enforced by test. The parameter-first builder does not call the composer directly, even though that is the shorter path. A test asserts that both paths return identical terms, bases and amounts.
  6. Build the modules on top of that: quoting, costing, promise dates, and a chat that answers from the warehouse only.

The costing engine runs to roughly forty thousand lines, with a second implementation in the browser held to field-for-field parity by the deploy gate. 534 tests cover the platform and engine code. The deploy refuses on a parity failure. A copy gate reads the rendered text of every view, collapsed sections included, against a rules file, and refuses on any match. After a deploy lands, the live URL gets fetched again, because a deploy command returning zero is not evidence that anything changed.

What the engine refuses to do

Every quote comes back in one of three states: fully costed, a named floor with the missing items listed, or refused outright. There is no separate object for a refusal, so no caller can total a bill without noticing that it was refused.

A gap line carries no amount at all. It names the table, the row, the role who can close it and what closing it unlocks. Gaps render in violet, because a gap is information and red is not in the palette. A configuration the engine cannot price cannot be saved or sent.

What we do differently

The chat gets no data in its context. It calls a tool, and the tool answers from the warehouse. A guard in the code then checks every number in the reply against the tool field it came from. The guard fails closed, because an adversarial pass found thirty ways past the pattern-matching version of it.

Scrap, rework, packaging, freight, duty and any burden outside the machine rate are not in the model. The page says so beside the total.

Where a named person approves

Nothing sends on its own. The engine stops at the number and a person carries it forward, which is the rule the rest of the design is arranged around. An override never overwrites: a typed value lands beside the derived one with an author, a timestamp and a reason.

The honest limit is worth stating plainly. The quote lifecycle, the guarded transitions and the five-step approval path are built on the server and tested. Nothing on the quoting screen calls them today. Approval is the desk's own review before a number leaves the plant. Write-back into the ERP stays cut, so no figure reaches a customer record without a person putting it there. An approval queue with per-person identity is the next build, and it is not shipped.

What the measurement changes

Actual time collapses as lot size rises, which is what a standard with no setup term cannot see.

Lot sizeMedian actual time over the standard
11.82
41.00
Above a dozen0.69

Break-even sits between four and six pieces. Single-piece work is under-costed and batch work over-costed by the same standard.

The obvious objection is selection: perhaps large-batch parts are different parts. Four independent tests say otherwise.

Three of our own headline numbers moved when an adversarial pass attacked them, and every correction went the less flattering way for us.

The fitted time model was scored on records held out of the fit against the incumbent standard, on the cells both methods answer. Median error 11.4 minutes against 17.4, R-squared 0.81 against 0.62, closer on 65 per cent of those cells. The caveat travels in the same sentence: most of the labour dollars come from a family-level rung rather than from the individual part's own records.

We audit our own output with the same instrument we use on the estate. An extracted table held the same records twice, so every absolute derived from it had been exactly double. A second, separate doubling turned up the same week. Both were corrected, and the coverage percentages never moved, because only the absolutes were affected. Of 382 proposals written by readers, 122 survived a skeptical re-measurement. Hundreds of dead ends are written down so nobody reopens them.

An operational headline can move fifteen points depending on how jobs are keyed, so the keying rule prints beside the figure. The measure is called schedule adherence, never on-time delivery, because adherence is what gets measured.

A complete lead-time rule can sit in the quoting tool with nothing reading it, while the desk types delays as free text. Quoting from such a rule can promise sooner than a contract allows. The tool prints the rule and the contracted term together, and says which one is longer.

What is not measured

No before-and-after exists, and inventing one would contradict the discipline the rest of the page describes. Four things a buyer reasonably asks for are absent.

Each of these can be asked for, and each requires the plant's own records to answer. None of them is asserted here in the meantime.

What is still open

The method behind this work is written up desk by desk in AI for manufacturing. The same reading applied to physical operations appears in physical AI, and to buying and stock in AI for supply chain.

Questions people ask

How long does work like this take?
We publish no cycle time, because the honest answer depends on what the export contains. Two things set the pace. The first is whether the estate's own cached arithmetic reproduces, which is the gate before any new number is trusted. The second is how many inputs exist only as typed cells with no source, because each one becomes a named ask with an owner. A shop whose job times are recorded against the operation moves faster than a shop that records against the day.
What does it need from our team?
Exports, and answers to a ranked list of gaps. Every gap the engine hits becomes a row naming the table, the row, the role who can close it and what closing it unlocks. The list arrives ordered by what each answer is worth. The ranking is rebuilt from the registry on every page load. Our own defects are excluded from that list, so your effort figure is never inflated by our work.
Where does our data sit, and where does the model run?
Your data is designed to sit at rest on your own server in Canada, one dedicated machine per client. That move is a decision taken and not yet executed, and this work does not run on one today. Inference runs one of two ways and you pick. It runs on that same server with an open-weight model, so nothing leaves the box. Or it runs through a frontier model under a written zero-data-retention control, with the model tier named in the contract. Zero retention is not available for every tier.
Does this work with our ERP?
It reads the ERP and replaces none of it. The raw tables are the interface: flat exports today, a live feed later, with the same table shapes and the same formulas on top. Nothing in the engine may depend on a number that exists only in a spreadsheet cell, so a fresh export refreshes the whole thing. Expect the part codes to disagree between systems. We have seen an entire component family where not one code matched.
What do the first thirty days look like?
Forensics before build. Every formula cell in the estate gets extracted into an addressable record and counted by function. That census settles what kind of system it is, before anyone proposes an architecture. The tables come out next, with an extraction script that can be re-run. Then comes the reconciliation against the estate's own cached arithmetic. Only after that does the first costed line appear, with a basis on every term and a named refusal on every gap.
What does the engine refuse to do?
It refuses to price a line it cannot trace, and it refuses to return a zero in place of an answer. A gap line carries no amount at all. It names the table, the row, the role who can close it and what closing it unlocks. A configuration the engine cannot price cannot be saved or sent. Scrap, rework, packaging, freight, duty and any burden outside the machine rate are not in the model, and the page says so.

Contact

Start with a reading of your own files

Tell Derik which ERP you run and where your quoting rules and costs live. He will tell you what a reading of your files would find before anyone proposes a build.

Prefer to talk? Book a meeting.

Your message goes to Derik Lawlis, the founder.