Let's talk
engineering

Run every pricing formula twice, once on cost and once on selling, and never mix the results

The quoting system could tell a fabricator exactly what to charge for a bespoke item and could not tell them whether the item was worth building.

That is a normal state for quoting software and it is a bad one. The estimator adds a splashback and the total goes up. Whether the total went up by more than the splashback costs to make is not a question the system can answer, so the answer lives where it always did — in whether the owner feels the number looks right.

The fix is structurally simple and it is worth doing early, because retrofitting it is unpleasant. Every priced thing carries two rates, and every formula is evaluated twice.

Two runs, one set of rules

Each material and each labour or process item stores a selling rate and a cost rate. The engine takes a mode. In selling mode it resolves rates to selling prices; in cost mode to cost prices. Everything else — the same formulas, the same steps, the same material choices, the same dimensions — is identical.

Every feature on every line is therefore evaluated twice, and the difference between the two results is the gross profit on that feature. Divide by the selling result and you have the margin. Sum across features and you have it for the line.

The important property is that there is no second engine and no separate costing model. A costing model maintained alongside a pricing model is a costing model that is wrong, because the two get edited at different times by different people for different reasons. Here there is nothing to keep in step. If the pricing rule changes, the cost calculation changed with it, in the same commit, by construction.

The cost is that every quote calculation does twice the work. For interactive quoting at this scale that is not noticeable, and if it ever becomes noticeable the cost run is the one you defer, because nothing the customer sees depends on it.

Two things called margin, which are not the same thing

This is where the design is easy to get wrong, and where I have seen the confusion cause real arguments.

There is a markup that sets the price. Different classes of customer — a retail buyer, a builder, an architect specifying for a client — get different markups. That percentage is applied to the selling total to produce the customer-facing unit price. It is a pricing decision, it is commercial policy, and it changes what the customer pays.

There is a gross margin that reports on the price. It is the gap between the cost run and the selling run. It changes nothing. It is a measurement.

Keeping those separate in the code and in the vocabulary matters, because both are percentages and both are called margin in conversation. The moment someone writes a report that adds them together or presents one as the other, every number in that report is meaningless and it will look completely plausible.

The layering is fixed and worth stating explicitly: sum the per-feature selling costs, apply the customer-class markup to that sum, and you have the unit price. Quantity, discount, additional charges and tax all happen afterwards, at the quotation level, on top. Each stage has exactly one job and nothing is applied twice.

Where the second rate comes from when it does not exist

The rate data arrived with the two prices unevenly populated. Some rows had both. Some had only a selling price. Some had only a cost.

The derivation rules are the obvious ones. From a selling price, subtract an explicit margin amount if the source gives one; otherwise divide by an explicit margin percentage if it gives one; otherwise apply a default markup. From a cost, the same in reverse. An explicit amount takes priority over an explicit percentage, because an amount is a stated fact and a percentage is a rule.

The default markup is the one that matters, because it is a fabrication. It is applied where the source told us nothing at all, and the resulting number will be used to compute a margin someone may make a decision on.

So the rate card records, per row, where each of the two prices came from — stated in the source, derived from the other by amount, derived by percentage, or defaulted. Provenance per field, not per import.

Any derived value that a person will treat as a measurement must carry a note saying it was derived. Without it, a default markup applied to 40 rows during a migration becomes indistinguishable from real cost data six months later, and every margin report built on those rows is quietly fictional.

The business decisions that reshaped it

Two came out of the review with the client, and both narrowed the design in useful ways.

Selling price is only meaningful for items bought in and resold — a fridge, a branded unit. For materials consumed in fabrication, only the cost is real; what those materials sell for is not a concept the business has, because they are never sold as materials. So for the fabrication path the two runs draw on the same figures, and the margin that matters is the one created by the customer-class markup rather than by a rate spread.

And the markup percentage must never appear to a salesperson or on any customer-facing output. It is admin-only, configured against the customer class, invisible everywhere else.

That second one has an architectural consequence that is easy to miss. If the markup is hidden but the price it produces is shown, then any place that displays both a base figure and a final figure lets someone recover the percentage by division. Hiding a number is not the same as hiding the information, and the check has to be on what can be derived from the outputs, not just on which fields are rendered.

The limit

Per-feature margin is only as good as the cost data, and the cost data on this catalogue is a mix of stated figures and derived ones. The engine will report a margin to two decimal places on a feature whose cost was defaulted during a migration, with no visual difference from one whose cost was stated by the supplier.

The provenance is recorded, so the distinction is recoverable. It is not currently surfaced in the margin display, and until it is, the per-feature margin figures deserve to be read as indicative rather than as accounting.

The rule

If the same rules can produce both numbers, produce both, and do it by running the rules twice rather than by writing a second model. Keep the markup that sets a price and the margin that measures a price in separate words and separate fields. And record, for every derived rate, how it was derived, because in a year that is the only way anybody will know which of your margins are real.

Working on something like this?

We build this kind of software, and we staff the teams that do.

Get in touch