chore: used frappe.db.bulk_insert to create serial nos and serial bunndle
diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js
index 1c98037..90967d9 100644
--- a/erpnext/public/js/utils/serial_no_batch_selector.js
+++ b/erpnext/public/js/utils/serial_no_batch_selector.js
@@ -771,7 +771,7 @@
 			}
 
 			frappe.call({
-				method: 'erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.add_serial_batch_no_ledgers',
+				method: 'erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.add_serial_batch_ledgers',
 				args: {
 					ledgers: ledgers,
 					child_row: this.item
@@ -786,7 +786,7 @@
 	render_data() {
 		if (!this.frm.is_new() && this.item.serial_and_batch_bundle) {
 			frappe.call({
-				method: 'erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.get_serial_batch_no_ledgers',
+				method: 'erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.get_serial_batch_ledgers',
 				args: {
 					item_code: this.item.item_code,
 					name: this.item.serial_and_batch_bundle,
diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
index 97e7d72..900fb75 100644
--- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
+++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
@@ -991,6 +991,7 @@
    "fieldname": "serial_and_batch_bundle",
    "fieldtype": "Link",
    "label": "Serial and Batch Bundle",
+   "no_copy": 1,
    "options": "Serial and Batch Bundle"
   },
   {
diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py
index ae25aad..554c032 100644
--- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py
+++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py
@@ -48,7 +48,7 @@
 
 
 @frappe.whitelist()
-def get_serial_batch_no_ledgers(item_code, voucher_no, name=None):
+def get_serial_batch_ledgers(item_code, voucher_no, name=None):
 	return frappe.get_all(
 		"Serial and Batch Bundle",
 		fields=[
@@ -68,7 +68,7 @@
 
 
 @frappe.whitelist()
-def add_serial_batch_no_ledgers(ledgers, child_row) -> object:
+def add_serial_batch_ledgers(ledgers, child_row) -> object:
 	if isinstance(child_row, str):
 		child_row = frappe._dict(frappe.parse_json(child_row))
 
diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py
index 9338dc5..98beda0 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.py
+++ b/erpnext/stock/doctype/serial_no/serial_no.py
@@ -16,6 +16,7 @@
 	flt,
 	get_link_to_form,
 	getdate,
+	now,
 	nowdate,
 	safe_json_loads,
 )
@@ -189,7 +190,6 @@
 	def get_last_sle(self, serial_no=None):
 		entries = {}
 		sle_dict = self.get_stock_ledger_entries(serial_no)
-		print("sle_dict", sle_dict)
 		if sle_dict:
 			if sle_dict.get("incoming", []):
 				entries["purchase_sle"] = sle_dict["incoming"][0]
@@ -538,13 +538,151 @@
 		and item_det.has_serial_no == 1
 		and item_det.serial_no_series
 	):
-		serial_nos = get_auto_serial_nos(item_det.serial_no_series, sle.actual_qty)
-		sle.db_set("serial_no", serial_nos)
-		validate_serial_no(sle, item_det)
-	if sle.serial_and_batch_bundle:
+		bundle = make_serial_bundle(sle, item_det)
+		if bundle:
+			sle.db_set("serial_and_batch_bundle", bundle.name)
+			child_doctype = sle.voucher_type + " Item"
+			if sle.voucher_type == "Stock Entry":
+				child_doctype = "Stock Entry Detail"
+			elif sle.voucher_type == "Stock Reconciliation":
+				child_doctype = "Stock Reconciliation Item"
+
+			frappe.db.set_value(
+				child_doctype, sle.voucher_detail_no, "serial_and_batch_bundle", bundle.name
+			)
+
+	elif sle.serial_and_batch_bundle:
 		auto_make_serial_nos(sle)
 
 
+def make_serial_bundle(sle, item_details):
+	sr_nos = auto_create_serial_nos(sle, item_details)
+
+	if sr_nos:
+		sn_doc = frappe.new_doc("Serial and Batch Bundle")
+		sn_doc.item_code = item_details.name
+		sn_doc.item_name = item_details.item_name
+		sn_doc.item_group = item_details.item_group
+		sn_doc.has_serial_no = item_details.has_serial_no
+		sn_doc.has_batch_no = item_details.has_batch_no
+		sn_doc.voucher_type = sle.voucher_type
+		sn_doc.voucher_no = sle.voucher_no
+		sn_doc.flags.ignore_mandatory = True
+		sn_doc.qty = sle.actual_qty
+		sn_doc.insert()
+
+		batch_no = ""
+		if item_details.has_batch_no:
+			batch_no = create_batch_for_serial_no(sle)
+
+		ledgers = []
+		fields = [
+			"name",
+			"serial_no",
+			"batch_no",
+			"warehouse",
+			"qty",
+			"parent",
+			"parenttype",
+			"parentfield",
+		]
+
+		for serial_no in sr_nos:
+			ledgers.append(
+				(
+					frappe.generate_hash("", 10),
+					serial_no,
+					batch_no,
+					sle.warehouse,
+					1,
+					sn_doc.name,
+					sn_doc.doctype,
+					"ledgers",
+				)
+			)
+
+		frappe.db.bulk_insert(
+			"Serial and Batch Ledger",
+			fields=fields,
+			values=set(ledgers),
+			ignore_duplicates=True,
+		)
+
+		sn_doc.load_from_db()
+		return sn_doc.submit()
+
+
+def create_batch_for_serial_no(sle):
+	from erpnext.stock.doctype.batch.batch import make_batch
+
+	return make_batch(
+		frappe._dict(
+			{
+				"item": sle.item_code,
+				"reference_doctype": sle.voucher_type,
+				"reference_name": sle.voucher_no,
+			}
+		)
+	)
+
+
+def auto_create_serial_nos(sle, item_details) -> List[str]:
+	sr_nos = []
+	serial_nos_details = []
+	for i in range(cint(sle.actual_qty)):
+		serial_no = make_autoname(item_details.serial_no_series, "Serial No")
+		sr_nos.append(serial_no)
+		serial_nos_details.append(
+			(
+				serial_no,
+				serial_no,
+				now(),
+				now(),
+				frappe.session.user,
+				frappe.session.user,
+				sle.voucher_type,
+				sle.voucher_no,
+				sle.warehouse,
+				sle.company,
+				sle.posting_date,
+				sle.posting_time,
+				sle.incoming_rate,
+				sle.item_code,
+				item_details.item_name,
+				item_details.description,
+			)
+		)
+
+	if serial_nos_details:
+		fields = [
+			"name",
+			"serial_no",
+			"creation",
+			"modified",
+			"owner",
+			"modified_by",
+			"purchase_document_type",
+			"purchase_document_no",
+			"warehouse",
+			"company",
+			"purchase_date",
+			"purchase_time",
+			"purchase_rate",
+			"item_code",
+			"item_name",
+			"description",
+		]
+
+		frappe.db.bulk_insert(
+			"Serial No",
+			fields=fields,
+			values=set(serial_nos_details),
+			ignore_duplicates=True,
+		)
+
+	return sr_nos
+
+
 def get_auto_serial_nos(serial_no_series, qty):
 	serial_nos = []
 	for i in range(cint(qty)):
@@ -609,7 +747,8 @@
 def get_item_details(item_code):
 	return frappe.db.sql(
 		"""select name, has_batch_no, docstatus,
-		is_stock_item, has_serial_no, serial_no_series
+		is_stock_item, has_serial_no, serial_no_series, description, item_name,
+		item_group, stock_uom
 		from tabItem where name=%s""",
 		item_code,
 		as_dict=True,
diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
index 916b14a..1bcea69 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
+++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
@@ -40,7 +40,6 @@
 		from erpnext.stock.utils import validate_disabled_warehouse, validate_warehouse_company
 
 		self.validate_mandatory()
-		self.validate_serial_batch_no_bundle()
 		self.validate_batch()
 		validate_disabled_warehouse(self.warehouse)
 		validate_warehouse_company(self.warehouse, self.company)
@@ -58,6 +57,8 @@
 
 			process_serial_no(self)
 
+		self.validate_serial_batch_no_bundle()
+
 	def calculate_batch_qty(self):
 		if self.batch_no:
 			batch_qty = (