diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 95e0967ca71..a82e1c2d527 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -860,7 +860,17 @@ class Item(Document): frappe.throw(_("Item {0} is not a template item.").format(frappe.bold(self.variant_of))) if based_on == "Item Attribute": + previous_doc = self.get_doc_before_save() + saved_attributes = ( + {(row.attribute, row.attribute_value) for row in previous_doc.attributes} + if previous_doc + else set() + ) + for d in self.attributes: + if (d.attribute, d.attribute_value) in saved_attributes: + continue + if not frappe.db.exists( "Item Variant Attribute", {"attribute": d.attribute, "parent": self.variant_of} ): diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index 4080d65aab4..11eccc429e8 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -423,6 +423,24 @@ class TestItem(ERPNextTestSuite): self.assertRaises(InvalidItemAttributeValueError, attribute.save) + def test_disabled_attribute_blocks_only_attribute_changes(self): + frappe.delete_doc_if_exists("Item", "_Test Variant Item-L", force=1) + + variant = create_variant("_Test Variant Item", {"Test Size": "Large"}) + variant.save() + + attribute = frappe.get_doc("Item Attribute", "Test Size") + attribute.disabled = 1 + attribute.save() + + variant.reload() + variant.description = "Edited after the attribute was disabled" + variant.save() + + variant.reload() + variant.attributes[0].attribute_value = "Small" + self.assertRaises(frappe.ValidationError, variant.save) + def test_rename_attribute_value_updates_variants(self): frappe.delete_doc_if_exists("Item", "_Test Variant Item-L", force=1)