diff --git a/addons/product/models/product_template.py b/addons/product/models/product_template.py index c3e8dc65f42..b80b4411cfe 100644 --- a/addons/product/models/product_template.py +++ b/addons/product/models/product_template.py @@ -373,7 +373,7 @@ class ProductTemplate(models.Model): for tmpl_id in self.with_context(active_test=False): # adding an attribute with only one value should not recreate product # write this attribute on every product to make sure we don't lose them - variant_alone = tmpl_id.attribute_line_ids.filtered(lambda line: len(line.value_ids) == 1).mapped('value_ids') + variant_alone = tmpl_id.attribute_line_ids.filtered(lambda line: line.attribute_id.create_variant and len(line.value_ids) == 1).mapped('value_ids') for value_id in variant_alone: updated_products = tmpl_id.product_variant_ids.filtered(lambda product: value_id.attribute_id not in product.mapped('attribute_value_ids.attribute_id')) updated_products.write({'attribute_value_ids': [(4, value_id.id)]}) diff --git a/addons/product/tests/test_variants.py b/addons/product/tests/test_variants.py index 939ae0f9f47..1a621d689cb 100644 --- a/addons/product/tests/test_variants.py +++ b/addons/product/tests/test_variants.py @@ -152,3 +152,181 @@ class TestVariants(common.TestProductCommon): 'value_ids': [(4, self.size_attr_value_l.id)], })] }) + + +class TestVariantsNoCreate(common.TestProductCommon): + + def setUp(self): + super(TestVariantsNoCreate, self).setUp() + self.size = self.env['product.attribute'].create({ + 'name': 'Size', + 'create_variant': False, + 'value_ids': [(0, 0, {'name': 'S'}), (0, 0, {'name': 'M'}), (0, 0, {'name': 'L'})], + }) + self.size_S = self.size.value_ids[0] + self.size_M = self.size.value_ids[1] + self.size_L = self.size.value_ids[2] + + def test_create_mono(self): + """ create a product with a 'nocreate' attribute with a single value """ + template = self.env['product.template'].create({ + 'name': 'Sofa', + 'uom_id': self.uom_unit.id, + 'uom_po_id': self.uom_unit.id, + 'attribute_line_ids': [(0, 0, { + 'attribute_id': self.size.id, + 'value_ids': [(4, self.size_S.id)], + })], + }) + self.assertEqual(len(template.product_variant_ids), 1) + self.assertFalse(template.product_variant_ids.attribute_value_ids) + + def test_update_mono(self): + """ modify a product with a 'nocreate' attribute with a single value """ + template = self.env['product.template'].create({ + 'name': 'Sofa', + 'uom_id': self.uom_unit.id, + 'uom_po_id': self.uom_unit.id, + }) + self.assertEqual(len(template.product_variant_ids), 1) + + template.write({ + 'attribute_line_ids': [(0, 0, { + 'attribute_id': self.size.id, + 'value_ids': [(4, self.size_S.id)], + })], + }) + self.assertEqual(len(template.product_variant_ids), 1) + self.assertFalse(template.product_variant_ids.attribute_value_ids) + + def test_create_multi(self): + """ create a product with a 'nocreate' attribute with several values """ + template = self.env['product.template'].create({ + 'name': 'Sofa', + 'uom_id': self.uom_unit.id, + 'uom_po_id': self.uom_unit.id, + 'attribute_line_ids': [(0, 0, { + 'attribute_id': self.size.id, + 'value_ids': [(6, 0, self.size.value_ids.ids)], + })], + }) + self.assertEqual(len(template.product_variant_ids), 1) + self.assertFalse(template.product_variant_ids.attribute_value_ids) + + def test_update_multi(self): + """ modify a product with a 'nocreate' attribute with several values """ + template = self.env['product.template'].create({ + 'name': 'Sofa', + 'uom_id': self.uom_unit.id, + 'uom_po_id': self.uom_unit.id, + }) + self.assertEqual(len(template.product_variant_ids), 1) + + template.write({ + 'attribute_line_ids': [(0, 0, { + 'attribute_id': self.size.id, + 'value_ids': [(6, 0, self.size.value_ids.ids)], + })], + }) + self.assertEqual(len(template.product_variant_ids), 1) + self.assertFalse(template.product_variant_ids.attribute_value_ids) + + def test_create_mixed_mono(self): + """ create a product with regular and 'nocreate' attributes """ + template = self.env['product.template'].create({ + 'name': 'Sofa', + 'uom_id': self.uom_unit.id, + 'uom_po_id': self.uom_unit.id, + 'attribute_line_ids': [ + (0, 0, { # no variants for this one + 'attribute_id': self.size.id, + 'value_ids': [(4, self.size_S.id)], + }), + (0, 0, { # two variants for this one + 'attribute_id': self.prod_att_1.id, + 'value_ids': [(4, self.prod_attr1_v1.id), (4, self.prod_attr1_v2.id)], + }), + ], + }) + self.assertEqual(len(template.product_variant_ids), 2) + self.assertEqual( + {variant.attribute_value_ids for variant in template.product_variant_ids}, + {self.prod_attr1_v1, self.prod_attr1_v2}, + ) + + def test_update_mixed_mono(self): + """ modify a product with regular and 'nocreate' attributes """ + template = self.env['product.template'].create({ + 'name': 'Sofa', + 'uom_id': self.uom_unit.id, + 'uom_po_id': self.uom_unit.id, + }) + self.assertEqual(len(template.product_variant_ids), 1) + + template.write({ + 'attribute_line_ids': [ + (0, 0, { # no variants for this one + 'attribute_id': self.size.id, + 'value_ids': [(4, self.size_S.id)], + }), + (0, 0, { # two variants for this one + 'attribute_id': self.prod_att_1.id, + 'value_ids': [(4, self.prod_attr1_v1.id), (4, self.prod_attr1_v2.id)], + }), + ], + }) + self.assertEqual(len(template.product_variant_ids), 2) + self.assertEqual( + {variant.attribute_value_ids for variant in template.product_variant_ids}, + {self.prod_attr1_v1, self.prod_attr1_v2}, + ) + + def test_create_mixed_multi(self): + """ create a product with regular and 'nocreate' attributes """ + template = self.env['product.template'].create({ + 'name': 'Sofa', + 'uom_id': self.uom_unit.id, + 'uom_po_id': self.uom_unit.id, + 'attribute_line_ids': [ + (0, 0, { # no variants for this one + 'attribute_id': self.size.id, + 'value_ids': [(6, 0, self.size.value_ids.ids)], + }), + (0, 0, { # two variants for this one + 'attribute_id': self.prod_att_1.id, + 'value_ids': [(4, self.prod_attr1_v1.id), (4, self.prod_attr1_v2.id)], + }), + ], + }) + self.assertEqual(len(template.product_variant_ids), 2) + self.assertEqual( + {variant.attribute_value_ids for variant in template.product_variant_ids}, + {self.prod_attr1_v1, self.prod_attr1_v2}, + ) + + def test_update_mixed_multi(self): + """ modify a product with regular and 'nocreate' attributes """ + template = self.env['product.template'].create({ + 'name': 'Sofa', + 'uom_id': self.uom_unit.id, + 'uom_po_id': self.uom_unit.id, + }) + self.assertEqual(len(template.product_variant_ids), 1) + + template.write({ + 'attribute_line_ids': [ + (0, 0, { # no variants for this one + 'attribute_id': self.size.id, + 'value_ids': [(6, 0, self.size.value_ids.ids)], + }), + (0, 0, { # two variants for this one + 'attribute_id': self.prod_att_1.id, + 'value_ids': [(4, self.prod_attr1_v1.id), (4, self.prod_attr1_v2.id)], + }), + ], + }) + self.assertEqual(len(template.product_variant_ids), 2) + self.assertEqual( + {variant.attribute_value_ids for variant in template.product_variant_ids}, + {self.prod_attr1_v1, self.prod_attr1_v2}, + )