Merge branch 'develop' into item-merge-bundles
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index b9e8b3f..d984d6e 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -398,6 +398,7 @@
 
 		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 @@
 			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 @@
 
 		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):
diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py
index fd4df42..6f5f1ff 100644
--- a/erpnext/stock/doctype/item/test_item.py
+++ b/erpnext/stock/doctype/item/test_item.py
@@ -15,6 +15,7 @@
 	get_variant,
 )
 from erpnext.stock.doctype.item.item import (
+	DataValidationError,
 	InvalidBarcode,
 	StockExistsForTemplate,
 	get_item_attribute,
@@ -388,6 +389,25 @@
 		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')