SHORT VERSION
Busy but not profitable means nothing in the business is comparing what a job actually cost against what it was bid at. Labor hours, material, and extra work have to be attached to a job number while the job is still running, and then the job gets closed by setting actual against estimated, one job at a time. Until that comparison happens somewhere, the only number you have is the shop total for the month, and a shop total can’t tell you which jobs to price differently or which work to stop taking.
You’re busy and the money isn’t there, and what’s missing is the comparison. Somewhere before a job gets marked done, what it actually cost in labor and material has to get set next to what you bid it at. Most shops never do that anywhere, so the only number anybody sees is the shop total for the month. A total tells you whether it was a good month. It can’t tell you which jobs made it good, or which ones the good ones paid for.
Where the cost goes when it doesn’t go on the job
Revenue lands on a job by itself. You invoiced the customer, so the money is already attached to the work that earned it. Cost has to be put there on purpose, and it comes in from several directions at once.
Hours. Time gets recorded. But if the entry doesn’t require a job and a cost code, it lands as hours worked that week rather than hours on that panel swap. Drive time and the trip to the counter belong to a job too, and those are the first ones to end up nowhere.
Material. Your journeyman is standing at the supply house with a breaker in his hand and nothing on the ticket that says which job it’s for. He pays and he drives, because that’s what the job needs. The receipt rides in the truck for a week and lands as a shop expense in the month it was bought. The job it belonged to now looks cheaper than it was.
Extra work. Your guy is out on a service call and the customer asks him to take a look at a receptacle in the garage while he’s already got the panel open. He looks at it and he takes care of it, which is what you’d want him doing. Nothing in the way the job moves stops long enough for that to get priced, so the time and the material go onto a job that was never repriced.
Returns. Material goes back and the credit comes in against the account instead of the job that was overbought. The job keeps carrying material it never used.
None of that is anybody being careless. Every one of those is a piece of information with nowhere to land.

Why does a busy month still come out thin?
Because busy moves revenue and cost at the same time, and only one of them is easy to see. A full board means more overtime, more trips to the counter, and more callbacks worked in around scheduled jobs. If the margin is draining on one type of work, doing more of it makes the year worse while making the schedule look better.
The P&L shows you the month. It doesn’t break the month into jobs. So the best answer available at the end of the year is that it was an okay year, and nobody in the building can say which work you should have taken more of.
Close the job against the bid, one job at a time
A job is finished when its actual labor and actual material are attached to it and set next to what you bid it at. That’s one step added to closeout, and it’s the whole thing. Not a review somebody runs at the end of the month, and not a report anybody pulls in January.
For that to be one number taken off another, instead of somebody digging back through a month of receipts to rebuild the job, two things have to be true while the job is still open. The job number goes on the purchase at the counter before the material leaves, and it goes on the return when material goes back, so the credit comes off the job that paid for it. And time gets recorded to a job and a cost code, not to a day.
Change work needs somewhere to land before it happens. Priced, approved in writing, added to the job’s budget. Otherwise you’re setting what the finished job cost against the price of the original scope, before any of the extra work went into it.
You don’t need a year of history to start, and don’t go back and rebuild last year. Pick one type of work, service calls or panel swaps, and cost every one of them at close for the next couple of months. That’s enough to show you which of your work has been carrying the rest of it.
Common questions
Do I need job costing software to do this?
Not to start. What you need is a job number on every purchase and a job on every hour, and one place where the two get set against the estimate. Whatever you’re already running may do it. Whether it’s set up that way for how your work actually moves is a separate question, and worth checking before you buy anything else.
Should I raise my prices if I’m busy but not making money?
You can’t answer that until you know which jobs are losing. An across-the-board increase also raises the price on the work that was already profitable, which is usually the work you most want to keep winning. Cost a few months of jobs first, then you’re adjusting a price you can defend.
How long after a job should I cost it?
At closeout, while the receipts, hours, and change orders are still attached to it. Wait a quarter and you’re rebuilding the job out of memory, and the numbers you get back are guesses in a spreadsheet.
What if it turns out a job I already finished lost money?
That’s the information you were missing. A completed job you can’t change is still the most accurate estimate you’ll ever have for the next one like it. What costs you real money is finding that out after you’ve already bid ten more jobs the same way.

