From 69c86a2c1a7fc453b3e397402a64c37f776a1fdc Mon Sep 17 00:00:00 2001 From: Damien Bouvy Date: Thu, 2 Jan 2020 13:05:46 +0000 Subject: [PATCH] [FIX] sale: prevent inconsistent company field on products If a user changes the company of a product, we should make sure that the product was not sold in another company in the past; otherwise it could make some orders un-invoiceable. closes odoo/odoo#43187 X-original-commit: 069f04935ebc22c15b4903b526401ebf0df830a3 Signed-off-by: Damien Bouvy (dbo) --- addons/sale/i18n/sale.pot | 11 +++++++++++ addons/sale/models/product_template.py | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/addons/sale/i18n/sale.pot b/addons/sale/i18n/sale.pot index b9152fe8547..43960af1000 100644 --- a/addons/sale/i18n/sale.pot +++ b/addons/sale/i18n/sale.pot @@ -3538,6 +3538,17 @@ msgstr "" msgid "The fixed amount to be invoiced in advance, taxes excluded." msgstr "" +#. module: sale +#: code:addons/sale/models/product_template.py:0 +msgid "" +"The following products cannot be restricted to the company" +" %s because they have already been used in quotations or " +"sales orders in another company:\n%s\n" +"You can archive these products and recreate them " +"with your company restriction instead, or leave them as " +"shared product." +msgstr "" + #. module: sale #: model:ir.model.fields,help:sale.field_res_config_settings__automatic_invoice msgid "" diff --git a/addons/sale/models/product_template.py b/addons/sale/models/product_template.py index b32a8a5442c..35f59dbb205 100644 --- a/addons/sale/models/product_template.py +++ b/addons/sale/models/product_template.py @@ -6,6 +6,7 @@ import logging from odoo import api, fields, models, _ from odoo.addons.base.models.res_partner import WARNING_MESSAGE, WARNING_HELP +from odoo.exceptions import ValidationError from odoo.tools.float_utils import float_round _logger = logging.getLogger(__name__) @@ -47,6 +48,25 @@ class ProductTemplate(models.Model): for product in self: product.sales_count = float_round(sum([p.sales_count for p in product.with_context(active_test=False).product_variant_ids]), precision_rounding=product.uom_id.rounding) + + @api.constrains('company_id') + def _check_sale_product_company(self): + """Ensure the product is not being restricted to a single company while + having been sold in another one in the past, as this could cause issues.""" + target_company = self.company_id + if target_company: # don't prevent writing `False`, should always work + product_data = self.env['product.product'].sudo().with_context(active_test=False).search_read([('product_tmpl_id', 'in', self.ids)], fields=['id']) + product_ids = list(map(lambda p: p['id'], product_data)) + so_lines = self.env['sale.order.line'].sudo().search_read([('product_id', 'in', product_ids), ('company_id', '!=', target_company.id)], fields=['id', 'product_id']) + used_products = list(map(lambda sol: sol['product_id'][1], so_lines)) + if so_lines: + raise ValidationError(_('The following products cannot be restricted to the company' + ' %s because they have already been used in quotations or ' + 'sales orders in another company:\n%s\n' + 'You can archive these products and recreate them ' + 'with your company restriction instead, or leave them as ' + 'shared product.') % (target_company.name, ', '.join(used_products))) + def action_view_sales(self): action = self.env.ref('sale.report_all_channels_sales_action').read()[0] action['domain'] = [('product_tmpl_id', 'in', self.ids)]