-
Notifications
You must be signed in to change notification settings - Fork 10.8k
[IMP] Sales: Invoicing project milestones #15545
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 19.0
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -2,235 +2,90 @@ | |||||
| Invoice project milestones | ||||||
| ========================== | ||||||
|
|
||||||
| Invoicing based on project milestones can be used for expensive or large-scale projects with | ||||||
| discrete, measurable deliverables. The series of milestones in a project represent a clear sequence | ||||||
| of work that will inevitably result in the completion of a project and/or contract. | ||||||
| .. |SO| replace:: :abbr:`SO (Sales Order)` | ||||||
| .. |SOs| replace:: :abbr:`SOs (Sales Orders)` | ||||||
|
|
||||||
| This method of invoicing ensures the company gets a consistent flow of money throughout the lifetime | ||||||
| of the project. Customers can closely monitor every phase of the project's development as it | ||||||
| happens, in addition to paying a large bill in several installments, instead of all at once. | ||||||
| Invoicing based on project milestones allows companies to bill large or long-running projects | ||||||
| progressively as key deliverables are completed. Each milestone represents a measurable stage of | ||||||
| work that triggers invoicing upon completion. This approach helps maintain predictable cash flow and | ||||||
| provides customers with visibility into project progress, all while allowing payments to occur in | ||||||
| manageable installments. | ||||||
|
|
||||||
| Create milestone products | ||||||
| ========================= | ||||||
|
|
||||||
| In Odoo, each milestone of a project is considered as an individual product. | ||||||
|
|
||||||
| To create and/or configure products to work like this, first navigate to :menuselection:`Sales app | ||||||
| --> Products --> Products`. Then, click on a product, or create a new one by clicking | ||||||
| :guilabel:`New`. | ||||||
|
|
||||||
| The option to invoice based on milestones is only available for certain product types. | ||||||
|
|
||||||
| On the product form, under the :guilabel:`General Information` tab, the :guilabel:`Product Type` | ||||||
| field *must* be set on any of the following options: :guilabel:`Service`, :guilabel:`Event Ticket`, | ||||||
| :guilabel:`Event Booth`, or :guilabel:`Course`. | ||||||
|
|
||||||
| .. image:: milestone/product-type-field.png | ||||||
| :align: center | ||||||
| :alt: The invoicing policy field drop-down menu with options on product form. | ||||||
|
|
||||||
| With any of those :guilabel:`Product Type` options selected, choose :guilabel:`Based on Milestones` | ||||||
| from the :guilabel:`Invoicing Policy` drop-down menu. | ||||||
|
|
||||||
| .. image:: milestone/invoicing-policy-field.png | ||||||
| :align: center | ||||||
| :alt: The invoicing policy field drop-down menu with options on product form. | ||||||
|
|
||||||
| Beneath that is the :guilabel:`Create on Order` field. | ||||||
|
|
||||||
| To ensure workflows are as seamless as possible, it is recommended that an option in the | ||||||
| :guilabel:`Create on Order` field is selected. | ||||||
|
|
||||||
| .. note:: | ||||||
| Leaving it on the default :guilabel:`Nothing` option won't negatively affect the desired | ||||||
| workflow. However, a project *must* then be created directly from a sales order form with that | ||||||
| specific product. Once a project is created *then* milestones and tasks can be created and | ||||||
| configured. | ||||||
|
|
||||||
| When the :guilabel:`Create on Order` default option of :guilabel:`Nothing` is clicked, a drop-down | ||||||
| menu is revealed with the following options: | ||||||
|
|
||||||
| - :guilabel:`Task`: Odoo creates a task related to this milestone product in the *Projects* app when | ||||||
| this specific product is ordered. | ||||||
| - :guilabel:`Project \& Task`: Odoo creates a project and task related to this milestone product in | ||||||
| the *Projects* app when this specific product is ordered. | ||||||
| - :guilabel:`Project`: Odoo creates a project related to this milestone product in the *Projects* | ||||||
| app when this specific product is ordered. | ||||||
|
|
||||||
| When :guilabel:`Task` is selected, a :guilabel:`Project` field appears. In this field, select to | ||||||
| which existing project in the *Projects* app this created task should be connected. | ||||||
|
|
||||||
| .. image:: milestone/task-option-project-field.png | ||||||
| :align: center | ||||||
| :alt: The Project field appears when the Task option is selected in Create on Order field. | ||||||
|
|
||||||
| When :guilabel:`Project \& Task` or :guilabel:`Project` is selected, two new fields appear: | ||||||
| :guilabel:`Project Template` and :guilabel:`Workspace Template`. | ||||||
| In Odoo, milestone invoicing is configured at the product level in the **Sales** app, with milestone | ||||||
| progress and completion managed in the **Projects** app. When a milestone is marked as reached, the | ||||||
| delivered quantity on the sales order (SO) is updated and can be invoiced. | ||||||
|
|
||||||
| .. image:: milestone/project-task-option-project-workspace-fields.png | ||||||
| :align: center | ||||||
| :alt: The Project template and workspace template fields that appear on milestone product. | ||||||
| In Odoo, this workflow is driven by two key elements: | ||||||
|
|
||||||
| The :guilabel:`Project Template` field provides template options to use for the project that will be | ||||||
| created when this specific product is ordered. | ||||||
| - A service product configured with a *Based on Milestones* invoicing policy | ||||||
| - One or more milestones that represent the phases of work | ||||||
|
|
||||||
| The :guilabel:`Workspace Template` field provides template options to use for the workspace (for the | ||||||
| *Documents* app, not the *Projects* app) that will be automatically generated for the project when | ||||||
| this specific product is ordered. | ||||||
| As project work is completed, milestones are marked as reached, which automatically updates the | ||||||
| delivered quantities and makes the milestone eligible for invoicing. | ||||||
|
|
||||||
| .. tip:: | ||||||
| For organizational purposes, click the :guilabel:`Sales` tab on the product form, and enter a | ||||||
| custom 'Milestone' related descriptor in the :guilabel:`Sales Description` field. This | ||||||
| information appears in the :guilabel:`Description` column on the :guilabel:`Order Lines` tab of | ||||||
| the sales order. | ||||||
| .. important:: | ||||||
| This document covers the **Sales** app configuration and invoicing flow for invoicing based on | ||||||
| project milestones. For more information on creating, managing, and completing milestones, and | ||||||
| how to link them to tasks, see :doc:`Project milestones | ||||||
| <../../../services/project/project_management/project_milestones>`. | ||||||
|
|
||||||
| Or, directly edit/modify the :guilabel:`Description` field on the :guilabel:`Order Lines` tab of | ||||||
| the sales order. | ||||||
| Create milestone products | ||||||
| ========================= | ||||||
|
|
||||||
| This is *not* a requirement. | ||||||
| To begin, a product must be configured specifically for milestone-based invoicing. Navigate to | ||||||
| :menuselection:`Sales app --> Products --> Products` and click :guilabel:`New`. Enter the necessary | ||||||
| information, including the product title and :guilabel:`Sales Price`. | ||||||
|
|
||||||
| Invoice milestones | ||||||
| ================== | ||||||
| For the :guilabel:`Product Type`, select :guilabel:`Service`. Doing so reveals the :guilabel:`Create | ||||||
| on Order` field. Select either :guilabel:`Project`, :guilabel:`Project and Task`, or | ||||||
| :guilabel:`Task`, depending on how the product is tracked in the **Project** app. | ||||||
|
|
||||||
| .. note:: | ||||||
| The following flow features a trio of milestone products that have :guilabel:`Service` set as | ||||||
| their :guilabel:`Product Type`, and :guilabel:`Task` set on their :guilabel:`Create on Order` | ||||||
| field. | ||||||
|
|
||||||
| .. image:: milestone/settings-for-workflow.png | ||||||
| :align: center | ||||||
| :alt: Product with Service "Product Type" and "Task" in the Create on Order field on form. | ||||||
|
|
||||||
| Those tasks are then attached to a pre-existing :guilabel:`Project`, which, in this case, is | ||||||
| titled, :guilabel:`Rebranding Projects`. | ||||||
|
|
||||||
| To invoice milestones, create a sales order with the milestone product(s). To do that, go to | ||||||
| :menuselection:`Sales app --> New`. Doing so reveals a blank quotation form. | ||||||
|
|
||||||
| From this quotation form, add a :guilabel:`Customer`. Then, click :guilabel:`Add a product` in the | ||||||
| :guilabel:`Order Lines` tab. Next, add the milestone product(s) to the :guilabel:`Order Lines` tab. | ||||||
|
|
||||||
| Once the corresponding milestone product(s) have been added, click :guilabel:`Confirm` to confirm | ||||||
| the order, which turns the quotation into a sales order. | ||||||
|
|
||||||
| When the order is confirmed, new smart buttons appear at the top of the sales order based on what | ||||||
| was selected in the :guilabel:`Create on Order` field on the product form. | ||||||
|
|
||||||
| From the sales order, click the :guilabel:`Milestones` smart button. Doing so reveals a blank | ||||||
| :guilabel:`Milestones` page. Click :guilabel:`New` to add milestones. | ||||||
|
|
||||||
| .. image:: milestone/adding-milestones.png | ||||||
| :align: center | ||||||
| :alt: Adding milestones to a sales order with milestone products. | ||||||
|
|
||||||
| Enter a :guilabel:`Name` for the milestone. Next, apply it to the corresponding :guilabel:`Sales | ||||||
| Order Item`. Lastly, assign a :guilabel:`Deadline` to the milestone, if desired. | ||||||
|
|
||||||
| Repeat that process for all milestone sales order items. | ||||||
|
|
||||||
| Then, return to the sales order, via the breadcrumbs. From the sales order, click the | ||||||
| :guilabel:`Tasks` smart button. Doing so reveals a :guilabel:`Tasks` page with a task for each sales | ||||||
| order item with that option designated in the :guilabel:`Create on Order` field. | ||||||
|
|
||||||
| .. image:: milestone/tasks-page.png | ||||||
| :align: center | ||||||
| :alt: Sample tasks page accessed via the smart button from a sales order with milestone products. | ||||||
|
|
||||||
| To manually assign a configured milestone to a task, click the desired task, which reveals the task | ||||||
| form. On the task form, select the appropriate milestone to which this task should be connected, in | ||||||
| the :guilabel:`Milestone` field. | ||||||
|
|
||||||
| .. image:: milestone/milestone-field-on-task-form.png | ||||||
| :align: center | ||||||
| :alt: The milestone field on the task form when dealing with milestone products in Odoo Sales. | ||||||
|
|
||||||
| Repeat this process for all milestone tasks. | ||||||
|
|
||||||
| With those tasks properly configured, employees log in their progress as they work on the task, in | ||||||
| addition to adding any notes related to the task. | ||||||
|
|
||||||
| Then, when that task is complete, that means that milestone has been reached. At that point, it is | ||||||
| time to invoice that milestone. | ||||||
|
|
||||||
| To invoice a milestone, first return to the sales order — either via the breadcrumb links, or by | ||||||
| navigating to :menuselection:`Sales app --> Orders --> Orders` and picking the appropriate sales | ||||||
| order. | ||||||
|
|
||||||
| Back on the sales order form, click the :guilabel:`Milestones` smart button, and check the box in | ||||||
| the :guilabel:`Reached` column for that particular task. | ||||||
|
|
||||||
| .. image:: milestone/reached-milestone.png | ||||||
| :align: center | ||||||
| :alt: What it looks like to mark a milestone as reached via the milestone smart button. | ||||||
|
|
||||||
| Next, return to the sales order — either by clicking :guilabel:`View Sales Order` on the | ||||||
| :guilabel:`Milestones` page, or via the breadcrumb links. | ||||||
|
|
||||||
| Back on the sales order, the line item for the milestone that's been reached has its | ||||||
| :guilabel:`Delivered` column filled. That's because the milestone has been reached, and therefore | ||||||
| delivered. | ||||||
|
|
||||||
| .. image:: milestone/delivered-milestone-product-sales-order.png | ||||||
| :align: center | ||||||
| :alt: A milestone product that's been reached marked as delivered on the sales order in Odoo. | ||||||
|
|
||||||
| Click :guilabel:`Create Invoice` in the upper-left corner. Doing so reveals a :guilabel:`Create | ||||||
| invoices` pop-up window. | ||||||
|
|
||||||
| .. image:: milestone/create-invoices-pop-up.png | ||||||
| :align: center | ||||||
| :alt: The create invoices pop-up window that appears when create invoice button is clicked. | ||||||
|
|
||||||
| On the :guilabel:`Create invoices` pop-up window, leave the :guilabel:`Create Invoice` option on the | ||||||
| default :guilabel:`Regular Invoice` selection, and click the :guilabel:`Create Draft Invoice` | ||||||
| button. | ||||||
|
|
||||||
| Upon clicking :guilabel:`Create Draft Invoice`, Odoo reveals the :guilabel:`Customer Invoice Draft`, | ||||||
| *only* showing that reached milestone in the :guilabel:`Invoice Lines` tab. | ||||||
| A :guilabel:`Project Template` can also be selected for the product. See :doc:`Project templates | ||||||
| <../../../services/project/project_management/project_templates>` for more information. | ||||||
|
|
||||||
| .. image:: milestone/invoice-draft-milestone.png | ||||||
| :align: center | ||||||
| :alt: A customer invoice draft showing only the milestone product that's been reached. | ||||||
| For the :guilabel:`Invoicing Policy`, select :guilabel:`Based on Milestones`. This option ensures | ||||||
| that the product's delivered quantities update automatically once a milestone is completed. | ||||||
|
|
||||||
| From this invoice page, click the :guilabel:`Confirm` button to confirm the invoice. Then, when the | ||||||
| customer has paid for this milestone, click :guilabel:`Register Payment`. | ||||||
| .. important:: | ||||||
| *Based on Milestones* is only available if there is at least one project with *Milestones* | ||||||
| enabled. | ||||||
|
|
||||||
| When :guilabel:`Register Payment` is clicked, a :guilabel:`Register Payment` pop-up window appears. | ||||||
| Creating milestones from a sales order | ||||||
| ====================================== | ||||||
|
Comment on lines
+47
to
+55
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like how concise you've managed to write the milestone product creation process! However, this document is currently missing step-by-step instructions on how to create milestones. You acknowledge that milestone creation is handled in a different document, but the current text does not explicitly indicate which prerequisite steps are external. The result is a structural gap: users cannot tell where milestone creation actually occurs, nor whether the current doc expects them to arrive with milestones already defined. To do for the next revision: Add a clear, unambiguous pointer that milestone creation is not covered here, e.g., “Milestones must be created in the Project app; see Project milestones for step-by-step instructions.” Without this, the workflow appears incomplete. |
||||||
|
|
||||||
| .. image:: milestone/register-payment-pop-up.png | ||||||
| :align: center | ||||||
| :alt: The Register Payment pop-up window that appears when Register Payment is clicked. | ||||||
| After the milestone product has been sold, a *Milestones* smart button is added to the |SO|. Click | ||||||
| the smart button to view, edit, or create new milestones. | ||||||
|
|
||||||
| On this pop-up window, confirm the accuracy of the auto-populated fields, then click | ||||||
| :guilabel:`Create Payment`. | ||||||
| .. image:: milestone/view-milestones.png | ||||||
| :alt: The milestones for a sales order line. | ||||||
|
Comment on lines
+57
to
+61
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To me, this is concise but has an ambiguous implication that milestones can be manually created from the SO This section suggests that users can click the Milestones smart button and create milestones directly from the SO. You need to clarify whether this is a supported workflow or merely an editing surface. The text also avoids addressing whether Odoo supports default milestone sets tied to a milestone product (via a project template or project task structure). That is a major functional assumption the reader needs resolved. Todo for the next revision:
Note: making this doc clearer may also imply we need to make changes to the project doc. If you feel that is the case, let me know and we can begin communicating with BE! |
||||||
|
|
||||||
| When clicked, the pop-up window disappears, and Odoo returns to the invoice for that milestone, | ||||||
| which now has a green :guilabel:`In Payment` banner in the upper-right corner. This banner signifies | ||||||
| the invoice has been paid. | ||||||
| From here, the :guilabel:`Delivered %` can be altered. This amount equates to the total cost of the | ||||||
| |SO| that is billed when the milestone is reached. | ||||||
|
Comment on lines
+63
to
+64
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I might be overthinking here, but the draft mixes two concepts—percentage-based delivery and cost of the SO delivered—without defining how Odoo interprets the Delivered % field. There is an implicit assumption that the system prorates invoiceable quantity strictly by percentage, which may not match actual configuration. I believe there are two methods: invoicing based on milestone percentage or sales price, so I'd like your help doing some testing to find out how this works, and likely need to document them separately using different examples or workflows. Todo:
|
||||||
|
|
||||||
| .. image:: milestone/in-payment-invoice.png | ||||||
| :align: center | ||||||
| :alt: An invoice with a milestone product that has been paid with an In Payment banner. | ||||||
| .. example:: | ||||||
| A company sells a *Custom furniture design* product with four milestones: | ||||||
|
|
||||||
| Then, return to the sales order, via the breadcrumb links. Back on the sales order, in the | ||||||
| :guilabel:`Order Lines` tab, the reached milestone that's been invoiced and paid for, now has its | ||||||
| :guilabel:`Invoiced` column filled. | ||||||
| - Initial design consult | ||||||
| - Preliminary designs submitted | ||||||
| - Final design submission | ||||||
| - Final product delivered | ||||||
|
Comment on lines
+63
to
+72
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this example is clear but seems to be in the wrong place, in my opinion? It's trying to do two things at once:
|
||||||
|
|
||||||
| .. image:: milestone/invoiced-column-filled-milestone.png | ||||||
| :align: center | ||||||
| :alt: The Invoiced column of a milestone product that's been paid for is filled. | ||||||
| Each of these milestones has a *Delivered %* of `25%`. As each milestone is marked complete, a | ||||||
| corresponding `25%` of the total number of hours is marked as *Delievered* on the invoice. | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| There is also a new :guilabel:`Invoices` smart button at the top of the sales order. Clicking that | ||||||
| reveals all the invoices that are connected to this sales order. | ||||||
| Invoicing a completed milestone | ||||||
| =============================== | ||||||
|
|
||||||
| .. image:: milestone/invoices-smart-button.png | ||||||
| :align: center | ||||||
| :alt: The invoices smart button that appears at the top of a sales order with milestones. | ||||||
| Milestones can be tracked through the **Project** app (see :ref:`Using milestones | ||||||
| <project/using-milestones>`). Additionally, a milestone can be marked as :guilabel:`Reached` on the | ||||||
| *Milestones* page by ticking the checkbox for that milestone. | ||||||
|
|
||||||
| Simply repeat the above process for each milestone as it is worked on, and subsequently, completed. | ||||||
| Then, click :guilabel:`View Sales Order` or use the breadcrumbs to return to the |SO|. The | ||||||
| :guilabel:`Delivered` column will be updated to reflect the *Delivered %* for the milestone reached. | ||||||
| Click :guilabel:`Create Invoice`. | ||||||
|
Comment on lines
+77
to
+86
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The invoicing workflow is described in conceptual terms but leaves out necessary navigational and field-level instructions. Users cannot reconstruct the actual UI path or the required field interactions.
Todo: Rewrite the invoicing steps with explicit UI elements, e.g.:
Avoid abstract phrases like “can be tracked through” and “is updated”; replace them with concrete instructions and field names. |
||||||
|
|
||||||
| Continue that process until the entire project has been completed, each milestone has been invoiced, | ||||||
| and the entire order has been paid for in full. | ||||||
| These steps can be repeated as additional milestones are reached until the |SO| has been fulfilled. | ||||||
|
|
||||||
| .. seealso:: | ||||||
| - :doc:`time_materials` | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand why this section was removed because it's unrelated to the sales flow, and it's covered in the project milestone doc
However, we should acknowledge that the milestone can be marked as reached and link to the doc that outlines how