fix: use serial batch fields for subcontracting receipt (#40311)

diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index c46ef50..a477a0d 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -439,9 +439,21 @@
 
 	filtered_batches = get_filterd_batches(batches)
 
+	if filters.get("is_inward"):
+		filtered_batches.extend(get_empty_batches(filters))
+
 	return filtered_batches
 
 
+def get_empty_batches(filters):
+	return frappe.get_all(
+		"Batch",
+		fields=["name", "batch_qty"],
+		filters={"item": filters.get("item_code"), "batch_qty": 0.0},
+		as_list=1,
+	)
+
+
 def get_filterd_batches(data):
 	batches = OrderedDict()
 
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index a67fbdc..2f05ec3 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -190,43 +190,23 @@
 			if row.use_serial_batch_fields and (
 				not row.serial_and_batch_bundle and not row.get("rejected_serial_and_batch_bundle")
 			):
-				if self.doctype == "Stock Reconciliation":
-					qty = row.qty
-					type_of_transaction = "Inward"
-					warehouse = row.warehouse
-				elif table_name == "packed_items":
-					qty = row.qty
-					warehouse = row.warehouse
-					type_of_transaction = "Outward"
-					if self.is_return:
-						type_of_transaction = "Inward"
-				else:
-					qty = row.stock_qty if self.doctype != "Stock Entry" else row.transfer_qty
-					type_of_transaction = get_type_of_transaction(self, row)
-					warehouse = (
-						row.warehouse if self.doctype != "Stock Entry" else row.s_warehouse or row.t_warehouse
-					)
+				bundle_details = {
+					"item_code": row.item_code,
+					"posting_date": self.posting_date,
+					"posting_time": self.posting_time,
+					"voucher_type": self.doctype,
+					"voucher_no": self.name,
+					"voucher_detail_no": row.name,
+					"company": self.company,
+					"is_rejected": 1 if row.get("rejected_warehouse") else 0,
+					"serial_nos": get_serial_nos(row.serial_no) if row.serial_no else None,
+					"batch_no": row.batch_no,
+					"use_serial_batch_fields": row.use_serial_batch_fields,
+					"do_not_submit": True,
+				}
 
-				sn_doc = SerialBatchCreation(
-					{
-						"item_code": row.item_code,
-						"warehouse": warehouse,
-						"posting_date": self.posting_date,
-						"posting_time": self.posting_time,
-						"voucher_type": self.doctype,
-						"voucher_no": self.name,
-						"voucher_detail_no": row.name,
-						"qty": qty,
-						"type_of_transaction": type_of_transaction,
-						"company": self.company,
-						"is_rejected": 1 if row.get("rejected_warehouse") else 0,
-						"serial_nos": get_serial_nos(row.serial_no) if row.serial_no else None,
-						"batches": frappe._dict({row.batch_no: qty}) if row.batch_no else None,
-						"batch_no": row.batch_no,
-						"use_serial_batch_fields": row.use_serial_batch_fields,
-						"do_not_submit": True,
-					}
-				).make_serial_and_batch_bundle()
+				self.update_bundle_details(bundle_details, table_name, row)
+				sn_doc = SerialBatchCreation(bundle_details).make_serial_and_batch_bundle()
 
 				if sn_doc.is_rejected:
 					row.rejected_serial_and_batch_bundle = sn_doc.name
@@ -243,6 +223,34 @@
 						}
 					)
 
+	def update_bundle_details(self, bundle_details, table_name, row):
+		# Since qty field is different for different doctypes
+		qty = row.get("qty")
+		warehouse = row.get("warehouse")
+
+		if table_name == "packed_items":
+			type_of_transaction = "Inward"
+			if not self.is_return:
+				type_of_transaction = "Outward"
+		else:
+			type_of_transaction = get_type_of_transaction(self, row)
+
+		if hasattr(row, "stock_qty"):
+			qty = row.stock_qty
+
+		if self.doctype == "Stock Entry":
+			qty = row.transfer_qty
+			warehouse = row.s_warehouse or row.t_warehouse
+
+		bundle_details.update(
+			{
+				"qty": qty,
+				"type_of_transaction": type_of_transaction,
+				"warehouse": warehouse,
+				"batches": frappe._dict({row.batch_no: qty}) if row.batch_no else None,
+			}
+		)
+
 	def validate_serial_nos_and_batches_with_bundle(self, row):
 		from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos