On this page
A contracting company in Bahrain is a set of contracts, each with its own site, its own bill of quantities, its own payment schedule and its own margin. The accounting system sees one company; the project manager sees twelve jobs at different stages; the bank sees a cash position that depends on which progress claim was certified last month. Most contractors we meet in Manama, Sitra and the industrial areas around Hidd reconcile those three views in a spreadsheet, once a month, after the fact. Odoo can hold all three in one place, provided the setup follows the order the data dictates: analytic accounts before timesheets, the invoicing policy of each contract before the first milestone, and the retention treatment before the first progress invoice. This guide walks through that order, with the Odoo documentation behind each statement, and says plainly what Odoo does not do out of the box for a contractor.
Who this is for
General contractors, MEP and electrical subcontractors, fit-out and joinery firms, engineering and design offices, facilities maintenance companies and anyone who delivers work against a contract with stages, certifies progress and waits for retention. Companies whose business is buying and selling goods should read our guide for trading and distribution companies instead; the people side (GOSI, LMRA, WPS) is covered in our Bahrain HR and payroll guide and is not repeated here.
One project per contract, one analytic account per project
The foundation is a rule, not a feature: every contract is a project in the Project app, and every project is linked to an analytic account in Accounting. Odoo’s documentation on project profitability is explicit that a record only appears in the project’s figures if it is linked to the project and its analytic account; a vendor bill coded to the wrong analytic account is invisible to the project manager even though the accountant posted it correctly. Analytic accounts are grouped into analytic plans, and a plan can be made mandatory, so that a bill, an invoice or a journal entry cannot be confirmed without one. For a contractor we set a “Projects” plan as mandatory on the expense and income account prefixes, and leave it optional on overheads: nobody can post a site cost without saying which site. Analytic distribution models then prefill the account automatically from the vendor, the product or the account prefix, which removes most of the typing and most of the errors.
The project itself holds tasks on a Kanban board by stage, a customer, a project manager, planned dates and allocated hours. Its visibility decides who sees it: invited internal users only, all internal users, or portal users as well. That last option matters for a contractor, because a project can be shared with the client or the consultant as a portal collaborator, in read mode, in edit mode limited to the tasks they follow, or in full edit mode. A client who can see the task list and the milestone dates asks fewer questions by email. The project’s top bar gives one-click access to the timesheets, sales orders, invoices, purchase orders and documents linked to it, and custom buttons can be saved for the views a site manager uses every morning.
Project templates for the work you repeat
A villa fit-out, a substation installation or an annual maintenance contract follows the same sequence every time. Odoo lets you convert a finished project into a project template, carrying its stages, tasks, sub-tasks and their settings. Templates can carry project roles (site engineer, foreman, QA/QC) so that assignees are picked once when a new project is created, and planned dates so that each task is scheduled from the project start date by its offset, taking the team’s working schedule, time off and public holidays into account. Two details from the documentation are worth knowing before you rely on this: converting a project into a template archives the original, so duplicate it first, and milestones defined in a template keep their names but the invoicing percentage must be set again on each new project.
Timesheets that carry the real cost of labour
The largest cost on most sites is people, and the cheapest control is the timesheet. In Odoo, employees log hours on a task from the web, the mobile app or the Timesheets grid; a project must have timesheets enabled for that to be possible, and access rights decide who can log their own time, who can see the team’s, and who can validate. Each hour is valued at the employee’s cost from the Employees app, and that valued hour appears on the project’s cost side immediately. For a contractor paying overtime, site allowances and accommodation, the hourly cost on the employee record should be the fully loaded cost, not the basic wage, or every project will look more profitable than it is. Validated timesheets feed payroll work entries if you run payroll in Odoo, and they are also the basis for invoicing on time-and-materials contracts, which we come to below.
Two practical rules from projects we have delivered. First, timesheets are logged per task, so the task list should mirror the cost breakdown you want to see: “Civil works”, “MEP first fix”, “Snagging”, not “Week 12”. Second, make the foreman the person who validates, weekly, from the grid view, and make validation a condition for the week’s payroll. A timesheet nobody validates is a number nobody believes.
Progress billing: three contract types and how Odoo invoices each
Odoo invoices a service product according to its invoicing policy, and the choice is made per product, so one company can run all three contract types at once.
Fixed-price contract billed by milestones
The service product is set to Based on Milestones and to create a project, a project and task or a task on order confirmation; the option is only offered once at least one project has milestones enabled. Once the sales order is confirmed, a Milestones smart button lists the milestones with a Quantity (%) each: mobilisation, structure complete, MEP first fix, handover. When a milestone is marked Reached, by hand or automatically because every task linked to it is done, the delivered quantity on the order line rises by that percentage. The documentation is careful on one point and so are we: reaching a milestone does not create an invoice; it makes the amount invoiceable, and someone clicks Create Invoice after the consultant has certified. That gap between “reached” and “invoiced” is exactly where a contractor’s certification process lives, and it is better to have it visible than hidden in a drawer. Milestones also appear as diamonds on the Gantt view, blue until their deadline, red once it has passed without being reached.
Percentage of completion without formal milestones
Many Bahraini contracts are certified monthly on a measured percentage rather than on named stages. The same mechanism serves: one milestone per month or one per claim, with the percentage entered when the quantity surveyor agrees the valuation, or simply a service product invoiced on delivered quantities where the delivered quantity is updated by hand to the certified percentage. The sales order then shows ordered value, delivered value and invoiced value side by side, which is the contractor’s “work done, certified, invoiced” triplet.
Time and materials
For maintenance contracts, variations and daywork, the product is Based on Timesheets: validated hours on the task become the delivered quantity, and the Recorded Hours smart button on the order shows what is billable. Expenses and purchases follow the same road: an expense with a Customer to Reinvoice, or a purchase order line with the project’s analytic distribution, lands on the sales order as a new line to be invoiced, at cost or with a markup depending on the product’s configuration. Rental of a crane or a generator bought in for one job is therefore re-billed without anyone copying figures.
Advance payments
Mobilisation advances are down payments in Odoo: from the Create Invoice dialog you choose a percentage or a fixed amount, the draft invoice carries a Down Payment line, and the order gains a Down Payments section. Each later progress invoice deducts the advance proportionally through the Already invoiced amount, so the recovery of the advance is visible on every claim. The income account used for the down payment can be changed on the draft, not after posting; for a contractor that account is usually a liability (advances received), not revenue, and this is set once in the Sales settings.
Retention: what Odoo does, and the choice you have to make
Retention money, the share of each certified amount the client holds back until practical completion and the end of the defects liability period, is the question every contractor asks first, and the honest answer is that Odoo has no dedicated retention feature. It is modelled with standard accounting objects, and there are two clean ways to do it. The first keeps the invoice at the full certified amount and uses a payment term with two instalments: the net amount due at the contract’s payment period, and the retained percentage due at a far date that is corrected when completion is certified. The receivable stays whole, the ageing report shows the retention as not yet due rather than overdue, and the follow-up levels do not chase it. The second way adds a negative retention line on each progress invoice, posted to a separate retention receivable account, and issues a final retention invoice at release; the client sees the deduction on the face of the document, as many Bahraini quantity surveyors expect, and the balance sheet shows retentions as a distinct asset.
Which one is right depends on how your clients’ certificates are laid out and on how your auditor wants retentions presented; the VAT treatment of the retained amount is a question for your tax adviser and is handled by the tax on the line, not by the structure. What matters is that the choice is made before the first progress invoice and applied to every contract, because moving from one model to the other mid-project means restating receivables. We also keep a retention register as a simple report on the retention account grouped by project, with the expected release date in the analytic account’s reference, because the money is usually forgotten by everyone except the person who built the report. The same two patterns apply, in mirror image, to the retention you hold on your subcontractors.
Subcontractors: purchase orders, bill control and back-to-back terms
A word on vocabulary first. Odoo’s Subcontracting feature lives in Manufacturing and describes a third party that manufactures goods you sell, with components you may supply. It is not the right tool for a plastering or ductwork subcontractor. For construction subcontractors the right objects are a purchase order for a service product coded to the project’s analytic account, vendor bills controlled against that order, and a blanket order when the same subcontractor works for you across several sites at agreed rates with a validity period.
Odoo’s bill control policy decides when a vendor bill can be created: on ordered quantities, which is the default for services, or on received quantities, the default for goods. For a subcontractor paid by certified progress we use the second even though the product is a service: the site engineer records the certified percentage as the received quantity, and only that amount can be billed. 3-way matching, enabled in the Purchase settings, then flags bills that exceed what was received, so a bill is only paid once the work it covers has been accepted. The payment term on the subcontract mirrors the main contract (back-to-back), including the retention pattern chosen above. When a subcontractor’s bill carries materials and labour, two lines with two products keep the cost split clean in the profitability report.
Materials and equipment from stock
Contractors who hold a yard of cable drums, pipes, tiles and consumables issue them to sites, and the site should bear the cost. In Odoo, each site can be an internal location or the project can simply receive deliveries; what makes the cost land on the project is enabling Analytic Costs on the operation type, after which the value of every validated stock move is posted to the project’s analytic account and appears under Materials in the profitability dashboard. Materials bought for one job and delivered straight to site are a purchase order with the project’s analytic distribution and never touch the yard. For owned equipment, the Maintenance app keeps one record per machine with its preventive and corrective maintenance requests; the cost of a machine’s time on a site is not computed by Odoo and, where a contractor wants it, is an internal charge we configure rather than a standard feature.
Site work: worksheets and planning
Where the company also does service calls and maintenance visits, the Field Service app adds worksheet templates (checkboxes, fields to fill, photos and files) completed on site from a phone and attached to the task, and the Planning app schedules technicians by role and publishes shifts with email notification. For a pure construction contractor these are optional; for an MEP or facilities company with a maintenance arm they replace paper job cards.
VAT and invoices in Bahrain
Progress invoices are tax invoices like any other and carry Bahrain’s standard VAT rate on the certified amount; Odoo’s Bahrain localization installs the chart of accounts, the taxes and the bilingual invoice layout. Our guide to VAT and e-invoicing in Bahrain and Saudi Arabia covers the NBR invoice requirements, the VAT return and the Saudi ZATCA rules for contractors who also work across the causeway; this article does not repeat them.
Reporting: profitability per project, budget against actual, cash
The project dashboard shows revenues and costs in three columns: Expected (from confirmed sales and purchase orders), To invoice or To bill (work delivered, timesheets validated, goods received, not yet invoiced), and Invoiced or Billed. Revenues come from timesheets, materials, customer invoices, down payments and re-invoiced expenses; costs from timesheets at employee cost, purchase orders once the vendor bill is posted, materials from stock moves, expenses, vendor bills and manufacturing orders. Read together, the three columns are a contractor’s work-in-progress statement: what is contracted, what is earned but unbilled, what is billed. Analytic budgets add the tender estimate per analytic account and the Budget Report compares it with actuals, which is the earliest warning that a job is going wrong. The cash view comes from the payment terms and the follow-up levels (email, WhatsApp, SMS or letter at the days you set); for a contractor, the aged receivables report split between due, retention and overdue is the weekly meeting’s first page.
A typical rollout
| Lot | Scope | Go-live criterion |
|---|---|---|
| 1. Books and the project model | Bahrain localization, chart of accounts, analytic plan “Projects” mandatory on income and expense prefixes, distribution models, one project and analytic account per live contract, opening balances including retentions | Every open contract has a project, an analytic account and its retention balance agreed with the client ledger |
| 2. People and time | Employees with loaded hourly cost, projects with timesheets enabled, task lists mirroring the cost breakdown, weekly validation by foremen | Four consecutive weeks of validated timesheets on every active site |
| 3. Contracts and progress billing | Service products per contract type (milestones, delivered quantities, timesheets), project templates, down payments, retention pattern chosen and configured, bilingual invoice layout | One full monthly claim cycle invoiced from Odoo for every contract, advance recovery and retention visible on each invoice |
| 4. Subcontractors and materials | Service products for subcontract work, bill control on received quantities, 3-way matching, blanket orders, Analytic Costs on stock operations, purchase orders coded to projects | A month of subcontractor bills matched to certified progress, materials issued from the yard costed to sites |
| 5. Reporting and budgets | Tender estimates as analytic budgets, profitability dashboards, retention register, follow-up levels, aged receivables split due/retention/overdue | Management reads work-in-progress and margin per project from Odoo, not from the spreadsheet |
Six mistakes we see
- Creating one project per client instead of one per contract, so that two jobs for the same developer share a margin figure that means nothing.
- Leaving the analytic plan optional. The first month looks fine; by the third, a third of the costs sit on no project and the dashboard is quietly wrong.
- Valuing timesheets at basic salary. Allowances, overtime, accommodation and the cost of idle time between sites belong in the hourly cost.
- Letting milestones create the invoice in people’s minds. The milestone says the work is done; the certificate says the client agrees. Invoice on the certificate.
- Choosing the retention model after the first invoices are out, then restating receivables when the auditor asks why retentions look overdue.
- Paying subcontractors from their bill rather than from the certified quantity. Bill control on received quantities and 3-way matching exist for exactly this.
When Odoo is not the right fit
A contractor whose core need is estimating and take-off from drawings, detailed CPM scheduling with resource levelling across hundreds of activities, or formal contract administration (RFIs, submittals, variation registers under FIDIC) will find Odoo thin in those areas; the Gantt and task dependencies are good for a project plan, not for a planner’s baseline. In those companies Odoo runs the money, the people, the purchasing and the progress billing, and a specialised tool runs the programme, with the certified percentages flowing to Odoo monthly. We say so at the scoping stage rather than after go-live.
Frequently asked questions
Can Odoo invoice progress claims against milestones?
Yes. A service product invoiced Based on Milestones gains a Milestones smart button on the sales order; each milestone has a percentage, and marking it reached makes that share of the order invoiceable. The invoice itself is created by a user, which is where your certification step fits.
How is retention handled?
With standard accounting objects, not a dedicated module: either a payment term that leaves the retained share due at a later date, or a negative retention line posted to a separate retention receivable account with a final release invoice. The choice is a configuration decision made with your accountant before the first progress invoice.
Can we recover a mobilisation advance across progress invoices?
Yes. The advance is a down payment on the sales order, and every regular invoice that follows deducts it through the Already invoiced amount, so the recovery is visible claim by claim.
Do subcontractor bills get checked against certified work?
Yes, when the subcontract product is billed on received quantities and 3-way matching is enabled: the certified percentage is recorded as received, and a bill above that amount is flagged before payment.
Does the project manager see the margin in real time?
The project dashboard shows expected, earned-but-unbilled and invoiced revenue against timesheet, purchase, material and expense costs, as long as every record carries the project’s analytic account. That condition is the reason we make the analytic plan mandatory.
Can the client follow the project?
A project can be shared with portal users in read mode or with limited edit rights on the tasks they follow; what they see is decided per project.
Working with Azinove in Bahrain
Azinove W.L.L is an official Odoo Partner based in Isa Town, Bahrain (CR 190436-1), with a French sister company in Strasbourg; the group has delivered more than 45 projects since 2021 and configures Odoo for companies in Bahrain and Saudi Arabia in Arabic, English and French. For a contracting company we start with a half-day workshop on the contract types, the certification process and the retention treatment, then build the five lots above on your own data. Read how we work on our Odoo Bahrain page, our Odoo Riyadh page for projects across the causeway, and our guide to choosing an Odoo partner in the Gulf, or write to us with your current contract list and the way your claims are certified today.
Sources
- Odoo — Documentation 19.0: Project management: projects and tasks, visibility, sharing a project with portal collaborators (read, edit with limited access, edit), the project top bar (read on 24 October 2026) — https://www.odoo.com/documentation/19.0/applications/services/project/project_management.html
- Odoo — Documentation 19.0: Project milestones: enabling milestones, Sales Order Item and Quantity (%) fields, automatic Reached when the linked tasks are done, Gantt display — https://www.odoo.com/documentation/19.0/applications/services/project/project_management/project_milestones.html
- Odoo — Documentation 19.0: Project templates: converting a project into a template, project roles, task scheduling from planned dates, billable templates linked to a service product — https://www.odoo.com/documentation/19.0/applications/services/project/project_management/project_templates.html
- Odoo — Documentation 19.0: Project profitability: the Expected, To invoice / To bill and Invoiced / Billed columns, revenue and cost records, Analytic Costs on operation types — https://www.odoo.com/documentation/19.0/applications/services/project/project_management/project_profitability.html
- Odoo — Documentation 19.0: Timesheets: access rights, enabling timesheets per project, validation — https://www.odoo.com/documentation/19.0/applications/services/timesheets.html
- Odoo — Documentation 19.0: Analytic accounting: analytic accounts, analytic plans and their applicability (optional, mandatory, unavailable), analytic distribution and distribution models — https://www.odoo.com/documentation/19.0/applications/finance/accounting/reporting/analytic_accounting.html
- Odoo — Documentation 19.0: Budgets: analytic budgets per analytic account and the Budget Report, financial budgets on the Profit and Loss report — https://www.odoo.com/documentation/19.0/applications/finance/accounting/reporting/budget.html
- Odoo — Documentation 19.0: Invoice project milestones: the Based on Milestones invoicing policy, the Milestones smart button, Delivered % and Create Invoice — https://www.odoo.com/documentation/19.0/applications/sales/sales/invoicing/milestone.html
- Odoo — Documentation 19.0: Down payments: percentage or fixed amount, the Down Payments section of the sales order, deduction on the regular invoice, income account of the down payment — https://www.odoo.com/documentation/19.0/applications/sales/sales/invoicing/down_payment.html
- Odoo — Documentation 19.0: Invoicing based on time and materials: Based on Timesheets policy, re-invoicing expenses and purchases through the analytic distribution — https://www.odoo.com/documentation/19.0/applications/sales/sales/invoicing/time_materials.html
- Odoo — Documentation 19.0: Invoicing policies: invoice what is ordered or what is delivered — https://www.odoo.com/documentation/19.0/applications/sales/sales/invoicing/invoicing_policy.html
- Odoo — Documentation 19.0: Purchase control policies: bills on ordered or on received quantities, defaults per product type, 3-way matching — https://www.odoo.com/documentation/19.0/applications/inventory_and_mrp/purchase/manage_deals/control_bills.html
- Odoo — Documentation 19.0: Blanket orders: long-term purchase agreements with agreed prices and a validity period — https://www.odoo.com/documentation/19.0/applications/inventory_and_mrp/purchase/manage_deals/blanket_orders.html
- Odoo — Documentation 19.0: Subcontracting (Manufacturing): a third-party manufacturer producing goods the company sells — https://www.odoo.com/documentation/19.0/applications/inventory_and_mrp/manufacturing/subcontracting.html
- Odoo — Documentation 19.0: Payment terms and installment plans — https://www.odoo.com/documentation/19.0/applications/finance/accounting/customer_invoices/payment_terms.html
- Odoo — Documentation 19.0: Follow-up on invoices: follow-up levels, email, WhatsApp, SMS or post — https://www.odoo.com/documentation/19.0/applications/finance/accounting/payments/follow_up.html
- Odoo — Documentation 19.0: Field Service worksheets: worksheet templates with checkboxes, fields, images and files — https://www.odoo.com/documentation/19.0/applications/services/field_service/worksheets.html
- Odoo — Source code: Bahrain localization module (l10n_bh), LGPL-3 — https://github.com/odoo/odoo/tree/19.0/addons/l10n_bh
