The Challenge
The client delivers fit-out and building works for developers, landlords and corporate tenants, with several projects running at once and much of the work let to subcontractors for joinery, ceilings, partitions and MEP packages. Every project had a budget built from the tender, a quantity surveyor who valued progress for each payment application and a site team that ordered materials as the program demanded.
None of it lived in one place. Budgets sat in spreadsheets that were rarely updated after award, purchase orders were raised in an accounting package with no link to a project, and subcontractor claims and the retention held on them were tracked in separate files kept by the commercial team. Progress invoices to clients were prepared in spreadsheets, and the retention each client held back was remembered rather than recorded. The real margin on a project was only known at the final account, long after anything could be done about it.
These are the challenges we see most often in Construction and Real Estate:
- Budgets that drift without warning: committed cost stayed invisible until supplier bills arrived.
- Subcontractor bills checked by hand: claims compared with certificates in separate files.
- Retention outside the books: amounts held by clients and held on subcontractors tracked in spreadsheets.
- Progress invoices rebuilt every time: each application started from the last spreadsheet.
- Costs coded to the wrong job: or to no job at all, so project reports could not be trusted.
Our Approach
We began with a free consultation, then ran workshops with the commercial manager, quantity surveyors, project managers, procurement and finance. Following one live project from tender budget to its latest payment application showed where money is really committed in a contracting business: when a subcontract or a material order is placed, not when the bill arrives.
The fit-gap review against standard Odoo Enterprise was encouraging. Projects with their own analytic accounts, analytic budgets with committed amounts, purchase orders linked to a project, bills controlled on received quantities, milestone invoicing and manually updated delivered quantities cover the core process. Odoo has no dedicated retention feature, so we agreed a configured approach with finance before building anything, rather than writing custom code.
The plan was phased, with a sign-off at the end of each phase:
- Structure: analytic plans for projects and cost types, the chart of accounts, project templates and budgets for live projects.
- Buying: purchase orders against projects, subcontract orders controlled on certified quantities and purchase approvals.
- Billing: contract sales orders, milestone and measured progress invoicing, retention and the project reports.
Rather than reconstructing the history of every project, live projects were loaded with their budgets, open subcontracts and the value certified to date, so the next payment application came straight from Odoo. Finance reconciled retention balances and open items with the old files before cut-over. Training was role-based: quantity surveyors on certification and progress invoicing, site teams on ordering against their project and project managers on the budget report.
The Solution
Every Project with a Budget That Counts Commitments
Each project has its own analytic account, and a second analytic plan records the cost type: materials, labor, subcontract, plant hire and preliminaries. Analytic budgets are built from the tender with a line for each project and cost type. Once a budget is open, Odoo shows the achieved amount from posted entries beside the committed amount, which adds confirmed purchase orders that have not been billed yet. Purchase orders carry the project, so their lines take its analytic distribution, and a line that would take an open budget past its allocation is highlighted in red. When an approved variation changes the scope, the budget is revised and the original stays on record beside the new version.
Subcontractor Bills against Certified Work
Subcontract packages are ordered as service products controlled on received quantities. When the quantity surveyor certifies a subcontractor's progress, the certified quantity is entered as the received quantity on the purchase order, and the draft bill created from the order covers only what has been certified. Three-way matching flags any bill that goes beyond it before payment. Retention held on subcontractors is set through a payment term with an installment plan rather than an extra bill line, so each bill still matches its certified quantity: the payable splits into an amount due now and a retained share due later, and the aged payables report shows what is still held for each subcontractor.
Progress Invoices and Retention from the Contract
Each contract is a sales order whose lines follow the contract breakdown. Stage payments use milestones: when the client's consultant certifies a stage, the project manager marks the milestone as reached, the delivered quantity on the order updates and finance invoices it. Measured works use lines whose delivered quantity is entered by hand, so the quantity surveyor enters the cumulative certified quantity and the invoice bills only the difference since the last application. Retention is a deduction line on each progress invoice, posted to a retention receivable account, and release invoices at practical completion and at the end of the defects liability period clear it. Each approved variation is its own quotation linked to the same project, so the original contract value stays visible beside it.
One View of Each Project's Money
Drawings, consultant certificates and variation instructions are filed in each project's folder in Odoo Documents, and subcontract agreements are signed through Odoo Sign. Project managers review budget, committed and actual cost by cost type in the budget report, and a spreadsheet dashboard gives the directors invoiced revenue, retention held and margin across all projects. Our OdooStar team supports the commercial and finance teams as new contract types come in.