Project work "views" used for invoicing

I’m learning to use the project module and am wondering whether it is possible to group multiple project works into one invoice line? I would like to invoice a client for a parent works “view” (not available to timesheets) rather than for the “leaf” works that employees would use to complete a project. The child works would be invoiced using the product of the parent.

For example:

- project root
    - parent view (becomes invoice line using time or effort accumulated from child works)
        - low-level work (not invoiced directly, but used for timesheet or effort tracking)
        - another low-level work
    - another parent view

Has anyone had this use case, or does a better pattern exist?

This is perfectly possible you just need to set the product on what you call parent view and set it as project with invoice method on timesheet. All timesheets related to children tasks will be included as part of the the project invoice line.

You can have as much as parent views as you want. Also you can combine diferent invoice methods for each project contained inside another project.

Thanks for the insight, @pokoli. However, when I set each parent view as a project and invoice method to “On Timesheet” or “On Effort”, if I don’t set a product on the child tasks but only on the parent project, an invoice line (or invoice) is not created for that parent project. Revenue for the project shows up as zero. If I set a product on each of the child tasks, an invoice for each parent project is created with the child tasks as invoice lines. What I want is one invoice for the entire tree with an invoice line for each parent view.

On a different tack, if I set a product and some amount of effort only on the parent view and use the “On Effort” invoice method, the parent view does show up as one invoice line. This is a step in the right direction, but it would be nice in my particular use case if the efforts of a child without a product rolled up to the parent (product) so I could keep track of the effort spent on each child rather than entering a summarized number on the parent.

With the invoice method “On Timesheet”, the behavior that I’m seeing is that timesheets on the children don’t automatically roll up to the parent project if they don’t have a product set. If they do have a product set, the children are billed as separate invoice lines.

Would rolling up the child tasks for invoicing be considered a new #feature or rather as an undesired behavior? The projects report rolls up the expected revenue and costs, so I just assumed that I would be able to invoice the child tasks on the parent in a similar way. But I’m sure I’m not thinking of edge cases here.

Invoice lines of tasks are grouped as long as they have the same grouping values like product, unit, unit_price and description.
And of course for sub-project they must also have the same company and party.

Thanks @ced, that was super helpful. An idea that might work for my current purposes is to remove the description from the key and construct a summarized description within the Work._get_invoice_line function with something like this:

description = '; '.join(list(dict.fromkeys(l['description'] for l in lines)))
invoice_line.description = description

While it would preserve the current functionality (group tasks with the same description), I think it might be too eager to group in general (e.g. where someone is using the same service labor product for tasks they want itemized individually on the invoice). I wonder whether there might be some heuristic to figure out whether a group of tasks with different descriptions but the same product, etc. should be summarized onto one invoice line?

Also, a hardcoded semicolon as a separator may not be ideal.

Or another approach that might work even better would be to key on the description or the parent’s description depending on some other heuristic.

I guess we could have a check box to include a task in the parent which indeed just use the parent description instead of the its description for the invoice line grouping.

I have another idea that would be more flexible and might work more generally. Introduce a new field for a project work (in the project_invoice module) that references another work that is used for the description for the invoice line. It would need to be a direct ancestor or self, be in the same project, and have the same product, unit, and unit_price. By default it would be a reference to itself. The description of this referenced work would be used in the key for the invoice line for all the tasks within its group.

This would give the ability to summarize a group of tasks not only on the parent, but on an ancestor further up the tree as well.

Though a check box to use the parent as the invoice line grouping could do the same thing recursively.

Started tracking work here: Issue 11579: Parent-level invoice line groupings for project tasks - Tryton issue tracker