A project is a parent rollup for multi-visit jobs. Use them when one customer has several appointments, multiple invoices, change orders, and receipts on the same job. The project page shows total invoiced, materials, labor, profit, every child entity in one place - and a Documents & permits area for permits, plans, photos, or anything else worth keeping with the job.
When to use projects (and when NOT to)
- USE for a 6-week kitchen remodel: 8 visits, 12 invoices, 15 receipts, 32 labor hours.
- USE for a multi-week landscape install: 4 crews, 3 invoices for materials + labor, weekly progress visits.
- USE for any job over $5k that spans more than one visit.
- DON'T USE for a one-off service call: a single appointment + a single invoice doesn't need a parent.
- DON'T USE for recurring contracts: those have their own roll-up at /portal/contracts/[id].
Creating a project
- 1Go to /portal/projects → New project
Pick the customer, name the project (e.g. 'Master bathroom remodel'), describe scope, optionally set quoted total + start + expected completion.
- 2Address inherits from customer
Defaults to the customer's billing address. Override if the project is at a different site (rental property, second home).
- 3Save
You land on the project detail page with every section ready to fill in.
Adding child entities - inline + auto-linked
Each section card on the project page has a + New button (Schedule for appointments, Add receipt for materials, etc.). Click it and the matching create form opens with the customer pre-filled and the project tag already attached. No more bouncing between pages or hand-picking a project from a dropdown.
| Quotes | + New → quote composer with customer + project pre-filled. |
| Invoices | + New → invoice composer with customer + project pre-filled. |
| Appointments | Schedule → /portal/schedule auto-opens the new-appointment modal with customer + address pre-populated; project_id stamped on save. |
| Change orders | + New → composer with customer pre-selected; source list (the invoices/quotes you can amend) is scoped to this project's children. |
| Receipts | Add receipt → mobile-first capture flow; the project tag is preserved through OCR + save. |
Documents & permits
Each project has a Documents & permits section for file uploads - building permits, structural drawings, pre-job damage photos, inspection reports, scope-of-work PDFs. Up to 25 MB per file. Allowed: PDF, JPG/PNG/HEIC/WebP/GIF, Word, Excel, plain text.
- Owner + dispatcher + tech + billing can upload.
- Owner + dispatcher can delete (techs can't accidentally remove a permit the office uploaded).
- Every member of the workspace can view + download (the tech on site needs the permit handy).
- Files are stored privately. Each open generates a fresh time-limited signed URL - links don't leak permanently if a page is shared.
Naming the file 'IMG_0432.jpg' is normal; labelling it 'Front-yard tree damage - pre-job' makes it findable in 6 months when the customer disputes a charge.
What rolls up
| Invoiced | Sum of every linked invoice's total_cents. |
| Collected | Sum of every linked invoice's amount_paid_cents. |
| Materials | Sum of every linked expense's amount_cents. |
| Labor | Sum of every linked time_entry's cost_cents. |
| Net profit | Invoiced − materials − labor. Live updated as new entities link in. |
| Quoted vs invoiced | If you set a quoted_total_cents at create time, the project page shows variance (+ or − vs quoted). |
Click 'Mark complete' on the project detail page when work wraps. The project moves to a completed state with a completed_at timestamp - useful for year-over-year reporting + 'how long did this kitchen actually take?' analysis.