Unit-mismatch protection on every priced line

When the book prices per foot and the takeoff counts objects, the conversion is done for you — because forgetting it doesn't error, it just silently bills a 27-foot panel as one foot.

What it is

A single billable-quantity function that all pricing paths share. Lumber is emitted as pieces of stock but priced per linear foot, so the line's purchased footage (which already accounts for cutting waste) is used; panels and sheets fall back to count × length. A dedicated script asserts the invariant across the whole option matrix.

Also called: totals way too low · priced per foot but counted pieces · a 16 foot post billed as one foot · estimate total too low · priced per foot but counted per piece · pricing bug guard

See it
Unit-mismatch protection on every priced line
CustomerBuildingAmountStatus
Delia YoderRiding Arena$6,900Approved
Sutter KlineBarndominium$18,110Paid
Marlin HooverRiding Arena$6,520Sent
Ivy BrubakerEquipment Storage$2,340Paid
Sutter KlineBarndominium$3,860Paid
A materials row expanded to its stock lengths — '2x6 SPF · 10′ · 51 pcs' — with the per-foot rate and the resulting amount, showing pieces × length (InternalEstimateMaterials.tsx expandMaterialRows). Sample data — no customer information appears here.
How it works
  1. 1billableQty() converts counted units (pcs, panels, sheets) to feet whenever the book row is priced per LF.
  2. 2purchasedLf is preferred because it includes cutting waste; qty × lengthFt is the fallback.
  3. 3stockRowSellTotal() does the same for the expanded stock rows the materials tab shows, so the two surfaces agree by construction rather than by coincidence.
  4. 4Cut items with no standard stock length apportion the line's purchased footage by piece share.
  5. 5scripts/check-price-book-units.mjs walks the option matrix — not just the shipped presets — and fails on a mismatch.
Why we built it

Forgetting a unit conversion doesn't throw an error. It just bills a 27-foot panel as one foot, and the estimate looks fine. A per-foot price charged once per stick brought totals in at about a third of a real estimate; a corrected per-foot panel price counted against panel counts made a 4,000 sf roof come to $225; timber priced per truss billed 29.2 feet as 29 trusses and put $27,740 of timber on a 16ft porch, making a 30x40 shop cost $42 a square foot. A second version of the same failure priced fourteen of 34 line types at zero on a 30x40, so turning on a concrete slab and insulating four walls left the total unchanged — a line with no price contributes nothing and says nothing. Every priced line now converts between what the book quotes and what the takeoff counts, and the guard walks the full set of options after it was caught checking only three shipped presets, none of which turn on insulation, a cupola, a ridge vent, a liner, a partition, a hipped roof or a non-embedded foundation.

The problem
  • Per-foot prices charged once per stick
  • Options that silently cost nothing because their line had no price row
  • Two screens pricing the same building differently
Sound familiar?
What you get
A wrong unit fails a check instead of shipping a wrong quote
Every option you switch on costs what it costs
The list, the card and the workspace agree by construction

See it on your own jobs

Twenty minutes, your numbers, no slide deck. We’ll build one of your real buildings in front of you and send you the estimate link at the end — yours to keep either way.

or keep browsing features →