A commercial landscaping company running forty-five maintenance contracts had a pricing model that worked at proposal time and a cost structure nobody tracked after the work started. Margin estimates lived in the proposal. Actual costs (crew hours, material purchases, equipment time) lived in separate records that were never reconciled against the contract until the accountant sorted it out at quarter end.
The problem
The company ran forty-five commercial maintenance contracts: office parks, retail properties, and an HOA portfolio. Contracts were annual, priced per-visit with seasonal scope adjustments for mowing cycles, mulching, and winter prep.
Estimating was accurate on account types the owner had priced before. New property configurations and large scope changes were where the bids drifted. A retail strip with heavy hardscaping and drainage work took 30 percent more crew hours per visit than the proposal assumed. The owner suspected it but could not quantify the margin impact across a contract year without pulling a week of records by hand.
Cost data existed in pieces. Crew hours were in a timesheet app, logged by day and by crew but never by job. Material purchases were in the bookkeeping ledger associated with the purchase date but not the contract that consumed them. Equipment hours were on a paper log in the truck cab that reached the office when someone remembered to bring it in.
What we built
A job costing tool that associates costs with contract numbers rather than dates. Crew timesheets are captured with a job code that maps to the contract, so the weekly labor summary shows hours by contract, not just by crew and day. Material usage is tagged to the contract at the point of entry: the crew lead records what was used on-site, or invoices are matched to the job schedule after delivery. Equipment hours pull from a structured end-of-shift log the foreman fills before leaving the property.
Each contract card shows: the estimated weekly cost from the proposal model, actual labor hours and cost for the current visit cycle, cumulative actual cost against the annual contract budget, and current margin versus the proposal estimate.
Contracts where actual hours cross a configurable threshold (15 percent over the estimated hours for that job type and property size) appear in a flagged list. The owner reviews flagged contracts before deciding whether the variance is a data issue, a scope change that was not repriced, or a systematic underbid that needs a renewal conversation.
The pricing model lives in an editable table the owner controls. When labor rates change or a scope adjustment is negotiated mid-contract, the owner updates the model, sets an effective date, and future visits calculate against the revised estimate. Historical records are unchanged.
What the owner sees
Each Monday: a contract summary showing last week's actual costs against estimated costs, per account. Flagged contracts appear at the top with the specific variance: estimated 8.5 hours, actual 12.0 hours, 3.5 hours over at a known labor burden rate.
For any contract, the owner can pull the full visit history: estimated cost per visit versus actual cost, across every service date in the contract year. That view distinguishes systematic underbids, where actual hours are consistently high relative to the estimate across every visit, from episodic overruns caused by a scope exception, a weather cleanup, or a crew change.
New bid estimates use the same interface. The estimator enters the property type, size, and scope; the tool pulls the cost history from comparable accounts and shows the actual average hours per visit for that category alongside the proposed estimate. The proposal anchors to data rather than memory.
What changed
The repricing conversation changed first. At contract renewal the owner could show actual visit-by-visit cost data rather than a general sense that the account was running thin. Contracts that were unprofitable got repriced or exited with data to back the decision. Contracts that were profitable confirmed the pricing model for that property type and became reference points for new bids.
The scoping process changed second. When the estimator priced a new retail strip, they pulled the cost history from similar accounts (actual hours per visit by season and by property size), and the proposal reflected what the crew actually took rather than what the last comparable bid assumed.
Equipment hours became visible for the first time. The owner had always known that certain equipment-heavy accounts eroded margin; they now had a per-account breakdown that made the equipment cost a line item in the renewal conversation rather than an untracked drag on the overall book.
