From 5d1b7ec61d984ae5e03e3d8330fbcc69c37f2b0a Mon Sep 17 00:00:00 2001 From: marination Date: Mon, 21 Feb 2022 16:14:40 +0530 Subject: [PATCH 1/3] fix: Block merging items if both have product bundles (cherry picked from commit 28cc2dbb72fc3d716ffcb19b039dccd67c13eb33) --- erpnext/stock/doctype/item/item.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 557e07bf0a2..cf261e5ba7b 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -399,6 +399,7 @@ class Item(Document): if merge: self.validate_properties_before_merge(new_name) + self.validate_duplicate_product_bundles_before_merge(old_name, new_name) self.validate_duplicate_website_item_before_merge(old_name, new_name) def after_rename(self, old_name, new_name, merge): @@ -463,6 +464,18 @@ class Item(Document): msg += ": \n" + ", ".join([self.meta.get_label(fld) for fld in field_list]) frappe.throw(msg, title=_("Cannot Merge"), exc=DataValidationError) + def validate_duplicate_product_bundles_before_merge(self, old_name, new_name): + "Block merge if both old and new items have product bundles." + bundle = frappe.get_value("Product Bundle",filters={"new_item_code": old_name}) + if bundle: + bundle_link = get_link_to_form("Product Bundle", bundle) + old_name, new_name = frappe.bold(old_name), frappe.bold(new_name) + + msg = _("Please delete Product Bundle {0}, before merging {1} into {2}").format( + bundle_link, old_name, new_name + ) + frappe.throw(msg, title=_("Cannot Merge"), exc=DataValidationError) + def validate_duplicate_website_item_before_merge(self, old_name, new_name): """ Block merge if both old and new items have website items against them. @@ -480,8 +493,9 @@ class Item(Document): old_web_item = [d.get("name") for d in web_items if d.get("item_code") == old_name][0] web_item_link = get_link_to_form("Website Item", old_web_item) + old_name, new_name = frappe.bold(old_name), frappe.bold(new_name) - msg = f"Please delete linked Website Item {frappe.bold(web_item_link)} before merging {old_name} and {new_name}" + msg = f"Please delete linked Website Item {frappe.bold(web_item_link)} before merging {old_name} into {new_name}" frappe.throw(_(msg), title=_("Cannot Merge"), exc=DataValidationError) def set_last_purchase_rate(self, new_name): From e0ed91433ba74af7fd9525e4d67f190a7d20890c Mon Sep 17 00:00:00 2001 From: marination Date: Mon, 21 Feb 2022 16:48:04 +0530 Subject: [PATCH 2/3] test: Item Merging with Product Bundles (cherry picked from commit 530f9f70291758d51babd7ec4f52eefe1a899ef1) --- erpnext/stock/doctype/item/test_item.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index 150cead465b..e149086ae77 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -14,6 +14,7 @@ from erpnext.controllers.item_variant import ( get_variant, ) from erpnext.stock.doctype.item.item import ( + DataValidationError, InvalidBarcode, StockExistsForTemplate, get_item_attribute, @@ -387,6 +388,25 @@ class TestItem(ERPNextTestCase): self.assertTrue(frappe.db.get_value("Bin", {"item_code": "Test Item for Merging 2", "warehouse": "_Test Warehouse 1 - _TC"})) + def test_item_merging_with_product_bundle(self): + from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle + + create_item("Test Item Bundle Item 1", is_stock_item=False) + create_item("Test Item Bundle Item 2", is_stock_item=False) + create_item("Test Item inside Bundle") + bundle_items = ["Test Item inside Bundle"] + + bundle1 = make_product_bundle("Test Item Bundle Item 1", bundle_items, qty=2) + make_product_bundle("Test Item Bundle Item 2", bundle_items, qty=2) + + with self.assertRaises(DataValidationError): + frappe.rename_doc("Item", "Test Item Bundle Item 1", "Test Item Bundle Item 2", merge=True) + + bundle1.delete() + frappe.rename_doc("Item", "Test Item Bundle Item 1", "Test Item Bundle Item 2", merge=True) + + self.assertFalse(frappe.db.exists("Item", "Test Item Bundle Item 1")) + def test_uom_conversion_factor(self): if frappe.db.exists('Item', 'Test Item UOM'): frappe.delete_doc('Item', 'Test Item UOM') From 34e0b85d6a37d8b60aaac12d9a6d326b884d1bfb Mon Sep 17 00:00:00 2001 From: marination Date: Wed, 23 Feb 2022 16:26:20 +0530 Subject: [PATCH 3/3] fix: Check if both old and new items have bundles before merging - If only one has bundle against it, they can be merged (cherry picked from commit a33f04ea41087305c95111aa86bf96d3df2e2b36) --- erpnext/stock/doctype/item/item.py | 8 +++++--- erpnext/stock/doctype/item/test_item.py | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index cf261e5ba7b..7bc875ac12f 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -466,9 +466,11 @@ class Item(Document): def validate_duplicate_product_bundles_before_merge(self, old_name, new_name): "Block merge if both old and new items have product bundles." - bundle = frappe.get_value("Product Bundle",filters={"new_item_code": old_name}) - if bundle: - bundle_link = get_link_to_form("Product Bundle", bundle) + old_bundle = frappe.get_value("Product Bundle",filters={"new_item_code": old_name}) + new_bundle = frappe.get_value("Product Bundle",filters={"new_item_code": new_name}) + + if old_bundle and new_bundle: + bundle_link = get_link_to_form("Product Bundle", old_bundle) old_name, new_name = frappe.bold(old_name), frappe.bold(new_name) msg = _("Please delete Product Bundle {0}, before merging {1} into {2}").format( diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index e149086ae77..c912101a4ac 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -396,6 +396,7 @@ class TestItem(ERPNextTestCase): create_item("Test Item inside Bundle") bundle_items = ["Test Item inside Bundle"] + # make bundles for both items bundle1 = make_product_bundle("Test Item Bundle Item 1", bundle_items, qty=2) make_product_bundle("Test Item Bundle Item 2", bundle_items, qty=2)