Projects & Job Costing
One Projects table, two different screens to view it from, and a separate rate-calculator tool that feeds it — untangled.
On this page
Two things named "Project"
The word "Project" is overloaded in this platform, and that's the single biggest source of confusion here. Two unrelated things share the name:
- The Projects table. A single set of records — one landscaping job or contract each — used for cost tracking. There is only one
projectstable in the database. It has two screens onto it: Purchasing > Projects (this module — procurement-focused: Materials and Other Costs) and CRM > Scheduling > Projects (client-focused: Milestones, Billing, Analysis). Open a project from either screen and you're looking at the same underlying record — just a different set of tabs layered on top depending on where you came from. - "Project" as a CRM Job type. A CRM Job (a scheduled visit for a client) has a
typeofrecurring,one_time,waiting_list,package,snow, orproject. This is a scheduling classification — it just marks the job as one-off project work rather than recurring service. It is a completely separate field from the Projects table above. A CRM Job of any type — including one whose type happens to be "project" — can optionally be linked to a Project record for cost tracking, via aProject IDfield on the job. The two are independent: a recurring job can link to a Project, and a job typed "project" doesn't have to.
Creating a Project
From either screen, click + New Project. The dialog is the same form either way, since it's writing to the same table.
| Field | Notes |
|---|---|
| Project Name | Free text — e.g. "Smith Residence Backyard Renovation." |
| Customer / Client Name | Free text field (not a dropdown of CRM Clients). A project can separately carry a Client ID for billing — see below. |
| Address / City / State / Zip | Job site location. |
| Status | Sold, Scheduled, In Progress, On Hold, Complete, or Canceled. |
| Start Date / End Date | End Date defaults to "TBD" until set. |
| Contract Price | The editable field here is the ORIGINAL contract price. The Revised Contract Price shown elsewhere (Analysis, Change Orders, Milestone billing) is derived — original plus every approved change order — and is maintained by the database, not editable directly. |
| Budget Hours | Planned labor hours, compared against Actual Hours for a variance once logged. |
| Notes | Optional free text. |
A project's status runs through a flow — Sold → Scheduled → In Progress → Complete — with On Hold and Canceled as side branches, shown as a step indicator on the Details tab.
Assigning costs to a Project
Projects don't hold costs directly — they roll them up from other records. When adding a line item to a Requisition or a Purchase Order, each line has an optional Project field. Setting it assigns that line's cost to the project.
Materials can also be added straight from the project itself — the Materials tab's Add Material button lets you send items directly onto the project (a "direct" line with no source document), onto an existing Requisition or PO, or into a brand-new Requisition or PO pre-filled with those items and this project already set on every line.
Worked example: Smith Residence Backyard Renovation
A project pulls cost together from however many source documents touch it:
- Create the project: Smith Residence Backyard Renovation, customer "Smith," a Contract Price, and a start date.
- PO #1 — a paver order from the hardscape supplier. Two line items (category
project_material) are each tagged with this project. - PO #2 — mulch and plants from the nursery, placed a week later. Its line items are tagged with the same project.
- PO #3 — a follow-up order for extra edging once the crew realized more was needed. Tagged the same way.
- Open the project and switch to its Materials tab: all line items from all three POs appear in one table, each showing its item, quantity, unit cost, and which PO it came from (a clickable badge that opens that PO). The Subtotal, Sales Tax, an allocated share of each PO's Shipping cost, and a grand Materials Total are computed live underneath.
- As each PO is received, the same numbers keep reflecting committed vs. received spend — there's nothing further to do on the project itself to keep the rollup current.
If a subcontractor also poured a patio slab for this job, that cost has no PO — it goes on the project's Other Costs tab instead, as its own line (vendor, description, cost type, amount), separate from the Materials rollup but included in the project's total cost on the Details tab.
The Materials & Other Costs tabs
The Materials tab merges three kinds of line items into one view: Requisition lines, PO lines, and "direct" lines added straight to the project (no source document). Requisitions that have already been converted into a PO are excluded, so a converted requisition's items don't show up twice.
Rows behave differently depending on where they came from:
- Direct items can be edited or deleted right from the project.
- Requisition / PO items can only be viewed here — editing quantity or cost, or removing the line, has to happen on the source Requisition or PO itself. The row's Source badge opens that document directly.
The Materials Total is built from:
- Subtotal — quantity × unit cost, summed across every line.
- Sales Tax — each line's source document's tax rate, applied only to lines still marked taxable (non-taxable items like pallet deposits or delivery fees are excluded).
- Shipping — a PO's shipping cost is allocated across every project it touches, proportional to that project's share of the PO's subtotal.
The Other Costs tab is a flat, manually-entered list — no product catalog involved — grouped into Materials, Labor, or Other, each optionally tied to a Vendor. Its own subtotal by type feeds into the project's overall cost on the Details tab, alongside the Materials Total.
The CRM view of a Project
Opening the same project from CRM > Scheduling > Projects does not show the Purchasing tabs at all — it has its own, entirely separate set of six tabs: Milestone, Change Orders, Billing, Analysis, Notes & Attachments, and Audit Trail. Same underlying projects row, completely different tab strip.
Milestone is a real, working billing-schedule editor, not a placeholder — it defines what percentage of the Revised Contract Price gets invoiced and when. Invoicing a milestone from here creates a draft invoice on the project and marks the matching milestone on the Estimate the project came from as invoiced, since the project's schedule and the estimate's schedule are the same rows. It requires the project to have a Client ID; without one it shows a message asking you to link a client first instead of the editor.
Change Orders is its own tab alongside Milestone, not folded into it. It runs scope changes through a real approve/reject/reverse workflow (statuses: draft, pending approval, approved, rejected). Approving a change order raises the Revised Contract Price by its amount and, based on the billing treatment chosen when it was created — spread across the remaining milestones, given its own new milestone, rolled into the final milestone, or left off the schedule entirely — adjusts only the milestones that haven't been invoiced yet. Anything already billed is left exactly as it was. Reversing an approved change order runs the inverse through the same guarded path, and is refused once a milestone it touched has already gone out on an invoice.
Billing and Analysis both depend on the project having a Client ID set — a link to a CRM Client record, separate from the project's free-text customer name field. Without a Client ID, Billing shows nothing at all (by design, so it doesn't show unrelated org-wide activity), and Analysis has no invoices or payments to total. Both are scoped to this project's invoices and payments specifically — not every invoice the linked client has — since billing-by-client used to pull unrelated invoices into a project's numbers.
Notes & Attachments is, today, just a notes textarea saved to the project — no file upload exists under that tab yet. Audit Trail is a static "coming soon" placeholder with nothing wired up behind it.
The Job Costing Dashboard
Separate from Projects entirely, Job Costing is a labor rate calculator — it computes a break-even hourly rate and a bid rate from wage, overtime, payroll burden (FICA, Workers' Comp, SUI, FUI, PFML), overhead, and target profit inputs. It is a season-level pricing tool, not a per-project cost record — it has no concept of an individual job or project.
This is a live, current tool with a direct, working connection into Projects:
- The Rate Calculator tab shows Bid Rate, Break-Even rate, and Billable Hours as you adjust inputs, with a chart breaking the bid rate down into Direct Labor, Payroll Burden, OH Payroll, Other OH, Liabilities, and Profit per hour.
- Clicking "Set as project rate" next to the Break-Even figure saves that number as the org's default labor rate (
breakevenLaborRateCentsin org settings). Every project's Details tab uses this org-level rate for its labor cost and net-profit math, unless that specific project has its own rate saved (projects snapshot a rate at creation and allow editing it per-project from the Details tab). - The Scenarios tab lets you save named input sets (e.g. "2026 Budget — Landscape Season," "2025 Actual") and reload them into the calculator. These scenarios live only in the page's local state for the current session — they are not saved to the database, so they reset on reload rather than persisting like a project or PO would.
Field & tab reference
Every tab available on a Project record, and which screen surfaces it:
| Tab | Surfaced in | What it shows |
|---|---|---|
| Details | Purchasing & CRM | Status flow, budget vs. actual hours, labor rates, and the Contract Price / Cost / Net Profit summary. |
| Materials | Purchasing | Every Requisition, PO, or direct line item assigned to this project, with running Subtotal / Sales Tax / Shipping / Total. |
| Other Costs | Purchasing | Subcontractor costs entered manually — Materials, Labor, or Other — each with an optional linked Vendor. |
| Milestone | CRM | A real, working billing-schedule editor — percentages of the Revised Contract Price, each invoiced independently. Invoicing a milestone creates a draft invoice on the project and marks the matching milestone on the source Estimate as invoiced (they're the same schedule). Requires the project to have a Client ID, or it shows a "link to a client first" message instead. |
| Change Orders | CRM | Its own tab, not folded into Milestone. Full create / approve / reject / reverse workflow with statuses draft, pending_approval, approved, and rejected. Approving one raises the Revised Contract Price by the change order's amount and, per its chosen billing treatment (spread across remaining milestones, its own new milestone, added to the final milestone, or left off the schedule), adjusts only the milestones not yet invoiced — anything already billed stays put. Reversing an approved change order undoes exactly that (contract price and schedule both drop back); it's blocked once a milestone it touched has already been invoiced. |
| Billing | CRM | Invoices, payments, and credits scoped to this project specifically — not every invoice on the linked client — filtered by type (All / Invoice / Payment / Credit). Requires the project to have a Client ID; without one this tab shows nothing rather than unrelated org-wide billing. |
| Analysis | CRM | Project-scoped Original Contract, Revised Contract, Invoiced, Payments, Amount Due, and Remaining to Bill, plus Budgeted vs. Actual Man Hours and Budgeted Labor Cost. Voided invoices are excluded from Invoiced. |
| Notes & Attachments | CRM | Despite the name, just a free-text notes field saved to the project record today — there's no attachment upload here. |
| Audit Trail | CRM | Not built yet — the tab renders a static "Audit trail coming soon" placeholder. |
| Comments & History | Purchasing | Comment thread plus the full audit trail for the project record. |
| Files | Purchasing | Attachments. |