fix: fetch batch items in stock reco
diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py
index cb1ee92..68de0b2 100644
--- a/erpnext/manufacturing/doctype/work_order/test_work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py
@@ -389,17 +389,12 @@
 		ste.submit()
 		stock_entries.append(ste)
 
-		job_cards = frappe.get_all('Job Card', filters = {'work_order': work_order.name})
+		job_cards = frappe.get_all('Job Card', filters = {'work_order': work_order.name}, order_by='creation asc')
 		self.assertEqual(len(job_cards), len(bom.operations))
 
 		for i, job_card in enumerate(job_cards):
 			doc = frappe.get_doc("Job Card", job_card)
-			doc.append("time_logs", {
-				"from_time": add_to_date(None, i),
-				"hours": 1,
-				"to_time": add_to_date(None, i + 1),
-				"completed_qty": doc.for_quantity
-			})
+			doc.time_logs[0].completed_qty = 1
 			doc.submit()
 
 		ste1 = frappe.get_doc(make_stock_entry(work_order.name, "Manufacture", 1))
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
index ac4ed5e..a01db80 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
@@ -48,37 +48,54 @@
 	},
 
 	get_items: function(frm) {
-		frappe.prompt({label:"Warehouse", fieldname: "warehouse", fieldtype:"Link", options:"Warehouse", reqd: 1,
+		let fields = [{
+			label: 'Warehouse', fieldname: 'warehouse', fieldtype: 'Link', options: 'Warehouse', reqd: 1,
 			"get_query": function() {
 				return {
 					"filters": {
 						"company": frm.doc.company,
 					}
-				}
-			}},
-			function(data) {
-				frappe.call({
-					method:"erpnext.stock.doctype.stock_reconciliation.stock_reconciliation.get_items",
-					args: {
-						warehouse: data.warehouse,
-						posting_date: frm.doc.posting_date,
-						posting_time: frm.doc.posting_time,
-						company:frm.doc.company
-					},
-					callback: function(r) {
-						var items = [];
-						frm.clear_table("items");
-						for(var i=0; i< r.message.length; i++) {
-							var d = frm.add_child("items");
-							$.extend(d, r.message[i]);
-							if(!d.qty) d.qty = null;
-							if(!d.valuation_rate) d.valuation_rate = null;
-						}
-						frm.refresh_field("items");
-					}
-				});
+				};
 			}
-		, __("Get Items"), __("Update"));
+		}, {
+			label: "Item Code", fieldname: "item_code", fieldtype: "Link", options: "Item",
+			"get_query": function() {
+				return {
+					"filters": {
+						"disabled": 0,
+					}
+				};
+			}
+		}];
+
+		frappe.prompt(fields, function(data) {
+			frappe.call({
+				method: "erpnext.stock.doctype.stock_reconciliation.stock_reconciliation.get_items",
+				args: {
+					warehouse: data.warehouse,
+					posting_date: frm.doc.posting_date,
+					posting_time: frm.doc.posting_time,
+					company: frm.doc.company,
+					item_code: data.item_code
+				},
+				callback: function(r) {
+					frm.clear_table("items");
+					for (var i=0; i<r.message.length; i++) {
+						var d = frm.add_child("items");
+						$.extend(d, r.message[i]);
+
+						if (!d.qty) {
+							d.qty = 0;
+						}
+
+						if (!d.valuation_rate) {
+							d.valuation_rate = 0;
+						}
+					}
+					frm.refresh_field("items");
+				}
+			});
+		}, __("Get Items"), __("Update"));
 	},
 
 	posting_date: function(frm) {
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
index 2b51c1a..e646600 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
@@ -481,45 +481,99 @@
 			self._cancel()
 
 @frappe.whitelist()
-def get_items(warehouse, posting_date, posting_time, company):
+def get_items(warehouse, posting_date, posting_time, company, item_code=None):
+	items = [frappe._dict({
+		'item_code': item_code,
+		'warehouse': warehouse
+	})]
+
+	if not item_code:
+		items = get_items_for_stock_reco(warehouse, company)
+
+	res = []
+	itemwise_batch_data = get_itemwise_batch(warehouse, posting_date, company, item_code)
+
+	for d in items:
+		if d.item_code in itemwise_batch_data:
+			stock_bal = get_stock_balance(d.item_code, d.warehouse,
+				posting_date, posting_time, with_valuation_rate=True)
+
+			for row in itemwise_batch_data.get(d.item_code):
+				args = get_item_data(row, row.qty, stock_bal[1])
+				res.append(args)
+		else:
+			stock_bal = get_stock_balance(d.item_code, d.warehouse, posting_date, posting_time,
+				with_valuation_rate=True , with_serial_no=cint(d.has_serial_no))
+
+			args = get_item_data(d, stock_bal[0], stock_bal[1],
+				stock_bal[2] if cint(d.has_serial_no) else '')
+
+			res.append(args)
+
+	return res
+
+def get_items_for_stock_reco(warehouse, company):
 	lft, rgt = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt"])
 	items = frappe.db.sql("""
-		select i.name, i.item_name, bin.warehouse, i.has_serial_no
+		select i.name as item_code, i.item_name, bin.warehouse as warehouse, i.has_serial_no, i.has_batch_no
 		from tabBin bin, tabItem i
-		where i.name=bin.item_code and i.disabled=0 and i.is_stock_item = 1
-		and i.has_variants = 0 and i.has_batch_no = 0
-		and exists(select name from `tabWarehouse` where lft >= %s and rgt <= %s and name=bin.warehouse)
-	""", (lft, rgt))
+		where i.name=bin.item_code and IFNULL(i.disabled, 0) = 0 and i.is_stock_item = 1
+		and i.has_variants = 0 and exists(
+			select name from `tabWarehouse` where lft >= %s and rgt <= %s and name=bin.warehouse
+		)
+	""", (lft, rgt), as_dict=1)
 
 	items += frappe.db.sql("""
-		select i.name, i.item_name, id.default_warehouse, i.has_serial_no
+		select i.name as item_code, i.item_name, id.default_warehouse as warehouse, i.has_serial_no, i.has_batch_no
 		from tabItem i, `tabItem Default` id
 		where i.name = id.parent
 			and exists(select name from `tabWarehouse` where lft >= %s and rgt <= %s and name=id.default_warehouse)
-			and i.is_stock_item = 1 and i.has_batch_no = 0
-			and i.has_variants = 0 and i.disabled = 0 and id.company=%s
+			and i.is_stock_item = 1 and i.has_variants = 0 and IFNULL(i.disabled, 0) = 0 and id.company=%s
 		group by i.name
-	""", (lft, rgt, company))
+	""", (lft, rgt, company), as_dict=1)
 
-	res = []
-	for d in set(items):
-		stock_bal = get_stock_balance(d[0], d[2], posting_date, posting_time,
-			with_valuation_rate=True , with_serial_no=cint(d[3]))
+	return items
 
-		if frappe.db.get_value("Item", d[0], "disabled") == 0:
-			res.append({
-				"item_code": d[0],
-				"warehouse": d[2],
-				"qty": stock_bal[0],
-				"item_name": d[1],
-				"valuation_rate": stock_bal[1],
-				"current_qty": stock_bal[0],
-				"current_valuation_rate": stock_bal[1],
-				"current_serial_no": stock_bal[2] if cint(d[3]) else '',
-				"serial_no": stock_bal[2] if cint(d[3]) else ''
-			})
+def get_item_data(row, qty, valuation_rate, serial_no=None):
+	return {
+		'item_code': row.item_code,
+		'warehouse': row.warehouse,
+		'qty': qty,
+		'item_name': row.item_name,
+		'valuation_rate': valuation_rate,
+		'current_qty': qty,
+		'current_valuation_rate': valuation_rate,
+		'current_serial_no': serial_no,
+		'serial_no': serial_no,
+		'batch_no': row.get('batch_no')
+	}
 
-	return res
+def get_itemwise_batch(warehouse, posting_date, company, item_code=None):
+	from erpnext.stock.report.batch_wise_balance_history.batch_wise_balance_history import execute
+	itemwise_batch_data = {}
+
+	filters = frappe._dict({
+		'warehouse': warehouse,
+		'from_date': posting_date,
+		'to_date': posting_date,
+		'company': company
+	})
+
+	if item_code:
+		filters.item_code = item_code
+
+	columns, data = execute(filters)
+
+	for row in data:
+		itemwise_batch_data.setdefault(row[0], []).append(frappe._dict({
+			'item_code': row[0],
+			'warehouse': warehouse,
+			'qty': row[8],
+			'item_name': row[1],
+			'batch_no': row[4]
+		}))
+
+	return itemwise_batch_data
 
 @frappe.whitelist()
 def get_stock_balance_for(item_code, warehouse,