The grand total resolves in priority order: the link's total_amount, then the snapshot's grandTotal, and only as a last resort material + labor + markup. The markup term was previously computed and then omitted from that final sum.
Also called: contract priced at cost · missing markup · wrong total on contract
- 1grandTotal = link.total_amount || snapshot.grandTotal || (materialCost + laborCost + markupCost).
- 2The same value drives {{estimate.total}}, the subtotal (total minus tax), and every payment-stage amount derived from a percentage.
- 3The sync-estimate path can override it with the live version's total.
Quoted from the code: 'Markup belongs in the last-resort total. It was computed here and then left out of this sum, so a snapshot missing both link.total_amount and grandTotal produced a contract priced at cost — the builder's entire margin silently absent from a document the customer signs.'
- A fallback total that silently dropped the builder's margin
- Payment stages computed from a wrong total
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 →