See which roofing jobs actually made money in JobNimbus
Open one screen every Friday to see contract value, cash collected, material and labor cost, and gross margin on every recent roofing job.
Build me an app that my owner and office manager open every Friday to see whether each roofing job actually made money. JobNimbus has no job costing built in, so the app has to assemble it from the records that are already there.
The main surface is a sortable job profitability table covering a lookback window that defaults to the last 90 days. One row per job, pulled with JobNimbus List Jobs. Columns: job name and number, customer, current status, contract value, cash collected, material spend, labor cost, gross profit in dollars, and gross margin percentage. Every column sorts, and the default sort puts the worst margin at the top. The margin cell turns red when it falls below a target margin the user sets in the app. Above the table put a summary strip: jobs scored, total contract value, total cash collected, blended gross margin, and how many jobs came in under target.
Joining the data is the core of this app. Every JobNimbus record carries a jnid, and the records attached to a job are found with the filter DSL clause {"must":[{"term":{"related.id":"<job jnid>"}}]}. The handlers use that clause to scope List Estimates, List Invoices, List Payments, List Material Orders and List Work Orders to each job. Contract value comes from the job's estimates via List Estimates and its invoices via List Invoices: show the estimate total and the invoiced total as separate figures so the office manager can see when the invoice never caught up with the estimate. Cash collected comes from List Payments. Material spend is the sum of the job's material orders from List Material Orders.
Labor is derived, not stored. Read the job's work orders with List Work Orders and price them against a crew and subcontractor rate sheet I keep in Google Sheets, read with Get Values. The rate sheet has one row per crew or subcontractor with the rate and whether it is hourly or per square. Store the spreadsheet id and range in app settings so I can point it at a different tab later. If a work order references a crew that is not on the rate sheet, flag that row as missing a rate rather than silently treating the labor as zero, and exclude it from the summary blend.
Jobs still in production are shown as provisional rather than scored. Let the user pick which job statuses count as finished; anything outside that set gets a provisional badge, a greyed out margin, and is excluded from the summary totals. A job that is half installed and half invoiced should never be presented as a real margin number.
Settings the user controls in the app: the target margin percentage (default it to 35 percent, since roofing labor typically runs 30 to 40 percent of the ticket leaving 20 to 30 percent for overhead and profit), the lookback window in days (default 90), which statuses count as finished, and the rate sheet location. These are shared app settings, not per user, because the owner and the office manager need to be looking at the same numbers.
Clicking a row opens a job detail page. The header repeats the margin math for that job. Below it: the estimate line items, fetched per estimate with Retrieve an Estimate so I can see quantities and prices rather than just a total; every material order on the job with vendor, date and total; every work order with the crew and the priced labor the app calculated; every invoice with its amount and status; and the full payment history with dates and amounts. Include a billed versus collected line so an unpaid balance is obvious at a glance.
Each job also gets an Investigate margin button, on the table row and on the detail page, that kicks off a background agent for that one job. The agent reads the job with Retrieve a Job, then walks its estimates, material orders, work orders, invoices and payments using the same related.id filter, pulling individual estimates with Retrieve an Estimate for line item detail. Its job is to work out where the money leaked. Have it look for the patterns that actually cause this in roofing: an extra material order placed after the estimate that was never billed, a change order that never made it onto an invoice, a second crew trip on the work orders that was never priced into the contract, and payments collected below the invoiced total.
The agent writes its findings back into the app so the owner can read them on the job detail page: a list of findings, each with a dollar impact and the specific records it used as evidence. It posts the same summary onto the job in JobNimbus as a note using Create an Activity. And whenever it finds work that was done but never invoiced, it opens a follow up task with Create a Task, assigned to the office manager with a due date a few days out, naming the amount and exactly what needs to be billed.
Show the agent's state inline on the row and the detail page: idle, running, or last investigated at a given time. Keep previous findings so I can see what an investigation said last month, and do not post a duplicate note on the job if I run the investigation twice on the same day.
What does this prompt do?
- Lists every job from the last 90 days in one sortable table, with contract value, cash collected, material spend, labor cost and gross margin side by side
- Turns margin red the moment a job falls below the target you set, so the worst jobs surface before you forget the details
- Prices labor from a crew and subcontractor rate sheet you keep in Google Sheets, so the labor number reflects what you actually pay
- Opens a full job detail view with the estimate line items, every material order and work order, and the complete payment history
- Gives every job an Investigate margin button that sends a background agent to find where the money leaked, write the findings back into the app, post a note on the job, and open a follow up task when work was done but never billed
What do I need to use this?
- A JobNimbus account with permission to read jobs, estimates, invoices, payments, material orders and work orders, and to add notes and tasks
- A Google Sheets rate sheet listing your crews and subcontractors with what each one costs per hour or per square
- A target gross margin you want jobs measured against, and the job statuses you consider finished
How can I customize it?
- Set the target margin that decides when a job turns red, and the lookback window the table covers
- Choose which JobNimbus job statuses count as finished, so jobs still in production stay provisional instead of being scored
- Point the app at a different rate sheet tab, or add crews and rates to the sheet as your subs change
FAQs
Does JobNimbus do job costing on its own?
What if I do not have a rate sheet yet?
How does it handle jobs that are still in progress?
Does it change anything in JobNimbus?
What does the Investigate margin button actually do?
Related templates
Stage a batch of filings overnight, then approve each completed form from a screenshot before anything is ever submitted.
Review every conversation Fin closed as resolved, judge which ones actually stuck, and see what the gap is worth against your bill.
Work every return, damage and warranty claim in one queue, with the order, the delivery date and a policy-backed recommendation already on screen.
See every install this week day by day, with the crew, the homeowner, whether materials were ordered, and the latest jobsite photos.
See exactly which ingredients next week needs based on what you actually sold, adjust anything by hand, then build a one-click grocery cart.
See follower growth, posting cadence, format mix and engagement rate for your brand and every competitor you track, side by side on one board.
Stop rebuilding job costing in a spreadsheet every Friday.
Get one screen that shows the real margin on every roofing job, and an agent that explains the bad ones.