From 28cc2dbb72fc3d716ffcb19b039dccd67c13eb33 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 --- 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 b9e8b3f2f1..d984d6eb99 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -398,6 +398,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): @@ -462,6 +463,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. @@ -479,8 +492,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 530f9f70291758d51babd7ec4f52eefe1a899ef1 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 --- 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 fd4df42187..6f5f1ff786 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -15,6 +15,7 @@ from erpnext.controllers.item_variant import ( get_variant, ) from erpnext.stock.doctype.item.item import ( + DataValidationError, InvalidBarcode, StockExistsForTemplate, get_item_attribute, @@ -388,6 +389,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 a33f04ea41087305c95111aa86bf96d3df2e2b36 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 --- 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 d984d6eb99..494fb3b8bb 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -465,9 +465,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 6f5f1ff786..9491e17259 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -397,6 +397,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)