Running an HVAC business with Odoo

How do I invoice an installation milestone in Odoo?

Workflow overview: How do I invoice an installation milestone in Odoo?
Workflow overview. Instructional screenshots show the actual demo interface.

Enable native Odoo milestone invoicing, split an installation service into 30% and 70%, and review the first partial invoice without releasing unfinished work.

Alex wants to bill at agreed installation points. Odoo milestone invoicing is available in this tested build after Milestones is enabled on a project. We use a separate fictional $1,000 installation contract, split its service quantity into 30% and 70%, and prepare a $318 draft for the first billing point. The remaining milestone stays unreached and the installation task stays open.

Alex Rivera and Demo Air HVAC are fictional training examples. Prices, dates, quantities and business situations in this guide are illustrative.

Before you begin

Tested in stock Odoo 20.0-20260926 Community as the demo owner administrator, with official modules and standard configuration. Complete H47 installation projects and H27 deposits and final deductions. Official Project, Sales–Project, Sales, Timesheets and Invoicing modules are installed. Reuse Demo Property H08 and its billing/service addresses. Create a separate training contract and project for this lesson: S00011 and the H48 supplier purchase remain unchanged. This is a demonstration of one milestone’s draft invoice. No real customer agreement, installation, commissioning, acceptance or receipt is established. Keep messages local and the invoice unposted and unsent for review.

Step-by-step workflow

Step 1. Create a separate installation project

Open Project → Projects → New. Enter Demo Milestone Installation H55, select the existing Demo Property H08 customer and click Create project once. Keep planned dates and email alias empty for this billing demonstration. This creates a separate project; use the H47 setup as your operational reference rather than changing or billing S00011 a second time.

Action 1: Separate H55 project for the existing fictional customer. The actual target is highlighted in gold.
Separate H55 project for the existing fictional customer.
Action 2: Create this separate project once; leave dates and alias empty. The actual target is highlighted in gold.
Create this separate project once; leave dates and alias empty.
Action 3: Saved H55 project; open its card settings. The actual target is highlighted in gold.
Saved H55 project; open its card settings.

Step 2. Enable Milestones on the project and save

Return to Projects. On the H55 card, open more_vert → Settings, then the Settings tab. Select Team members only, verify Project Manager Demo Air Owner and keep Billable checked. Check Milestones, then click Save manually and wait. The product’s Based on Milestones option becomes available after this native project setting is saved. This build’s general Project settings page has no separate Milestones checkbox; use the project’s own Settings tab.

Action 3: Saved H55 project; open its card settings. The actual target is highlighted in gold.
Saved H55 project; open its card settings.
Action 4: Enable native Milestones on this project. The actual target is highlighted in gold.
Enable native Milestones on this project.
Action 5: Private team visibility; Billable and owner manager retained. The actual target is highlighted in gold.
Private team visibility; Billable and owner manager retained.
Action 6: Save project Milestones before configuring the service. The actual target is highlighted in gold.
Save project Milestones before configuring the service.
Action 7: Reopened project has Milestones enabled. The actual target is highlighted in gold.
Reopened project has Milestones enabled.

Step 3. Configure the milestone service product

Open Sales → Products → Products → New. Name it Demo Milestone Installation H55, select Service, keep Sales checked and clear Purchase. Set Reference H55-MILESTONE, Sales Price $1,000 and explicitly select Units; Service initially defaults to Hours here. Choose Create on Order → Task, select the existing H55 project, leave Task Template empty and choose Invoicing Policy → Based on Milestones. Save and reopen. Check the illustrative 6% sales tax; confirm the appropriate account and tax treatment for your own business.

Action 8: Separate H55 Service: $1,000 per Unit, Purchase off. The actual target is highlighted in gold.
Separate H55 Service: $1,000 per Unit, Purchase off.
Action 9: Create one task in the selected H55 project. The actual target is highlighted in gold.
Create one task in the selected H55 project.
Action 10: Native Based on Milestones is now available. The actual target is highlighted in gold.
Native Based on Milestones is now available.
Action 11: Save this milestone service once. The actual target is highlighted in gold.
Save this milestone service once.
Action 12: Reopened same service keeps H55-MILESTONE. The actual target is highlighted in gold.
Reopened same service keeps H55-MILESTONE.

Step 4. Prepare one separate milestone quotation

Use Sales → Orders → Quotations → New → New Quotation. Select Demo Property H08 and Demo Net 30 H06. Add H55-MILESTONE, quantity 1 Unit at $1,000. In Other Info, enter Customer Reference DEMO-H55-MILESTONE-001 — Separate fictional installation contract; no actual work or approval. Clear Online signature for this local owner-confirmation test. Save and reopen S00012. Review Billing Office H08, Service Site H08 and $1,000 + $60 demo tax = $1,060 before proceeding.

Action 13: Separate contract: one $1,000 Unit plus $60 demo tax. The actual target is highlighted in gold.
Separate contract: one $1,000 Unit plus $60 demo tax.
Action 14: Explicit fictional reference; original S00011 stays separate. The actual target is highlighted in gold.
Explicit fictional reference; original S00011 stays separate.
Action 15: Clear Online signature for this local owner test. The actual target is highlighted in gold.
Clear Online signature for this local owner test.
Action 16: Save this separate milestone quotation once. The actual target is highlighted in gold.
Save this separate milestone quotation once.
Action 17: Reopened S00012; $1,060 quotation, no generated task yet. The actual target is highlighted in gold.
Reopened S00012; $1,060 quotation, no generated task yet.

Step 5. Confirm once and inspect the generated records

Click Confirm once as the owner. The order gains 1 Projects / 1 Tasks and 1 Milestones. Confirmation creates one task in the project you selected and one native milestone linked to S00012’s service line. The generated task has no stage, assignee, deadline or handoff instructions in this case, with zero allocated time. This billing setup does not make it ready for dispatch; prepare the operational details using the earlier job guides.

Action 18: Owner confirms once: one task and one default milestone. The actual target is highlighted in gold.
Owner confirms once: one task and one default milestone.
Action 19: Generated task is In Progress; dispatch details remain empty. The actual target is highlighted in gold.
Generated task is In Progress; dispatch details remain empty.

Step 6. Inspect the default 100% milestone

Click 1 Milestones on S00012. The list initially has one row named for the H55 product, with the correct Sales Order Item, Quantity (%) 100% and Reached clear. Its View Tasks action refers to the generated installation task. Review the agreed billing schedule before marking this row reached: leaving the default at 100% would describe the full service quantity, rather than the intended first 30%.

Action 20: Open the one native milestone on S00012. The actual target is highlighted in gold.
Open the one native milestone on S00012.
Action 21: Default 100% milestone is unreached and linked to this service. The actual target is highlighted in gold.
Default 100% milestone is unreached and linked to this service.

Step 7. Keep the generated installation milestone at 70%

Click the row’s Name cell to enter edit mode. Rename it H55 Installation and handoff — pending, enter 70 under Quantity (%) and set Deadline October 23, 2026. Keep its existing S00012 Sales Order Item and leave Reached clear. Click the list toolbar’s Save and wait. Its generated task remains associated with this installation/handoff milestone.

Action 22: Edit the generated milestone; keep its installation task. The actual target is highlighted in gold.
Edit the generated milestone; keep its installation task.
Action 23: Keep installation and handoff at 70%. The actual target is highlighted in gold.
Keep installation and handoff at 70%.
Action 24: Installation milestone deadline: October 23. The actual target is highlighted in gold.
Installation milestone deadline: October 23.
Action 25: Save the generated 70% milestone, still unreached. The actual target is highlighted in gold.
Save the generated 70% milestone, still unreached.
Action 26: Same generated milestone: 70%, unreached, task retained. The actual target is highlighted in gold.
Same generated milestone: 70%, unreached, task retained.

Step 8. Add the separate 30% billing review

Click New in the milestone list. Enter H55 Preparation billing review — synthetic, keep the selected S00012 – H55-MILESTONE Sales Order Item, enter 30 under Quantity (%) and set Deadline October 22, 2026. Leave Reached clear and click Save. Reload and check exactly two rows totalling 30% + 70% = 100%, both linked to this service line and project. The new 30% row has no task assigned in this example; it represents an explicit owner-reviewed billing point.

Action 28: Save the separate 30% row once. The actual target is highlighted in gold.
Save the separate 30% row once.
Action 29: Exactly two unreached rows: 30% plus 70% equals 100%. The actual target is highlighted in gold.
Exactly two unreached rows: 30% plus 70% equals 100%.

Step 9. Record the billing decision and review initial eligibility

Return to S00012 with its breadcrumb or the row’s View Sales Order. Both unreached milestones leave the service Delivered 0.00 / Invoiced 0.00. Use Log note to record the fictional 30%/70% schedule, required acceptance evidence and training-only decision to test the first billing point. State that no actual agreement, work or payment is established, S00011 is separate, and S00012 has no deposit. Click Log. In the verification, attempting a Regular invoice at this zero-delivery point was refused without creating an invoice.

Action 30: Both unreached: Delivered 0.00 and Invoiced 0.00. The actual target is highlighted in gold.
Both unreached: Delivered 0.00 and Invoiced 0.00.
Action 31: Record the fictional billing decision internally. The actual target is highlighted in gold.
Record the fictional billing decision internally.
Action 32: Label the proposed schedule and lack of real acceptance. The actual target is highlighted in gold.
Label the proposed schedule and lack of real acceptance.
Action 33: Log this one internal training decision. The actual target is highlighted in gold.
Log this one internal training decision.
Action 34: Check regular invoice eligibility before anything is reached. The actual target is highlighted in gold.
Check regular invoice eligibility before anything is reached.
Action 35: Choose Regular invoice, not a new down payment. The actual target is highlighted in gold.
Choose Regular invoice, not a new down payment.
Action 36: Test the regular draft: no delivered quantity yet. The actual target is highlighted in gold.
Test the regular draft: no delivered quantity yet.
Action 37: Native refusal; no invoice was created. The actual target is highlighted in gold.
Native refusal; no invoice was created.

Step 10. Mark only the reviewed first milestone Reached

Open 2 Milestones. Click the Name cell of H55 Preparation billing review — synthetic to enter row edit mode, check Reached, then click Save. The display-only checkbox is disabled until the row is being edited in this list. Reload and return to S00012: the service now shows Delivered 0.30. That is 30% of the one service Unit. The 70% row remains unreached and its installation task remains In Progress. A native Reached tick records your decision; it does not independently verify actual preparation, installation or customer acceptance.

Action 38: Click the 30% Name cell to enter edit mode. The actual target is highlighted in gold.
Click the 30% Name cell to enter edit mode.
Action 39: Mark only this synthetic 30% billing point Reached. The actual target is highlighted in gold.
Mark only this synthetic 30% billing point Reached.
Action 40: Save Reached on this one billing review. The actual target is highlighted in gold.
Save Reached on this one billing review.
Action 41: Only 30% is Reached; 70% installation stays unreached. The actual target is highlighted in gold.
Only 30% is Reached; 70% installation stays unreached.
Action 42: Delivered 0.30 of one service Unit; no invoice yet. The actual target is highlighted in gold.
Delivered 0.30 of one service Unit; no invoice yet.
Action 27: Same saved 30% row; Reached here reflects later Step 10. The actual target is highlighted in gold.
Same saved 30% row; Reached here reflects later Step 10.

Step 11. Create the first regular milestone draft

On S00012, choose Create Invoice → Regular invoice → Create Draft once. Check Demo Property H08, Billing Office H08, the S00012 sale link and the H55 service. The proposed quantity is 0.30 Units at $1,000, producing $300 untaxed + $18 demo tax = $318. The milestone changes the invoiceable service quantity; it did not automatically create an invoice when Reached was saved. This regular milestone line is not a new down-payment request.

Action 43: Regular invoice for the reached 30%; no new down payment. The actual target is highlighted in gold.
Regular invoice for the reached 30%; no new down payment.
Action 44: Create this one 30% draft invoice. The actual target is highlighted in gold.
Create this one 30% draft invoice.
Action 45: 0.30 Units × $1,000 = $300 plus $18 demo tax. The actual target is highlighted in gold.
0.30 Units × $1,000 = $300 plus $18 demo tax.

Step 12. Date and label the draft for review

Enter Invoice Date October 15, 2026 and leave the field. Verify Demo Net 30 H06; the saved draft’s due date is November 14, 2026. Under Invoice Lines, use Add a note to add H55 FIRST MILESTONE DRAFT REVIEW ONLY / HOLD, identify the synthetic 30% billing point and state that the remaining 70% is unreached. Preserve the copied product/quantity and review the Product Sales account, tax and prior invoices. Leave the cell, let changes save, and use Save manually only if changes remain pending. Reopen the same draft and check the note and date. Keep it unposted and unsent.

Action 46: Date this draft October 15, 2026. The actual target is highlighted in gold.
Date this draft October 15, 2026.
Action 47: Add a review note without replacing the service. The actual target is highlighted in gold.
Add a review note without replacing the service.
Action 48: Label the synthetic 30% draft HOLD; 70% remains unreached. The actual target is highlighted in gold.
Label the synthetic 30% draft HOLD; 70% remains unreached.
Action 49: Save pending draft changes once. The actual target is highlighted in gold.
Save pending draft changes once.
Action 50: Reopen the same $318 Draft with its separate hold note. The actual target is highlighted in gold.
Reopen the same $318 Draft with its separate hold note.
Action 51: Saved October 15 invoice date; Net 30 retained. The actual target is highlighted in gold.
Saved October 15 invoice date; Net 30 retained.

Step 13. Reopen the same invoice from the order

Use 1 Sale Orders, then 1 Invoices, to reopen the same $318 Draft. The order shows Delivered 0.30 / Invoiced 0.30 even while that invoice remains Draft and unpaid. Its current quantity to invoice is zero; the later 70% is still unreached. In the tested retry, Regular invoice → Create Draft was refused with No items are available to invoice, retaining the same one draft. Review that existing draft instead of treating an available Create Invoice button as a new amount due.

Action 52: Open this draft’s one Sales Order. The actual target is highlighted in gold.
Open this draft’s one Sales Order.
Action 53: Draft already counts as Invoiced 0.30; Delivered remains 0.30. The actual target is highlighted in gold.
Draft already counts as Invoiced 0.30; Delivered remains 0.30.
Action 54: Reopen the same one $318 Draft invoice. The actual target is highlighted in gold.
Reopen the same one $318 Draft invoice.
Action 55: Check existing-draft warning before requesting any duplicate. The actual target is highlighted in gold.
Check existing-draft warning before requesting any duplicate.
Action 56: Check Regular invoice with the existing draft retained. The actual target is highlighted in gold.
Check Regular invoice with the existing draft retained.
Action 57: Test once: no further milestone quantity is invoiceable. The actual target is highlighted in gold.
Test once: no further milestone quantity is invoiceable.
Action 58: Native refusal retains the same one Draft; no second invoice. The actual target is highlighted in gold.
Native refusal retains the same one Draft; no second invoice.
Action 59: Same $318 Amount Due; Draft stays unposted and unpaid. The actual target is highlighted in gold.
Same $318 Amount Due; Draft stays unposted and unpaid.

Check the result

Native project Milestones makes the product’s Based on Milestones policy available. Confirming separate S00012 creates one task in the selected project and one default 100% milestone for its $1,000 service Unit. Two saved milestone rows divide that same service line into 30% preparation review and 70% installation/handoff. With neither reached, delivery and regular invoiceability are zero and a premature regular invoice is refused. Saving only the synthetic 30% Reached delivers 0.30 Units and makes that amount invoiceable, while the installation task and 70% milestone remain unfinished. One regular draft invoices 0.30 × $1,000 + $18 demo tax = $318, with the native sale-line/project allocation and a saved review hold/date. It stays Draft/unpaid/unposted; it already counts as Invoiced 0.30 on the order. A repeated regular-invoice attempt is refused and creates no duplicate. Reopen retains the same two milestones, task and draft. Original business records, H47 installation, H48 supplier draft, existing deposit/deduction, CRM, portal access, stock, payments and local mail are preserved.

If your screen differs

The product option was absent before a project’s Milestones setting was saved; that initial absence did not establish an edition limitation. Check the native project setting and installed official integrations. Keep the milestone’s actual Sales Order Item and percentages correct. This example manually marks a 30% billing review Reached with no assigned task; it does not establish automatic acceptance or an enforced approval system. The generated task remains linked to the unreached 70% milestone, without a stage or operational handoff. Its Delivered quantity is a service-billing measure, not a physical equipment receipt or commissioning proof. The regular-invoice wizard initially offered a percentage down payment when nothing was delivered; explicitly choose the intended billing path. Existing drafts count toward Invoiced quantities, and the retry dialog warns about linked Draft Invoices before refusing the regular invoice when nothing further is invoiceable. A later 70% invoice, completion/unreaching after billing, altered percentages, other roles and a deposit combined with milestone billing were not exercised here. H27’s separate deposit/deduction evidence remains valid; match a deposit to its own order and invoices before any deduction. The displayed sales margin uses the product’s zero Cost here and is not a job-profit calculation.

Frequently asked questions

How do I enable milestone invoicing in Odoo? In this tested stock Odoo 20 Community build, enable Milestones on the project’s Settings tab and save. A Service product can then use Based on Milestones, with its Task linked to the selected billable project. Confirming the separate order generated a native milestone; we reviewed its Sales Order Item and split the default 100% into 30% and 70% before recording achievement.
Does an Odoo milestone automatically create an invoice? Saving Reached on the tested 30% milestone updated the service’s Delivered and invoiceable quantity to 0.30 of one Unit. The owner then used Create Invoice → Regular invoice → Create Draft to create the $318 draft. The 70% milestone and installation task stayed unfinished; the tick did not establish actual customer acceptance, create a payment or finish the job.
How do I avoid billing an Odoo milestone twice? Check the same order’s linked invoices and quantities first. The $318 draft already counted as Invoiced 0.30. With only that 30% reached, a repeated regular-invoice attempt was refused and kept one draft. This example has no deposit; H27 verifies a separate deposit deduction on its own order. Combined deposit and milestone deductions still need their own review.

Continue building the business

Continue with H50: How do I sell an HVAC maintenance agreement in Odoo? to define its annual scope, price and office handoff. Keep this first milestone draft on hold and the later installation/handoff milestone pending for a real billing decision.

Talk to an Odoo partner

Bring your current process and the result you need to Onward to plan your Odoo workflow. Talk to an Odoo partner.