Estimates & the Budget Engine
How an estimate is built, how its numbers are actually calculated, and how it becomes a job.
On this page
Creating an estimate
- Go to CRM → Estimates → + New Estimate.
- Pick a client. Leads are labeled “(lead)” in the picker so you can tell them apart from active clients at a glance; inactive or cancelled clients don’t show up at all.
- Set the estimate date and a valid-until date — it defaults to 30 days out, but can be pushed further for a bid that needs more runway.
- Assign a sales rep.
From there you’re in the estimate detail view, where line items, direct costs, and the summary panel all live.
Estimate Builder: drafting line-item text from a transcript
Tools → Estimate Builder is a small AI-assisted writing aid, separate from the estimate detail view itself. It takes a sales-visit transcript and turns it into draft line-item wording you copy into a real estimate — it does not create or touch any estimate record on its own.
- Upload a transcript file (.txt or .vtt) or paste transcript text directly. For a .vtt file, the tool automatically strips the
WEBVTTheader, speaker-id lines, and timestamp lines before showing you the cleaned text. - Click Generate Proposal. The transcript is sent to an AI model that drafts professional, client-ready line-item descriptions — grouped by service type, with locations, quantities, and exclusions called out, and any ambiguous point (like whether weed killer was discussed) flagged inline for you to resolve.
- Click Copy to Clipboard and paste the wording into the appropriate line item on the actual estimate you’re building.
Estimate record — it only produces description text sitting in the browser tab until you manually copy it in. Always check scope, quantities, and pricing against what was actually measured/quoted before pasting it in, and resolve any clarification flags in the output first.Stage vs. approval status
These are two separate fields on the estimate, and they get confused constantly because they both sound like “where is this at.” Stage tracks the sales process. Approval Status is a separate internal sign-off gate that sits on top of it.
| Stage | What sets it |
|---|---|
| Draft | Default stage for a brand-new estimate. Still being built — line items and pricing are in flux. Drafts were never presented to a client, so Close Ratios and win-rate figures leave them out of both counts and amounts. |
| Quote | Set manually once the estimate is ready for internal review — the numbers are considered final pending sign-off. |
| Sent | Set when the estimate is actually delivered to the client (email, PDF, or the client portal). Blocked from actually going out if Approval Status is still Pending — see the callout below. Pipeline dashboards count Sent estimates as open pipeline alongside Draft and Quote. |
| Accepted | Set when the client accepts — in full or via a tiered/partial acceptance, whether you mark it in-app or the client accepts online through the proposal link. Once an estimate is Accepted, a Convert to Job button appears in its header; converting normally happens from here. |
| Lost | Set when the client declines — including a Decline in the client portal, which records the reason “Declined by client via portal” — or when an estimate is manually marked dead. Line items already marked “lost” individually (e.g. a tier the client unchecked when accepting) don’t count toward totals, and the Accepted Estimates by Service reports skip them. |
| Invoiced | Set once billing has started against the estimate (a deposit, milestone, or the full amount has been invoiced). |
Approval Status runs on its own track: Not Required, Pending, Approved, or Rejected. It exists to hold an estimate back regardless of what stage says.
Manual vs. production-rate budgeting
Every service has a configured Budget Method (in service settings), and every estimate line item snapshots that method the moment the line is added:
- Manual — budgeted hours are entered directly on the line, no formula involved.
- Production Rate — budgeted hours are derived:
hours = quantity ÷ the service’s sq ft per man-hour.
One override applies regardless of method: if the line’s unit type is hr (hourly), the entered quantity is the hours — there’s nothing to derive.
A worked example, start to finish
Say a “Mulch Installation” service is configured with Budget Method = Production Rate and a production rate of 1,000 sq ft per man-hour. A property’s Mulch Bed Sq Ft measurement is 8,000.
- Budgeted hours: 8,000 sq ft ÷ 1,000 sq ft/man-hour = 8 budgeted hours for one visit. With a single visit, total budgeted hours is also 8.
- Cost: the org’s breakeven (fully-burdened) labor rate is, say, $45.00/hr. Because the line’s Cost field is still at its never-set default of $0, it auto-fills the first time the line is added: 8 hrs × $45.00 = $360.00 total cost.
- Rate (price to the client): say the line is priced at $0.12/sq ft, quantity-based (calc type ×): 8,000 sq ft × $0.12 = $960.00 total.
- Margin: ($960.00 − $360.00) ÷ $960.00 = 37.5% gross margin — comfortably in the green band (30%+) on the line-item grid.
- Overhead: at the estimate level, that $360.00 in modeled line-item cost is bucketed as Labor cost and run through the org’s configured Labor overhead + Labor Burden percentages (set separately from the per-line breakeven rate) to arrive at the estimate’s overhead cost, which nets against gross profit to produce the estimate’s net profit figure in the summary panel.
Edit the Cost field directly at any point and that override sticks — the breakeven-rate auto-fill only ever applies while Cost is still exactly $0.
The B.Hrs cell has its own calculator popover for building that number up instead of guessing: enter Men and Hrs:Min to compose budgeted hours (e.g. 2 men for 2:30 = 5.0 hrs), or give it a target man-hour rate — defaulting to the org’s breakeven labor rate — and it solves for whichever of Cost or B.Hrs you leave it to fill in.
Why budget method is snapshotted per-line
It would be simpler for a line item to just read its service’s current Budget Method live, every time. The engine deliberately doesn’t do that: the method (and, for production-rate lines, the rate itself) is copied onto the line item at the moment it’s added, and stays there.
The reason is historical integrity. Say “Mulch Installation” is switched from Production Rate to Manual six months from now, or its production rate is retuned from 1,000 to 1,200 sq ft/man-hour after a crew turns out to be faster than assumed. Every estimate written before that change already has real budgeted-hours numbers baked into it — numbers a job may have been scheduled and costed against, or a client may have already accepted a price built on. If line items re-read the service live, changing one service setting would silently rewrite the economics of every past estimate that used it, with no record that anything changed. Snapshotting means an old estimate keeps meaning exactly what it meant when it was sent, and a service’s settings can be tuned going forward without touching history.
Complexity multiplier & Rate Matrix pricing
Two more inputs can override the plain manual/production-rate math above. Both are snapshotted onto the line item the moment it’s added or adjusted — same historical-integrity reasoning as budget method, above.
Complexity multiplier. Every line item has a Complexity popover (the icon next to the line’s notes button) set from 50% to 200%, defaulting to 100% (no adjustment). It scales the line’s Rate and Cost together, which is why it doesn’t move GM% — a harder job costs and prices proportionally more without silently changing margin. It also scales the effective hours used for cost, dashboards, and the total-hours column. Critically, the hours you see and edit on the line (“B.Hrs”) always stay the plain, unscaled number you typed or that production rate derived — complexity is applied fresh every time something re-reads the line, never baked back into the stored hours. That matters in practice: dial complexity up to 150%, then back down to 100%, and the line returns exactly to where it started instead of drifting.
Rate Matrix. A service can have banded pricing rows configured against one of a property’s custom fields (e.g. price breaks by Turf Sq Ft ranges). If the estimate has a property attached and that property has a value for the field a service’s matrix is keyed on, adding that service looks up the matching band and uses its rate, budgeted hours, and cost instead of the service’s flat production rate — the line is recorded as Manual budget method going forward, since its hours came from the matrix rather than a formula. No property on the estimate, no matrix rows configured on the service, or no value on that field, and the line falls through to the ordinary manual/production-rate behavior with nothing different. Like everything else here, the match is looked up once at add-time, not re-resolved later if the property’s field value or the matrix rows change.
Reading the line-item grid
The GM% column color-codes each line’s gross margin, calculated from Rate, Cost, and Adjusted Rate:
- Green — 30% or higher.
- Gray — 10% up to 30%.
- Red — below 10%.
Each line also has a Calc Type toggle between per-unit pricing (× — rate × qty × visits) and a fixed total ($ — the entered rate is the line’s total, regardless of quantity).
Overhead on the estimate as a whole is either one flat percentage applied to total cost, or — when the org has configured any per-type overhead rate — broken out by cost type instead:
| Cost type | Overhead setting used | Where it comes from |
|---|---|---|
| Labor | Labor Overhead + Labor Burden | Line items’ modeled cost (totalCostCents) is bucketed here, alongside any Direct Cost rows typed as Labor. |
| Sub-Contract | Contract Overhead | Subcontracted work entered as a Direct Cost. |
| Product/Material | Materials Overhead | Materials entered as a Direct Cost. |
| Asset/Equipment | Equipment Overhead | Equipment costs entered as a Direct Cost. |
| Service/Other | Other Overhead | Direct Costs typed as Service or Other — there’s no dedicated bucket for “Service,” so it shares Other’s rate. |
Both the breakeven labor rate and the per-cost-type overhead percentages are org-wide settings, not per-estimate — the breakeven rate is set from Equipt’s Job Costing bid-rate calculator (“Set as project rate”), and overhead percentages live in the org’s overhead settings.
Where zone measurements come from
Production-rate lines need a quantity to divide by the service’s rate — that quantity usually comes from a property’s zone measurements: Turf Sq Ft, Mulch Bed Sq Ft, Gross Sq Ft, Linear Ft Perimeter/Edging, Yards of Mulch.
The client-facing proposal link
Every estimate has a public proposal page — the same page a client lands on from the “View Your Proposal” button in the estimate email, where they can review the line items and accept, decline, or request changes online. You don’t have to send an email to get at it:
- Get link / Copy link in the estimate header puts the proposal URL on your clipboard. It reads Get link when no live link exists yet (clicking it creates one) and Copy link once there is.
- Open opens that same proposal page in a new tab — handy for checking exactly what the client will see before you send, or for walking a client through it on a call.
- The “N links sent” strip under the header offers the same Copy link / Open shortcuts once at least one link has gone out.
There is one live link per estimate. It’s minted the first time you ask for it (Get link / Open) or the first time the estimate is emailed, and every later copy, open, or send reuses that same URL instead of minting a fresh one — so a link you texted a client last week and the one in this week’s reminder email land on the same page. A link is good for 30 days; after it expires (or the client accepts through it) the next request creates a new one.
Taking a deposit on acceptance
Set Deposit Required on the estimate header and the client is asked for it as part of accepting the proposal, before the acceptance is recorded.
- Pay by card charges the deposit through Stripe there and then. It appears once your organisation has finished Stripe Connect setup; the amount always comes from the estimate, so the client can’t change what they’re charged. Your card processing fee applies on the same terms as an invoice payment (only above your threshold), and the client sees the split — deposit, fee, total — before confirming. They are credited the deposit; the fee is yours.
- Pay by bank transfer (ACH) appears if you have ACH turned on. No processing fee. A bank debit takes a few business days to clear, and the proposal is accepted straight away rather than waiting on it — see below.
- The manual methods (check, cash, ACH, credit card, other) do not charge anything. They only record that the client says they’re sending it, so you know to expect it — and reconcile it as a normal payment when it lands.
- Skip for now accepts the proposal with no deposit at all. A deposit never blocks acceptance.
Using it on the first invoice is a manual step — nothing is applied for you, because a converted job invoices its full amount with the deposit not deducted. The invoice tells you when there’s money waiting:
- Open the invoice. If the client has unapplied money, a blue bar reads “$2,000.00 of unapplied payments on this client (including a deposit) — $2,000.00 can go to this invoice”.
- Click Apply to this invoice. It uses the oldest money first, so a deposit is consumed before a later overpayment, and never applies more than the invoice still owes.
- The balance drops and the unapplied figure drops to match. Anything left over stays available for the next invoice. You can still do it the long way — open the payment and edit its allocation — if you want to split it differently.
If the deposit fails — a returned bank transfer (insufficient funds, closed account, a mistyped routing number) or a declined card — the proposal stays accepted. Only the money failed; nothing needs signing again. Three things happen:
- The estimate shows a red payment failed badge with the amount, the date, and the bank’s own reason on hover. That reason is the useful part — “insufficient funds” means ask them to try again, “account closed” means pick up the phone.
- You’re notified — a Deposit failed bell notification and an email, to whoever already receives proposal-decision notifications, plus the estimate’s sales rep. Both can be turned off individually under Notification Preferences.
- The client’s original proposal link re-opens itself so they can pay it again. Re-visiting it shows a “your deposit didn’t go through” screen with the reason and the card / bank-transfer buttons, instead of the usual thank-you. They can’t change the amount, and there’s no Skip button this time — skipping is a choice made before accepting, and by now the deposit is owed.
Converting an estimate to a job
Once an estimate is Accepted — whether you set the stage yourself or the client accepted online through the proposal link — a Convert to Job button appears in the estimate header. After a job has been created from the estimate, that same button reads View Job and jumps straight to it, so an estimate is never converted twice by accident.
- From the accepted estimate, click Convert to Job.
- Choose which line items to include — not every accepted line has to become part of the job. Lines that net out to $0 start unchecked so they don’t land on the job (and its invoice) as empty rows; tick them if you really want them.
- Pick a Job Type: One Time, Recurring, Project, or Waiting List.
- Set the scheduled date, assign a crew, and enter a Crew Size (men). The crew size is written onto the job and its first visit, so the Dispatch Board’s Men column is right from day one instead of reading 0.
- Confirm. The job is created and a “Job created” entry is logged on the client’s Activity timeline.