diff --git a/addons/sale_project/models/project.py b/addons/sale_project/models/project.py
index 523fad6b108..94df2d0c965 100644
--- a/addons/sale_project/models/project.py
+++ b/addons/sale_project/models/project.py
@@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
+from ast import literal_eval
+
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
@@ -38,6 +40,8 @@ class ProjectTask(models.Model):
"and if this employee is not in the 'Employee/Sales Order Item Mapping' of the project, the "
"timesheet entry will be linked to this sales order item.")
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')
+ task_to_invoice = fields.Boolean("To invoice", compute='_compute_task_to_invoice', search='_search_task_to_invoice', groups='sales_team.group_sale_salesman_all_leads')
@api.depends('project_id.sale_line_id.order_partner_id')
def _compute_partner_id(self):
@@ -96,3 +100,42 @@ class ProjectTask(models.Model):
if partner:
return partner
return super().rating_get_partner_id()
+
+ @api.depends('sale_order_id.invoice_status', 'sale_order_id.order_line')
+ def _compute_task_to_invoice(self):
+ for task in self:
+ if task.sale_order_id:
+ task.task_to_invoice = bool(task.sale_order_id.invoice_status not in ('no', 'invoiced'))
+ else:
+ task.task_to_invoice = False
+
+ @api.model
+ def _search_task_to_invoice(self, operator, value):
+ query = """
+ SELECT so.id
+ FROM sale_order so
+ WHERE so.invoice_status != 'invoiced'
+ AND so.invoice_status != 'no'
+ """
+ operator_new = 'inselect'
+ if(bool(operator == '=') ^ bool(value)):
+ operator_new = 'not inselect'
+ return [('sale_order_id', operator_new, (query, ()))]
+
+ def action_create_invoice(self):
+ # ensure the SO exists before invoicing, then confirm it
+ so_to_confirm = self.filtered(
+ lambda task: task.sale_order_id and task.sale_order_id.state in ['draft', 'sent']
+ ).mapped('sale_order_id')
+ so_to_confirm.action_confirm()
+
+ # redirect create invoice wizard (of the Sales Order)
+ action = self.env.ref('sale.action_view_sale_advance_payment_inv').read()[0]
+ context = literal_eval(action.get('context', "{}"))
+ context.update({
+ 'active_id': self.sale_order_id.id if len(self) == 1 else False,
+ 'active_ids': self.mapped('sale_order_id').ids,
+ 'default_company_id': self.company_id.id,
+ })
+ action['context'] = context
+ return action
diff --git a/addons/sale_project/views/project_task_views.xml b/addons/sale_project/views/project_task_views.xml
index 4ccd0f8b9c9..d45fdd10d26 100644
--- a/addons/sale_project/views/project_task_views.xml
+++ b/addons/sale_project/views/project_task_views.xml
@@ -56,6 +56,22 @@
+
+
+
+
+
+
+
+
+
+ Create invoice
+
+
+ code
+
+ if records:
+ action = records.action_create_invoice()