diff --git a/addons/sale_project/models/project.py b/addons/sale_project/models/project.py index 10bb47f2a5d..204ed64dd5f 100644 --- a/addons/sale_project/models/project.py +++ b/addons/sale_project/models/project.py @@ -12,7 +12,7 @@ class Project(models.Model): sale_line_id = fields.Many2one( 'sale.order.line', 'Sales Order Item', copy=False, - compute="_compute_sale_line_id", store=True, readonly=False, + compute="_compute_sale_line_id", store=True, readonly=False, index=True, domain="[('is_service', '=', True), ('is_expense', '=', False), ('state', 'in', ['sale', 'done']), ('order_partner_id', '=?', partner_id), '|', ('company_id', '=', False), ('company_id', '=', company_id)]", help="Sales order item to which the project is linked. Link the timesheet entry to the sales order item defined on the project. " "Only applies on tasks without sale order item defined, and if the employee is not in the 'Employee/Sales Order Item Mapping' of the project.") @@ -61,7 +61,7 @@ class ProjectTask(models.Model): sale_order_id = fields.Many2one('sale.order', 'Sales Order', compute='_compute_sale_order_id', store=True, help="Sales order to which the task is linked.") sale_line_id = fields.Many2one( 'sale.order.line', 'Sales Order Item', domain="[('company_id', '=', company_id), ('is_service', '=', True), ('order_partner_id', 'child_of', commercial_partner_id), ('is_expense', '=', False), ('state', 'in', ['sale', 'done'])]", - compute='_compute_sale_line', recursive=True, store=True, readonly=False, copy=False, tracking=True, + compute='_compute_sale_line', recursive=True, store=True, readonly=False, copy=False, tracking=True, index=True, help="Sales Order Item to which the time spent on this task will be added, in order to be invoiced to your customer.") project_sale_order_id = fields.Many2one('sale.order', string="Project's sale order", related='project_id.sale_order_id') invoice_count = fields.Integer("Number of invoices", related='sale_order_id.invoice_count') diff --git a/addons/sale_project/models/sale_order.py b/addons/sale_project/models/sale_order.py index b91be8db811..10795b84a15 100644 --- a/addons/sale_project/models/sale_order.py +++ b/addons/sale_project/models/sale_order.py @@ -353,3 +353,24 @@ class SaleOrderLine(models.Model): project = map_so_project[so_line.order_id.id] if not so_line.task_id: so_line._timesheet_create_task(project=project) + + def _prepare_invoice_line(self, **optional_values): + """ + If the sale order line isn't linked to a sale order which already have a default analytic account, + this method allows to retrieve the analytic account which is linked to project or task directly linked + to this sale order line, or the analytic account of the project which uses this sale order line, if it exists. + """ + values = super(SaleOrderLine, self)._prepare_invoice_line(**optional_values) + if not values['analytic_account_id']: + if self.project_id.analytic_account_id: + values['analytic_account_id'] = self.project_id.analytic_account_id + elif self.task_id.project_id.analytic_account_id: + values['analytic_account_id'] = self.task_id.project_id.analytic_account_id + elif self.is_service and not self.is_expense: + project_analytic_account_id = self.env['project.project'].read_group([ + '|', ('sale_line_id', '=', self.id), ('task_ids.sale_line_id', '=', self.id) + ], ['analytic_account_id'], ['analytic_account_id']) + analytic_account_ids = {rec['analytic_account_id'][0] for rec in project_analytic_account_id} + if len(analytic_account_ids) == 1: + values['analytic_account_id'] = analytic_account_ids.pop() + return values