From ac41cd819596ce265ddc233594fbb374d46c915f Mon Sep 17 00:00:00 2001 From: Mitali Patel Date: Tue, 24 Jul 2018 14:31:36 +0530 Subject: [PATCH] [IMP] mrp: Change the condition 'and' to 'or' in product variants having the same attribute value For example: I want to consume a component A if the product is grey OR yellow. Currently,the component A will be consumed if the product is grey AND yellow. But this variant never exists as grey and yellow are values for the same attribute. So if the values are for the same attribute, odoo should check for a product that is GREY OR YELLOW (and not GREY AND YELLOW). TASK-ID: 1865604 --- addons/mrp/models/mrp_bom.py | 8 +++-- addons/mrp/tests/test_bom.py | 67 ++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/addons/mrp/models/mrp_bom.py b/addons/mrp/models/mrp_bom.py index c8b965a89c3..58df0ad6d14 100644 --- a/addons/mrp/models/mrp_bom.py +++ b/addons/mrp/models/mrp_bom.py @@ -6,6 +6,8 @@ from odoo.addons import decimal_precision as dp from odoo.exceptions import UserError, ValidationError from odoo.tools import float_round +from itertools import groupby + class MrpBom(models.Model): """ Defines bills of material for a product or a product template """ @@ -292,8 +294,10 @@ class MrpBomLine(models.Model): custom control. It currently checks that all variant values are in the product. """ if self.attribute_value_ids: - if not product or self.attribute_value_ids - product.attribute_value_ids: - return True + for att, att_values in groupby(self.attribute_value_ids, lambda l: l.attribute_id): + values = self.env['product.attribute.value'].concat(*list(att_values)) + if not (product.attribute_value_ids & values): + return True return False @api.multi diff --git a/addons/mrp/tests/test_bom.py b/addons/mrp/tests/test_bom.py index 0cd8f9effa4..44fd56b6431 100644 --- a/addons/mrp/tests/test_bom.py +++ b/addons/mrp/tests/test_bom.py @@ -161,3 +161,70 @@ class TestBoM(TestMrpCommon): }) with self.assertRaises(exceptions.UserError): test_bom_3.explode(self.product_9, 1) + + def test_multi_level_variants2(self): + """Test skip bom line with same attribute values in bom lines.""" + + Product = self.env['product.product'] + ProductAttribute = self.env['product.attribute'] + ProductAttributeValue = self.env['product.attribute.value'] + MrpProduction = self.env['mrp.production'] + + # Product Attribute + att_color = ProductAttribute.create({'name': 'Color'}) + att_size = ProductAttribute.create({'name': 'size'}) + + # Product Attribute color Value + att_color_red = ProductAttributeValue.create({'name': 'red', 'attribute_id': att_color.id}) + att_color_blue = ProductAttributeValue.create({'name': 'blue', 'attribute_id': att_color.id}) + # Product Attribute size Value + att_size_big = ProductAttributeValue.create({'name': 'big', 'attribute_id': att_size.id}) + att_size_medium = ProductAttributeValue.create({'name': 'medium', 'attribute_id': att_size.id}) + + # Create Template Product + product_template = self.env['product.template'].create({ + 'name': 'Sofa', + 'attribute_line_ids': [(0, 0, { + 'attribute_id': att_color.id, + 'value_ids': [(6, 0, [att_color_red.id, att_color_blue.id])] + }), (0, 0, { + 'attribute_id': att_size.id, + 'value_ids': [(6, 0, [att_size_big.id, att_size_medium.id])] + })] + }) + + # Create components Of BOM + product_A = Product.create({ + 'name': 'Wood'}) + product_B = Product.create({ + 'name': 'Clothes'}) + + # Create BOM + test_bom = self.env['mrp.bom'].create({ + 'product_tmpl_id': product_template.id, + 'product_qty': 1.0, + 'type': 'normal', + 'bom_line_ids': [(0, 0, { + 'product_id': product_A.id, + 'product_qty': 1, + 'attribute_value_ids': [(4, att_color_red.id), (4, att_color_blue.id), (4, att_size_big.id)], + }), (0, 0, { + 'product_id': product_B.id, + 'product_qty': 1, + 'attribute_value_ids': [(4, att_color_red.id), (4, att_color_blue.id)] + })] + }) + + combination = {(att_color_red, att_size_big): [product_A.id, product_B.id] , (att_color_red, att_size_medium): [product_B.id] , (att_color_blue, att_size_big):[product_A.id, product_B.id], (att_color_blue, att_size_medium): [product_B.id]} + + # Create production order for all variants. + for comb in combination.keys(): + consu_product_ids = combination[comb] + product = product_template.product_variant_ids.filtered(lambda x: all(value in comb for value in x.attribute_value_ids)) + mrp_order = MrpProduction.create({ + 'product_uom_id': product.uom_id.id, + 'product_id': product.id, + 'bom_id': test_bom.id, + }) + # Check consumed materials in production order. + self.assertEqual(mrp_order.move_raw_ids.mapped('product_id').ids, consu_product_ids)