Fixed incorrect operation time calculation develop (#23674)

* fix: incorrect operation time calculation for batch size

* Update test_work_order.py
diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
index e728cc2..d020bc8 100644
--- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
@@ -251,6 +251,10 @@
 			'rate': item_doc.valuation_rate or args.rate,
 		})
 
-	bom.insert(ignore_permissions=True)
-	bom.submit()
+	if not args.do_not_save:
+		bom.insert(ignore_permissions=True)
+
+		if not args.do_not_submit:
+			bom.submit()
+
 	return bom
diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py
index b7c7c32..7010f29 100644
--- a/erpnext/manufacturing/doctype/work_order/test_work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py
@@ -407,6 +407,49 @@
 		ste1 = frappe.get_doc(make_stock_entry(wo.name, "Manufacture", 1))
 		self.assertEqual(len(ste1.items), 3)
 
+	def test_operation_time_with_batch_size(self):
+		fg_item = "Test Batch Size Item For BOM"
+		rm1 = "Test Batch Size Item RM 1 For BOM"
+
+		for item in ["Test Batch Size Item For BOM", "Test Batch Size Item RM 1 For BOM"]:
+			make_item(item, {
+				"include_item_in_manufacturing": 1,
+				"is_stock_item": 1
+			})
+
+		bom_name = frappe.db.get_value("BOM",
+			{"item": fg_item, "is_active": 1, "with_operations": 1}, "name")
+
+		if not bom_name:
+			bom = make_bom(item=fg_item, rate=1000, raw_materials = [rm1], do_not_save=True)
+			bom.with_operations = 1
+			bom.append("operations", {
+				"operation": "_Test Operation 1",
+				"workstation": "_Test Workstation 1",
+				"description": "Test Data",
+				"operating_cost": 100,
+				"time_in_mins": 40,
+				"batch_size": 5
+			})
+
+			bom.save()
+			bom.submit()
+			bom_name = bom.name
+
+		work_order = make_wo_order_test_record(item=fg_item,
+			planned_start_date=now(), qty=1, do_not_save=True)
+
+		work_order.set_work_order_operations()
+		work_order.save()
+		self.assertEqual(work_order.operations[0].time_in_mins, 8.0)
+
+		work_order1 = make_wo_order_test_record(item=fg_item,
+			planned_start_date=now(), qty=5, do_not_save=True)
+
+		work_order1.set_work_order_operations()
+		work_order1.save()
+		self.assertEqual(work_order1.operations[0].time_in_mins, 40.0)
+
 def get_scrap_item_details(bom_no):
 	scrap_items = {}
 	for item in frappe.db.sql("""select item_code, stock_qty from `tabBOM Scrap Item`
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index 3173b6c..7f8341f 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -403,7 +403,7 @@
 		bom_qty = frappe.db.get_value("BOM", self.bom_no, "quantity")
 
 		for d in self.get("operations"):
-			d.time_in_mins = flt(d.time_in_mins) / flt(bom_qty) * math.ceil(flt(self.qty) / flt(d.batch_size))
+			d.time_in_mins = flt(d.time_in_mins) / flt(bom_qty) * (flt(self.qty) / flt(d.batch_size))
 
 		self.calculate_operating_cost()