diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py index 5890b5d1e9..a8f69cac33 100644 --- a/erpnext/controllers/item_variant.py +++ b/erpnext/controllers/item_variant.py @@ -12,7 +12,7 @@ class InvalidItemAttributeValueError(frappe.ValidationError): pass class ItemTemplateCannotHaveStock(frappe.ValidationError): pass @frappe.whitelist() -def get_variant(item, args): +def get_variant(variant, template, args): """Validates Attributes and their Values, then looks for an exactly matching Item Variant :param item: Template Item @@ -24,9 +24,9 @@ def get_variant(item, args): if not args: frappe.throw(_("Please specify at least one attribute in the Attributes table")) - validate_item_variant_attributes(item, args) + validate_item_variant_attributes(template, args) - return find_variant(item, args) + return find_variant(variant, template, args) def validate_item_variant_attributes(item, args): attribute_values = {} @@ -65,7 +65,7 @@ def validate_item_variant_attributes(item, args): frappe.throw(_("Value {0} for Attribute {1} does not exist in the list of valid Item Attribute Values").format( value, attribute)) -def find_variant(item, args): +def find_variant(variant_item_code, template, args): conditions = ["""(iv_attribute.attribute="{0}" and iv_attribute.attribute_value="{1}")"""\ .format(frappe.db.escape(key), frappe.db.escape(cstr(value))) for key, value in args.items()] @@ -79,8 +79,8 @@ def find_variant(item, args): where variant_of=%s and exists ( select name from `tabItem Variant Attribute` iv_attribute where iv_attribute.parent=item.name - and ({conditions}) - )""".format(conditions=conditions), item) + and ({conditions}) and parent != %s + )""".format(conditions=conditions), (template, variant_item_code)) for variant in possible_variants: variant = frappe.get_doc("Item", variant) diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js index 55295f4c02..d6e47485b5 100644 --- a/erpnext/stock/doctype/item/item.js +++ b/erpnext/stock/doctype/item/item.js @@ -320,6 +320,10 @@ $.extend(erpnext.item, { frm.toggle_display("attributes", frm.doc.has_variants || frm.doc.variant_of); frm.fields_dict.attributes.grid.toggle_reqd("attribute_value", frm.doc.variant_of ? 1 : 0); frm.fields_dict.attributes.grid.set_column_disp("attribute_value", frm.doc.variant_of ? 1 : 0); + + frm.toggle_enable("attributes", !frm.doc.variant_of); + frm.fields_dict.attributes.grid.toggle_enable("attribute", !frm.doc.variant_of); + frm.fields_dict.attributes.grid.toggle_enable("attribute_value", !frm.doc.variant_of); } }); diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index dfe17e89fc..1004f91edd 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -563,11 +563,10 @@ class Item(WebsiteGenerator): frappe.throw(_("Please specify Attribute Value for attribute {0}").format(d.attribute)) args[d.attribute] = d.attribute_value - if self.variant_of: - # test this during insert because naming is based on item_code and we cannot use condition like self.name != variant - variant = get_variant(self.variant_of, args) - if variant and self.get("__islocal"): - frappe.throw(_("Item variant {0} exists with same attributes").format(variant), ItemVariantExistsError) + variant = get_variant(self.name, self.variant_of, args) + if variant: + frappe.throw(_("Item variant {0} exists with same attributes") + .format(variant), ItemVariantExistsError) def validate_end_of_life(item_code, end_of_life=None, disabled=None, verbose=1): if (not end_of_life) or (disabled is None): diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index bd6fe285a1..f8b63936bd 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -107,6 +107,7 @@ class TestItem(unittest.TestCase): # doing it again should raise error variant = create_variant("_Test Variant Item", {"Test Size": "Large"}) + variant.item_code = "_Test Variant Item-L-duplicate" self.assertRaises(ItemVariantExistsError, variant.save) def test_make_item_variant_with_numeric_values(self):