From d629f90eb57ac59fb5abcb745bbf18758f08abf8 Mon Sep 17 00:00:00 2001 From: Damien Bouvy Date: Tue, 16 Jul 2019 08:29:03 +0000 Subject: [PATCH] [IMP] sale_management: no client reload when adding optional product Purpose ======= Avoid a complete reload of the web client when adding a optional product, which loses searches, breadcrumb, etc. This is achieved by adding a non-stored 'is_present' computed field which is computed depending on the presence of a SO line linked to the option line - that way its is dynamically adapted when the option is added to the SO. Since we wanted a clear feedback when the option was added to the quote, green colouring and the disappearance of the 'add to quote' button have been added. Note that this field *cannot* be stored - since the line_id field on the option bypasses the ORM (`set null` for the on_delete attribute), it would not recompute properly upon deletion of the linked SO line. Task#1950410 closes odoo/odoo#34929 Signed-off-by: Damien Bouvy (dbo) --- addons/sale_management/models/sale_order.py | 19 +++++++++++++++++-- .../views/sale_order_views.xml | 9 ++++++--- .../views/sale_portal_templates.xml | 4 ++-- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/addons/sale_management/models/sale_order.py b/addons/sale_management/models/sale_order.py index e2c6210e169..47d224daac0 100644 --- a/addons/sale_management/models/sale_order.py +++ b/addons/sale_management/models/sale_order.py @@ -153,8 +153,12 @@ class SaleOrderOption(models.Model): _description = "Sale Options" _order = 'sequence, id' + is_present = fields.Boolean(string="Present on Quotation", + help="This field will be checked if the option line's product is " + "already present in the quotation.", + compute="_compute_is_present", search="_search_is_present") order_id = fields.Many2one('sale.order', 'Sales Order Reference', ondelete='cascade', index=True) - line_id = fields.Many2one('sale.order.line', ondelete="set null") + line_id = fields.Many2one('sale.order.line', ondelete="set null", copy=False) name = fields.Text('Description', required=True) product_id = fields.Many2one('product.product', 'Product', required=True, domain=[('sale_ok', '=', True)]) price_unit = fields.Float('Unit Price', required=True, digits='Product Price') @@ -163,6 +167,18 @@ class SaleOrderOption(models.Model): quantity = fields.Float('Quantity', required=True, digits='Product UoS', default=1) sequence = fields.Integer('Sequence', help="Gives the sequence order when displaying a list of optional products.") + @api.depends('line_id', 'order_id.order_line', 'product_id') + def _compute_is_present(self): + # NOTE: this field cannot be stored as the line_id is usually removed + # through cascade deletion, which means the compute would be false + for option in self: + option.is_present = bool(option.order_id.order_line.filtered(lambda l: l.product_id == option.product_id)) + + def _search_is_present(self, operator, value): + if (operator, value) in [('=', True), ('!=', False)]: + return [('line_id', '=', False)] + return [('line_id', '!=', False)] + @api.onchange('product_id', 'uom_id') def _onchange_product_id(self): if not self.product_id: @@ -181,7 +197,6 @@ class SaleOrderOption(models.Model): @api.multi def button_add_to_order(self): self.add_option_to_order() - return {'type': 'ir.actions.client', 'tag': 'reload'} @api.multi def add_option_to_order(self): diff --git a/addons/sale_management/views/sale_order_views.xml b/addons/sale_management/views/sale_order_views.xml index d67671ab6de..e4e78db4a1b 100644 --- a/addons/sale_management/views/sale_order_views.xml +++ b/addons/sale_management/views/sale_order_views.xml @@ -17,6 +17,7 @@ + @@ -24,6 +25,7 @@ +
@@ -36,7 +38,7 @@
-
@@ -60,7 +62,7 @@ - + @@ -71,7 +73,8 @@ -