Merge pull request #30926 from frappe/mergify/bp/develop/pr-30065

fix: HSN-wise-summary of outward supplies Updated Report (backport #30065)
diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.js b/erpnext/hr/doctype/leave_allocation/leave_allocation.js
index aef4412..9742387 100755
--- a/erpnext/hr/doctype/leave_allocation/leave_allocation.js
+++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.js
@@ -34,15 +34,6 @@
 				});
 			}
 		}
-
-		// make new leaves allocated field read only if allocation is created via leave policy assignment
-		// and leave type is earned leave, since these leaves would be allocated via the scheduler
-		if (frm.doc.leave_policy_assignment) {
-			frappe.db.get_value("Leave Type", frm.doc.leave_type, "is_earned_leave", (r) => {
-				if (r && cint(r.is_earned_leave))
-					frm.set_df_property("new_leaves_allocated", "read_only", 1);
-			});
-		}
 	},
 
 	expire_allocation: function(frm) {
diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.py b/erpnext/hr/doctype/leave_application/test_leave_application.py
index 4c39e15..7506c61 100644
--- a/erpnext/hr/doctype/leave_application/test_leave_application.py
+++ b/erpnext/hr/doctype/leave_application/test_leave_application.py
@@ -745,7 +745,7 @@
 
 		i = 0
 		while i < 14:
-			allocate_earned_leaves(ignore_duplicates=True)
+			allocate_earned_leaves()
 			i += 1
 		self.assertEqual(get_leave_balance_on(employee.name, leave_type, nowdate()), 6)
 
@@ -753,7 +753,7 @@
 		frappe.db.set_value("Leave Type", leave_type, "max_leaves_allowed", 0)
 		i = 0
 		while i < 6:
-			allocate_earned_leaves(ignore_duplicates=True)
+			allocate_earned_leaves()
 			i += 1
 		self.assertEqual(get_leave_balance_on(employee.name, leave_type, nowdate()), 9)
 
diff --git a/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py b/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py
index 9780828..031ed0e 100644
--- a/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py
+++ b/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py
@@ -4,6 +4,7 @@
 import unittest
 
 import frappe
+from frappe.tests.utils import FrappeTestCase
 from frappe.utils import add_days, add_months, get_first_day, get_last_day, getdate
 
 from erpnext.hr.doctype.leave_application.test_leave_application import (
@@ -18,7 +19,7 @@
 test_dependencies = ["Employee"]
 
 
-class TestLeavePolicyAssignment(unittest.TestCase):
+class TestLeavePolicyAssignment(FrappeTestCase):
 	def setUp(self):
 		for doctype in [
 			"Leave Period",
@@ -39,6 +40,9 @@
 		leave_policy = create_leave_policy()
 		leave_policy.submit()
 
+		self.employee.date_of_joining = get_first_day(leave_period.from_date)
+		self.employee.save()
+
 		data = {
 			"assignment_based_on": "Leave Period",
 			"leave_policy": leave_policy.name,
@@ -188,19 +192,6 @@
 		)
 		self.assertEqual(leaves_allocated, 3)
 
-		# if the daily job is not completed yet, there is another check present
-		# to ensure leave is not already allocated to avoid duplication
-		from erpnext.hr.utils import allocate_earned_leaves
-
-		allocate_earned_leaves()
-
-		leaves_allocated = frappe.db.get_value(
-			"Leave Allocation",
-			{"leave_policy_assignment": leave_policy_assignments[0]},
-			"total_leaves_allocated",
-		)
-		self.assertEqual(leaves_allocated, 3)
-
 	def test_earned_leave_alloc_for_passed_months_with_cf_leaves_based_on_leave_period(self):
 		from erpnext.hr.doctype.leave_allocation.test_leave_allocation import create_leave_allocation
 
@@ -242,20 +233,6 @@
 		self.assertEqual(details.unused_leaves, 5)
 		self.assertEqual(details.total_leaves_allocated, 7)
 
-		# if the daily job is not completed yet, there is another check present
-		# to ensure leave is not already allocated to avoid duplication
-		from erpnext.hr.utils import is_earned_leave_already_allocated
-
-		frappe.flags.current_date = get_last_day(getdate())
-
-		allocation = frappe.get_doc("Leave Allocation", details.name)
-		# 1 leave is still pending to be allocated, irrespective of carry forwarded leaves
-		self.assertFalse(
-			is_earned_leave_already_allocated(
-				allocation, leave_policy.leave_policy_details[0].annual_allocation
-			)
-		)
-
 	def test_earned_leave_alloc_for_passed_months_based_on_joining_date(self):
 		# tests leave alloc for earned leaves for assignment based on joining date in policy assignment
 		leave_type = create_earned_leave_type("Test Earned Leave")
@@ -288,19 +265,6 @@
 		self.assertEqual(effective_from, self.employee.date_of_joining)
 		self.assertEqual(leaves_allocated, 3)
 
-		# to ensure leave is not already allocated to avoid duplication
-		from erpnext.hr.utils import allocate_earned_leaves
-
-		frappe.flags.current_date = get_last_day(getdate())
-		allocate_earned_leaves()
-
-		leaves_allocated = frappe.db.get_value(
-			"Leave Allocation",
-			{"leave_policy_assignment": leave_policy_assignments[0]},
-			"total_leaves_allocated",
-		)
-		self.assertEqual(leaves_allocated, 3)
-
 	def test_grant_leaves_on_doj_for_earned_leaves_based_on_leave_period(self):
 		# tests leave alloc based on leave period for earned leaves with "based on doj" configuration in leave type
 		leave_period, leave_policy = setup_leave_period_and_policy(
@@ -330,20 +294,6 @@
 		)
 		self.assertEqual(leaves_allocated, 3)
 
-		# if the daily job is not completed yet, there is another check present
-		# to ensure leave is not already allocated to avoid duplication
-		from erpnext.hr.utils import allocate_earned_leaves
-
-		frappe.flags.current_date = get_first_day(getdate())
-		allocate_earned_leaves()
-
-		leaves_allocated = frappe.db.get_value(
-			"Leave Allocation",
-			{"leave_policy_assignment": leave_policy_assignments[0]},
-			"total_leaves_allocated",
-		)
-		self.assertEqual(leaves_allocated, 3)
-
 	def test_grant_leaves_on_doj_for_earned_leaves_based_on_joining_date(self):
 		# tests leave alloc based on joining date for earned leaves with "based on doj" configuration in leave type
 		leave_type = create_earned_leave_type("Test Earned Leave", based_on_doj=True)
@@ -377,21 +327,7 @@
 		self.assertEqual(effective_from, self.employee.date_of_joining)
 		self.assertEqual(leaves_allocated, 3)
 
-		# to ensure leave is not already allocated to avoid duplication
-		from erpnext.hr.utils import allocate_earned_leaves
-
-		frappe.flags.current_date = get_first_day(getdate())
-		allocate_earned_leaves()
-
-		leaves_allocated = frappe.db.get_value(
-			"Leave Allocation",
-			{"leave_policy_assignment": leave_policy_assignments[0]},
-			"total_leaves_allocated",
-		)
-		self.assertEqual(leaves_allocated, 3)
-
 	def tearDown(self):
-		frappe.db.rollback()
 		frappe.db.set_value("Employee", self.employee.name, "date_of_joining", self.original_doj)
 		frappe.flags.current_date = None
 
diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py
index 4e30b0f..269e4aa 100644
--- a/erpnext/hr/utils.py
+++ b/erpnext/hr/utils.py
@@ -269,7 +269,7 @@
 		create_leave_encashment(leave_allocation=leave_allocation)
 
 
-def allocate_earned_leaves(ignore_duplicates=False):
+def allocate_earned_leaves():
 	"""Allocate earned leaves to Employees"""
 	e_leave_types = get_earned_leaves()
 	today = getdate()
@@ -305,14 +305,10 @@
 			if check_effective_date(
 				from_date, today, e_leave_type.earned_leave_frequency, e_leave_type.based_on_date_of_joining
 			):
-				update_previous_leave_allocation(
-					allocation, annual_allocation, e_leave_type, ignore_duplicates
-				)
+				update_previous_leave_allocation(allocation, annual_allocation, e_leave_type)
 
 
-def update_previous_leave_allocation(
-	allocation, annual_allocation, e_leave_type, ignore_duplicates=False
-):
+def update_previous_leave_allocation(allocation, annual_allocation, e_leave_type):
 	earned_leaves = get_monthly_earned_leave(
 		annual_allocation, e_leave_type.earned_leave_frequency, e_leave_type.rounding
 	)
@@ -326,20 +322,19 @@
 	if new_allocation != allocation.total_leaves_allocated:
 		today_date = today()
 
-		if ignore_duplicates or not is_earned_leave_already_allocated(allocation, annual_allocation):
-			allocation.db_set("total_leaves_allocated", new_allocation, update_modified=False)
-			create_additional_leave_ledger_entry(allocation, earned_leaves, today_date)
+		allocation.db_set("total_leaves_allocated", new_allocation, update_modified=False)
+		create_additional_leave_ledger_entry(allocation, earned_leaves, today_date)
 
-			if e_leave_type.based_on_date_of_joining:
-				text = _("allocated {0} leave(s) via scheduler on {1} based on the date of joining").format(
-					frappe.bold(earned_leaves), frappe.bold(formatdate(today_date))
-				)
-			else:
-				text = _("allocated {0} leave(s) via scheduler on {1}").format(
-					frappe.bold(earned_leaves), frappe.bold(formatdate(today_date))
-				)
+		if e_leave_type.based_on_date_of_joining:
+			text = _("allocated {0} leave(s) via scheduler on {1} based on the date of joining").format(
+				frappe.bold(earned_leaves), frappe.bold(formatdate(today_date))
+			)
+		else:
+			text = _("allocated {0} leave(s) via scheduler on {1}").format(
+				frappe.bold(earned_leaves), frappe.bold(formatdate(today_date))
+			)
 
-			allocation.add_comment(comment_type="Info", text=text)
+		allocation.add_comment(comment_type="Info", text=text)
 
 
 def get_monthly_earned_leave(annual_leaves, frequency, rounding):