fix: dialog issue
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 6d05ec4..b10898a 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -432,7 +432,7 @@
 			update_stock = cint(me.frm.doc.update_stock);
 			show_batch_dialog = update_stock;
 
-		} else if((this.frm.doc.doctype === 'Purchase Receipt' && me.frm.doc.is_return) ||
+		} else if((this.frm.doc.doctype === 'Purchase Receipt') ||
 			this.frm.doc.doctype === 'Delivery Note') {
 			show_batch_dialog = 1;
 		}
@@ -538,7 +538,7 @@
 											});
 								},
 								() => {
-									if(show_batch_dialog && !frappe.flags.hide_serial_batch_dialog) {
+									if(show_batch_dialog && !frappe.flags.hide_serial_batch_dialog && !frappe.flags.dialog_set) {
 										var d = locals[cdt][cdn];
 										$.each(r.message, function(k, v) {
 											if(!d[k]) d[k] = v;
@@ -548,12 +548,15 @@
 											d.batch_no = undefined;
 										}
 
+										frappe.flags.dialog_set = true;
 										erpnext.show_serial_batch_selector(me.frm, d, (item) => {
 											me.frm.script_manager.trigger('qty', item.doctype, item.name);
 											if (!me.frm.doc.set_warehouse)
 												me.frm.script_manager.trigger('warehouse', item.doctype, item.name);
 											me.apply_price_list(item, true);
 										}, undefined, !frappe.flags.hide_serial_batch_dialog);
+									} else {
+										frappe.flags.dialog_set = false;
 									}
 								},
 								() => me.conversion_factor(doc, cdt, cdn, true),
@@ -2287,6 +2290,7 @@
 };
 
 erpnext.show_serial_batch_selector = function (frm, item_row, callback, on_close, show_dialog) {
+	debugger
 	let warehouse, receiving_stock, existing_stock;
 	if (frm.doc.is_return) {
 		if (["Purchase Receipt", "Purchase Invoice"].includes(frm.doc.doctype)) {
diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js
index 8c7b2f2..0e0ef33 100644
--- a/erpnext/public/js/utils/serial_no_batch_selector.js
+++ b/erpnext/public/js/utils/serial_no_batch_selector.js
@@ -29,10 +29,6 @@
 			primary_action: () => this.update_ledgers()
 		});
 
-		if (this.item?.outward) {
-			this.prepare_for_auto_fetch();
-		}
-
 		this.dialog.show();
 	}
 
@@ -76,6 +72,13 @@
 				fieldname: 'scan_batch_no',
 				label: __('Scan Batch No'),
 				options: 'Batch',
+				get_query: () => {
+					return {
+						filters: {
+							'item': this.item.item_code
+						}
+					};
+				},
 				onchange: () => this.update_serial_batch_no()
 			});
 		}
@@ -97,7 +100,7 @@
 		}
 
 		if (this.item?.outward) {
-			fields = [...fields, ...this.get_filter_fields()];
+			fields = [...this.get_filter_fields(), ...fields];
 		}
 
 		fields.push({
@@ -126,6 +129,7 @@
 				fieldname: 'qty',
 				default: this.item.qty || 0,
 				label: __('Qty to Fetch'),
+				onchange: () => this.get_auto_data()
 			},
 			{
 				fieldtype: 'Column Break',
@@ -135,16 +139,11 @@
 				options: ['FIFO', 'LIFO', 'Expiry'],
 				default: 'FIFO',
 				fieldname: 'based_on',
-				label: __('Fetch Based On')
+				label: __('Fetch Based On'),
+				onchange: () => this.get_auto_data()
 			},
 			{
-				fieldtype: 'Column Break',
-			},
-			{
-				fieldtype: 'Button',
-				fieldname: 'get_auto_data',
-				label: __('Fetch {0}',
-					[this.item?.has_serial_no ? 'Serial Nos' : 'Batch Nos']),
+				fieldtype: 'Section Break',
 			},
 		]
 
@@ -177,6 +176,13 @@
 					fieldname: 'batch_no',
 					label: __('Batch No'),
 					in_list_view: 1,
+					get_query: () => {
+						return {
+							filters: {
+								'item': this.item.item_code
+							}
+						};
+					},
 				}
 			]
 
@@ -202,12 +208,6 @@
 		return fields;
 	}
 
-	prepare_for_auto_fetch() {
-		this.dialog.fields_dict.get_auto_data.$input.on('click', () => {
-			this.get_auto_data();
-		});
-	}
-
 	get_auto_data() {
 		const { qty, based_on } = this.dialog.get_values();
 
@@ -215,6 +215,10 @@
 			frappe.throw(__('Please enter Qty to Fetch'));
 		}
 
+		if (!based_on) {
+			based_on = 'FIFO';
+		}
+
 		frappe.call({
 			method: 'erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.get_auto_data',
 			args: {
diff --git a/erpnext/stock/deprecated_serial_batch.py b/erpnext/stock/deprecated_serial_batch.py
index 1e1d8fd..9e15015 100644
--- a/erpnext/stock/deprecated_serial_batch.py
+++ b/erpnext/stock/deprecated_serial_batch.py
@@ -17,13 +17,9 @@
 
 		stock_value_change = 0
 		if actual_qty < 0:
-			# In case of delivery/stock issue, get average purchase rate
-			# of serial nos of current entry
 			if not self.sle.is_cancelled:
 				outgoing_value = self.get_incoming_value_for_serial_nos(serial_nos)
 				stock_value_change = -1 * outgoing_value
-			else:
-				stock_value_change = actual_qty * self.sle.outgoing_rate
 
 		self.stock_value_change += stock_value_change
 
diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.json b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.json
index b613f20..18d8a72 100644
--- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.json
+++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.json
@@ -139,7 +139,7 @@
   {
    "collapsible": 1,
    "fieldname": "quantity_and_rate_section",
-   "fieldtype": "Section Break",
+   "fieldtype": "Tab Break",
    "label": "Quantity and Rate"
   },
   {
@@ -243,7 +243,7 @@
  "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2023-03-24 13:39:17.843812",
+ "modified": "2023-04-03 16:22:30.767805",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "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 9f26b40..4fe59bd 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
@@ -154,7 +154,10 @@
 				if sn_obj.batch_avg_rate.get(d.batch_no):
 					d.incoming_rate = abs(sn_obj.batch_avg_rate.get(d.batch_no))
 
-				available_qty = flt(sn_obj.available_qty.get(d.batch_no)) + flt(d.qty)
+				available_qty = flt(sn_obj.available_qty.get(d.batch_no))
+				if self.docstatus == 1:
+					available_qty += flt(d.qty)
+
 				self.validate_negative_batch(d.batch_no, available_qty)
 
 			d.stock_value_difference = flt(d.qty) * flt(d.incoming_rate)
@@ -553,6 +556,38 @@
 	def on_submit(self):
 		self.validate_serial_nos_inventory()
 
+	def validate_serial_and_batch_inventory(self):
+		self.check_future_entries_exists()
+		self.validate_batch_inventory()
+
+	def validate_batch_inventory(self):
+		if not self.has_batch_no:
+			return
+
+		batches = [d.batch_no for d in self.entries if d.batch_no]
+		if not batches:
+			return
+
+		available_batches = get_auto_batch_nos(
+			frappe._dict(
+				{
+					"item_code": self.item_code,
+					"warehouse": self.warehouse,
+					"batch_no": batches,
+				}
+			)
+		)
+
+		if not available_batches:
+			return
+
+		available_batches = get_availabel_batches_qty(available_batches)
+		for batch_no in batches:
+			if batch_no not in available_batches or available_batches[batch_no] < 0:
+				self.throw_error_message(
+					f"Batch {bold(batch_no)} is not available in the selected warehouse {self.warehouse}"
+				)
+
 	def on_cancel(self):
 		self.validate_voucher_no_docstatus()
 
@@ -599,6 +634,7 @@
 			"`tabSerial and Batch Entry`.`serial_no`",
 		],
 		filters=filters,
+		order_by="`tabSerial and Batch Entry`.`idx`",
 	)
 
 
@@ -762,6 +798,14 @@
 		return get_auto_batch_nos(kwargs)
 
 
+def get_availabel_batches_qty(available_batches):
+	available_batches_qty = defaultdict(float)
+	for batch in available_batches:
+		available_batches_qty[batch.batch_no] += batch.qty
+
+	return available_batches_qty
+
+
 def get_available_serial_nos(kwargs):
 	fields = ["name as serial_no", "warehouse"]
 	if kwargs.has_batch_no:
@@ -778,6 +822,7 @@
 	if kwargs.warehouse:
 		filters["warehouse"] = kwargs.warehouse
 
+	# Since SLEs are not present against POS invoices, need to ignore serial nos present in the POS invoice
 	ignore_serial_nos = get_reserved_serial_nos_for_pos(kwargs)
 
 	# To ignore serial nos in the same record for the draft state
@@ -792,6 +837,13 @@
 	elif ignore_serial_nos:
 		filters["name"] = ("not in", ignore_serial_nos)
 
+	if kwargs.get("batches"):
+		batches = get_non_expired_batches(kwargs.get("batches"))
+		if not batches:
+			return []
+
+		filters["batch_no"] = ("in", batches)
+
 	return frappe.get_all(
 		"Serial No",
 		fields=fields,
@@ -801,6 +853,23 @@
 	)
 
 
+def get_non_expired_batches(batches):
+	filters = {}
+	if isinstance(batches, list):
+		filters["name"] = ("in", batches)
+	else:
+		filters["name"] = batches
+
+	data = frappe.get_all(
+		"Batch",
+		filters=filters,
+		or_filters=[["expiry_date", ">=", today()], ["expiry_date", "is", "not set"]],
+		fields=["name"],
+	)
+
+	return [d.name for d in data] if data else []
+
+
 def get_serial_nos_based_on_posting_date(kwargs, ignore_serial_nos):
 	from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
 
diff --git a/erpnext/stock/doctype/serial_no/test_serial_no.py b/erpnext/stock/doctype/serial_no/test_serial_no.py
index 4a0abb6..5a5c403 100644
--- a/erpnext/stock/doctype/serial_no/test_serial_no.py
+++ b/erpnext/stock/doctype/serial_no/test_serial_no.py
@@ -6,7 +6,9 @@
 
 
 import frappe
+from frappe import _, _dict
 from frappe.tests.utils import FrappeTestCase
+from frappe.utils import today
 
 from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
 from erpnext.stock.doctype.item.test_item import make_item
@@ -49,26 +51,22 @@
 
 	def test_inter_company_transfer(self):
 		se = make_serialized_item(target_warehouse="_Test Warehouse - _TC")
-		serial_nos = get_serial_nos(se.get("items")[0].serial_no)
+		serial_nos = get_serial_nos_from_bundle(se.get("items")[0].serial_and_batch_bundle)
 
 		dn = create_delivery_note(
-			item_code="_Test Serialized Item With Series", qty=1, serial_no=serial_nos[0]
+			item_code="_Test Serialized Item With Series", qty=1, serial_no=[serial_nos[0]]
 		)
 
 		serial_no = frappe.get_doc("Serial No", serial_nos[0])
 
 		# check Serial No details after delivery
-		self.assertEqual(serial_no.status, "Delivered")
 		self.assertEqual(serial_no.warehouse, None)
-		self.assertEqual(serial_no.company, "_Test Company")
-		self.assertEqual(serial_no.delivery_document_type, "Delivery Note")
-		self.assertEqual(serial_no.delivery_document_no, dn.name)
 
 		wh = create_warehouse("_Test Warehouse", company="_Test Company 1")
 		pr = make_purchase_receipt(
 			item_code="_Test Serialized Item With Series",
 			qty=1,
-			serial_no=serial_nos[0],
+			serial_no=[serial_nos[0]],
 			company="_Test Company 1",
 			warehouse=wh,
 		)
@@ -76,11 +74,7 @@
 		serial_no.reload()
 
 		# check Serial No details after purchase in second company
-		self.assertEqual(serial_no.status, "Active")
 		self.assertEqual(serial_no.warehouse, wh)
-		self.assertEqual(serial_no.company, "_Test Company 1")
-		self.assertEqual(serial_no.purchase_document_type, "Purchase Receipt")
-		self.assertEqual(serial_no.purchase_document_no, pr.name)
 
 	def test_inter_company_transfer_intermediate_cancellation(self):
 		"""
@@ -89,25 +83,19 @@
 		Try to cancel intermediate receipts/deliveries to test if it is blocked.
 		"""
 		se = make_serialized_item(target_warehouse="_Test Warehouse - _TC")
-		serial_nos = get_serial_nos(se.get("items")[0].serial_no)
+		serial_nos = get_serial_nos_from_bundle(se.get("items")[0].serial_and_batch_bundle)
 
 		sn_doc = frappe.get_doc("Serial No", serial_nos[0])
 
 		# check Serial No details after purchase in first company
-		self.assertEqual(sn_doc.status, "Active")
-		self.assertEqual(sn_doc.company, "_Test Company")
 		self.assertEqual(sn_doc.warehouse, "_Test Warehouse - _TC")
-		self.assertEqual(sn_doc.purchase_document_no, se.name)
 
 		dn = create_delivery_note(
-			item_code="_Test Serialized Item With Series", qty=1, serial_no=serial_nos[0]
+			item_code="_Test Serialized Item With Series", qty=1, serial_no=[serial_nos[0]]
 		)
 		sn_doc.reload()
 		# check Serial No details after delivery from **first** company
-		self.assertEqual(sn_doc.status, "Delivered")
-		self.assertEqual(sn_doc.company, "_Test Company")
 		self.assertEqual(sn_doc.warehouse, None)
-		self.assertEqual(sn_doc.delivery_document_no, dn.name)
 
 		# try cancelling the first Serial No Receipt, even though it is delivered
 		# block cancellation is Serial No is out of the warehouse
@@ -118,7 +106,7 @@
 		pr = make_purchase_receipt(
 			item_code="_Test Serialized Item With Series",
 			qty=1,
-			serial_no=serial_nos[0],
+			serial_no=[serial_nos[0]],
 			company="_Test Company 1",
 			warehouse=wh,
 		)
@@ -133,17 +121,14 @@
 		dn_2 = create_delivery_note(
 			item_code="_Test Serialized Item With Series",
 			qty=1,
-			serial_no=serial_nos[0],
+			serial_no=[serial_nos[0]],
 			company="_Test Company 1",
 			warehouse=wh,
 		)
 		sn_doc.reload()
 
 		# check Serial No details after delivery from **second** company
-		self.assertEqual(sn_doc.status, "Delivered")
-		self.assertEqual(sn_doc.company, "_Test Company 1")
 		self.assertEqual(sn_doc.warehouse, None)
-		self.assertEqual(sn_doc.delivery_document_no, dn_2.name)
 
 		# cannot cancel any intermediate document before last Delivery Note
 		self.assertRaises(frappe.ValidationError, se.cancel)
@@ -158,12 +143,12 @@
 		"""
 		# Receipt in **first** company
 		se = make_serialized_item(target_warehouse="_Test Warehouse - _TC")
-		serial_nos = get_serial_nos(se.get("items")[0].serial_no)
+		serial_nos = get_serial_nos_from_bundle(se.get("items")[0].serial_and_batch_bundle)
 		sn_doc = frappe.get_doc("Serial No", serial_nos[0])
 
 		# Delivery from first company
 		dn = create_delivery_note(
-			item_code="_Test Serialized Item With Series", qty=1, serial_no=serial_nos[0]
+			item_code="_Test Serialized Item With Series", qty=1, serial_no=[serial_nos[0]]
 		)
 
 		# Receipt in **second** company
@@ -171,7 +156,7 @@
 		pr = make_purchase_receipt(
 			item_code="_Test Serialized Item With Series",
 			qty=1,
-			serial_no=serial_nos[0],
+			serial_no=[serial_nos[0]],
 			company="_Test Company 1",
 			warehouse=wh,
 		)
@@ -180,55 +165,29 @@
 		dn_2 = create_delivery_note(
 			item_code="_Test Serialized Item With Series",
 			qty=1,
-			serial_no=serial_nos[0],
+			serial_no=[serial_nos[0]],
 			company="_Test Company 1",
 			warehouse=wh,
 		)
 		sn_doc.reload()
 
-		self.assertEqual(sn_doc.status, "Delivered")
-		self.assertEqual(sn_doc.company, "_Test Company 1")
-		self.assertEqual(sn_doc.delivery_document_no, dn_2.name)
+		self.assertEqual(sn_doc.warehouse, None)
 
 		dn_2.cancel()
 		sn_doc.reload()
 		# Fallback on Purchase Receipt if Delivery is cancelled
-		self.assertEqual(sn_doc.status, "Active")
-		self.assertEqual(sn_doc.company, "_Test Company 1")
 		self.assertEqual(sn_doc.warehouse, wh)
-		self.assertEqual(sn_doc.purchase_document_no, pr.name)
 
 		pr.cancel()
 		sn_doc.reload()
 		# Inactive in same company if Receipt cancelled
-		self.assertEqual(sn_doc.status, "Inactive")
-		self.assertEqual(sn_doc.company, "_Test Company 1")
 		self.assertEqual(sn_doc.warehouse, None)
 
 		dn.cancel()
 		sn_doc.reload()
 		# Fallback on Purchase Receipt in FIRST company if
 		# Delivery from FIRST company is cancelled
-		self.assertEqual(sn_doc.status, "Active")
-		self.assertEqual(sn_doc.company, "_Test Company")
 		self.assertEqual(sn_doc.warehouse, "_Test Warehouse - _TC")
-		self.assertEqual(sn_doc.purchase_document_no, se.name)
-
-	def test_serial_no_sanitation(self):
-		"Test if Serial No input is sanitised before entering the DB."
-		item_code = "_Test Serialized Item"
-		test_records = frappe.get_test_records("Stock Entry")
-
-		se = frappe.copy_doc(test_records[0])
-		se.get("items")[0].item_code = item_code
-		se.get("items")[0].qty = 4
-		se.get("items")[0].serial_no = " _TS1, _TS2 , _TS3  , _TS4 - 2021"
-		se.get("items")[0].transfer_qty = 4
-		se.set_stock_entry_type()
-		se.insert()
-		se.submit()
-
-		self.assertEqual(se.get("items")[0].serial_no, "_TS1\n_TS2\n_TS3\n_TS4 - 2021")
 
 	def test_correct_serial_no_incoming_rate(self):
 		"""Check correct consumption rate based on serial no record."""
@@ -236,19 +195,28 @@
 		warehouse = "_Test Warehouse - _TC"
 		serial_nos = ["LOWVALUATION", "HIGHVALUATION"]
 
+		for serial_no in serial_nos:
+			if not frappe.db.exists("Serial No", serial_no):
+				frappe.get_doc(
+					{"doctype": "Serial No", "item_code": item_code, "serial_no": serial_no}
+				).insert()
+
 		in1 = make_stock_entry(
-			item_code=item_code, to_warehouse=warehouse, qty=1, rate=42, serial_no=serial_nos[0]
+			item_code=item_code, to_warehouse=warehouse, qty=1, rate=42, serial_no=[serial_nos[0]]
 		)
 		in2 = make_stock_entry(
-			item_code=item_code, to_warehouse=warehouse, qty=1, rate=113, serial_no=serial_nos[1]
+			item_code=item_code, to_warehouse=warehouse, qty=1, rate=113, serial_no=[serial_nos[1]]
 		)
 
 		out = create_delivery_note(
-			item_code=item_code, qty=1, serial_no=serial_nos[0], do_not_submit=True
+			item_code=item_code, qty=1, serial_no=[serial_nos[0]], do_not_submit=True
 		)
 
-		# change serial no
-		out.items[0].serial_no = serial_nos[1]
+		bundle = out.items[0].serial_and_batch_bundle
+		doc = frappe.get_doc("Serial and Batch Bundle", bundle)
+		doc.entries[0].serial_no = serial_nos[1]
+		doc.save()
+
 		out.save()
 		out.submit()
 
@@ -285,40 +253,90 @@
 		}
 
 		# Test FIFO
-		first_fetch = auto_fetch_serial_number(5, item_code, warehouse)
+		first_fetch = get_auto_serial_nos(
+			_dict(
+				{
+					"qty": 5,
+					"item_code": item_code,
+					"warehouse": warehouse,
+				}
+			)
+		)
+
 		self.assertEqual(first_fetch, batch_wise_serials[batch1])
 
 		# partial FIFO
-		partial_fetch = auto_fetch_serial_number(2, item_code, warehouse)
+		partial_fetch = get_auto_serial_nos(
+			_dict(
+				{
+					"qty": 2,
+					"item_code": item_code,
+					"warehouse": warehouse,
+				}
+			)
+		)
+
 		self.assertTrue(
 			set(partial_fetch).issubset(set(first_fetch)),
 			msg=f"{partial_fetch} should be subset of {first_fetch}",
 		)
 
 		# exclusion
-		remaining = auto_fetch_serial_number(
-			3, item_code, warehouse, exclude_sr_nos=json.dumps(partial_fetch)
+		remaining = get_auto_serial_nos(
+			_dict(
+				{
+					"qty": 3,
+					"item_code": item_code,
+					"warehouse": warehouse,
+					"ignore_serial_nos": partial_fetch,
+				}
+			)
 		)
+
 		self.assertEqual(sorted(remaining + partial_fetch), first_fetch)
 
 		# batchwise
 		for batch, expected_serials in batch_wise_serials.items():
-			fetched_sr = auto_fetch_serial_number(5, item_code, warehouse, batch_nos=batch)
+			fetched_sr = get_auto_serial_nos(
+				_dict({"qty": 5, "item_code": item_code, "warehouse": warehouse, "batches": [batch]})
+			)
+
 			self.assertEqual(fetched_sr, sorted(expected_serials))
 
 		# non existing warehouse
-		self.assertEqual(auto_fetch_serial_number(10, item_code, warehouse="Nonexisting"), [])
+		self.assertFalse(
+			get_auto_serial_nos(
+				_dict({"qty": 10, "item_code": item_code, "warehouse": "Non Existing Warehouse"})
+			)
+		)
 
 		# multi batch
 		all_serials = [sr for sr_list in batch_wise_serials.values() for sr in sr_list]
-		fetched_serials = auto_fetch_serial_number(
-			10, item_code, warehouse, batch_nos=list(batch_wise_serials.keys())
+		fetched_serials = get_auto_serial_nos(
+			_dict(
+				{
+					"qty": 10,
+					"item_code": item_code,
+					"warehouse": warehouse,
+					"batches": list(batch_wise_serials.keys()),
+				}
+			)
 		)
 		self.assertEqual(sorted(all_serials), fetched_serials)
 
 		# expiry date
 		frappe.db.set_value("Batch", batch1, "expiry_date", "1980-01-01")
-		non_expired_serials = auto_fetch_serial_number(
-			5, item_code, warehouse, posting_date="2021-01-01", batch_nos=batch1
+		non_expired_serials = get_auto_serial_nos(
+			_dict({"qty": 5, "item_code": item_code, "warehouse": warehouse, "batches": [batch1]})
 		)
+
 		self.assertEqual(non_expired_serials, [])
+
+
+def get_auto_serial_nos(kwargs):
+	from erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle import (
+		get_available_serial_nos,
+	)
+
+	serial_nos = get_available_serial_nos(kwargs)
+	return sorted([d.serial_no for d in serial_nos])
diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json
index 4ad6b26..569f58a 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json
+++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json
@@ -15,9 +15,10 @@
   "voucher_type",
   "voucher_no",
   "voucher_detail_no",
+  "serial_and_batch_bundle",
   "dependant_sle_voucher_detail_no",
-  "recalculate_rate",
   "section_break_11",
+  "recalculate_rate",
   "actual_qty",
   "qty_after_transaction",
   "incoming_rate",
@@ -31,15 +32,14 @@
   "company",
   "stock_uom",
   "project",
-  "serial_and_batch_bundle",
-  "has_batch_no",
-  "batch_no",
   "column_break_26",
   "fiscal_year",
+  "has_batch_no",
   "has_serial_no",
-  "serial_no",
   "is_cancelled",
-  "to_rename"
+  "to_rename",
+  "serial_no",
+  "batch_no"
  ],
  "fields": [
   {
@@ -341,7 +341,7 @@
  "in_create": 1,
  "index_web_pages_for_search": 1,
  "links": [],
- "modified": "2022-12-28 14:50:56.359348",
+ "modified": "2023-04-03 16:33:16.270722",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Ledger Entry",
diff --git a/erpnext/stock/serial_batch_bundle.py b/erpnext/stock/serial_batch_bundle.py
index 33dd960..9cae66d 100644
--- a/erpnext/stock/serial_batch_bundle.py
+++ b/erpnext/stock/serial_batch_bundle.py
@@ -177,6 +177,11 @@
 			{"is_cancelled": 1, "voucher_no": ""},
 		)
 
+		if self.sle.serial_and_batch_bundle:
+			frappe.get_cached_doc(
+				"Serial and Batch Bundle", self.sle.serial_and_batch_bundle
+			).validate_serial_and_batch_inventory()
+
 	def post_process(self):
 		if not self.sle.serial_and_batch_bundle:
 			return