DEV Community

Tim Carter
Tim Carter

Posted on • Originally published at toolbagcrm.com

Building progress billing into a CRM: the UX and data challenges

When we started building ToolbagCRM, we thought invoicing was the hard part. It wasn't. Invoicing is straightforward. Progress billing is where the data model gets weird and the UX gets opinionated.

Here's the problem. A contractor quotes a $40,000 kitchen remodel. The customer signs. Now what? You can't invoice $40k on day one, and you can't wait until month three to collect a dime. So you break it into milestones: deposit, rough-in complete, cabinets installed, final walkthrough. Each milestone has a dollar amount. Each one triggers an invoice.

Sounds simple. It isn't.

The data model problem

In a normal CRM, a quote becomes an invoice. One-to-one. Done. With progress billing, a quote becomes multiple invoices, each tied to a milestone, and the sum of all milestone invoices should equal the original quote total. But what if the customer adds a change order mid-project? Now you've got a modifier that needs to distribute across remaining milestones, or become its own milestone.

We went back and forth on this. Do milestones live on the job? On the quote? On the invoice schedule? We ended up tying them to the job record itself, with each milestone referencing the parent quote. That way, when you pull up a job, you see the full picture: what was quoted, what's been billed, what's left. The running balance is always visible.

The tricky part is the deposit. It's not an installment, it's a deposit. It comes off the top. So the data model needs to distinguish between a deposit (collected against the quote total) and a milestone payment (collected against a phase of work). They look the same on a receipt but they mean different things in the system.

The UX challenge nobody talks about

Here's what we learned from watching contractors actually use billing software: they bill at the wrong time. Not wrong as in fraudulent. Wrong as in suboptimal.

The best time to bill a milestone is right after the customer has watched you complete it. They saw the work. They're at peak willingness to pay. Bill before the phase starts and they're paying for something they haven't seen yet, which feels different to them even when the math is identical.

So we designed the flow around that. When a tech marks a milestone complete in the field, the system surfaces the invoice immediately. One tap to send. The customer gets a text with a payment link while the work is still fresh. ACH and card on the same page, with ACH defaulted on anything over a few thousand bucks (because card fees on a $6,000 deposit are real money).

The receipt is automatic. Business name, project, amount, what it covers. Not a hand-scrawled note. The receipt is part of the close.

What we got wrong early on

We originally let contractors set up freeform milestones with custom amounts. Total flexibility. Sounds great. In practice, most people don't want to think about it. They want a template: deposit at signing, two or three milestones through the job, final payment on completion. Pick the template, adjust the percentages, done.

The ones who need custom milestones still have that option. But the 80% case is a roofing job that looks like every other roofing job. Give them a starting point.

We also learned to write milestones into the quote from day one. Trying to introduce progress billing halfway through a job you originally quoted as one number is a conversation that goes badly every time.

The receipts matter more than you'd think

This one surprised me. Contractors would send a payment link, collect the deposit, and then... nothing. No confirmation. The customer is left wondering if the payment went through. A clean digital receipt with the project name, the deposit amount, and what it covers makes the customer feel like they just paid a professional. It's a small thing that closes more deposits than any feature we've built.

Progress billing in a CRM is one of those problems that sounds like accounting but is really UX. The data model needs to be right, sure. But the flow needs to match how contractors actually work in the field, not how accountants think about revenue recognition.

We're still iterating on it. If you're building something similar, I'd love to hear how you approached it.

Originally published at toolbagcrm.com

Top comments (0)