diff --git a/addons/product/models/product.py b/addons/product/models/product.py index e0801ce4967..530d920dbf6 100644 --- a/addons/product/models/product.py +++ b/addons/product/models/product.py @@ -348,11 +348,7 @@ class ProductProduct(models.Model): if 'product_template_attribute_value_ids' in values: # `_get_variant_id_for_combination` depends on `product_template_attribute_value_ids` self.clear_caches() - if 'active' in values: - # prefetched o2m have to be reloaded (because of active_test) - # (eg. product.template: product_variant_ids) - self.flush() - self.invalidate_cache() + elif 'active' in values: # `_get_first_possible_variant_id` depends on variants active state self.clear_caches() return res diff --git a/addons/product/models/product_pricelist.py b/addons/product/models/product_pricelist.py index ba2bfb4229c..ecd118c3405 100644 --- a/addons/product/models/product_pricelist.py +++ b/addons/product/models/product_pricelist.py @@ -571,12 +571,7 @@ class PricelistItem(models.Model): values.update(dict(product_id=None, categ_id=None)) elif applied_on == '0_product_variant': values.update(dict(categ_id=None)) - res = super(PricelistItem, self).write(values) - # When the pricelist changes we need the product.template price - # to be invalided and recomputed. - self.flush() - self.invalidate_cache() - return res + return super(PricelistItem, self).write(values) def _is_applicable_for(self, product, qty_in_product_uom): """Check whether the current rule is valid for the given product & qty. diff --git a/addons/product/tests/test_variants.py b/addons/product/tests/test_variants.py index 0cc9e5cb657..35f9a8e1450 100644 --- a/addons/product/tests/test_variants.py +++ b/addons/product/tests/test_variants.py @@ -5,6 +5,8 @@ import base64 from collections import OrderedDict from datetime import timedelta import io +import unittest.mock + from PIL import Image from . import common @@ -1199,3 +1201,52 @@ class TestVariantsArchive(common.TestProductCommon): variants = variants or self.template.product_variant_ids self.assertEqual(len(variants), 1) self.assertFalse(variants[0].product_template_attribute_value_ids) + + +class TestVariantWrite(TransactionCase): + + def test_active_one2many(self): + template = self.env['product.template'].create({'name': 'Foo', 'description': 'Foo'}) + self.assertEqual(len(template.product_variant_ids), 1) + + # check the consistency of one2many field product_variant_ids w.r.t. active variants + variant1 = template.product_variant_ids + variant2 = self.env['product.product'].create({'product_tmpl_id': template.id}) + self.assertEqual(template.product_variant_ids, variant1 + variant2) + + variant2.active = False + self.assertEqual(template.product_variant_ids, variant1) + + variant2.active = True + self.assertEqual(template.product_variant_ids, variant1 + variant2) + + variant1.active = False + self.assertEqual(template.product_variant_ids, variant2) + + def test_write_inherited_field(self): + product = self.env['product.product'].create({'name': 'Foo', 'sequence': 1}) + self.assertEqual(product.name, 'Foo') + self.assertEqual(product.sequence, 1) + + self.env['product.pricelist'].create({ + 'name': 'Foo', + 'item_ids': [(0, 0, {'product_id': product.id, 'fixed_price': 1})], + }) + + # patch template.write to modify pricelist items, which causes some + # cache invalidation + Template = self.registry['product.template'] + Template_write = Template.write + + def write(self, vals): + result = Template_write(self, vals) + items = self.env['product.pricelist.item'].search([('product_id', '=', product.id)]) + items.fixed_price = 2 + return result + + with unittest.mock.patch.object(Template, 'write', write): + # change both 'name' and 'sequence': due to some programmed cache + # invalidation, the second field may not be properly assigned + product.write({'name': 'Bar', 'sequence': 2}) + self.assertEqual(product.name, 'Bar') + self.assertEqual(product.sequence, 2)