test: earned leave allocation for passed months and allocation on month-end
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 3b7f8ec..3455bae 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,7 +4,7 @@
 import unittest
 
 import frappe
-from frappe.utils import add_months, get_first_day, getdate
+from frappe.utils import add_months, get_first_day, get_last_day, getdate
 
 from erpnext.hr.doctype.leave_application.test_leave_application import (
 	get_employee,
@@ -125,6 +125,69 @@
 		}, "total_leaves_allocated")
 		self.assertEqual(leaves_allocated, 0)
 
+	def test_earned_leave_allocation_for_passed_months(self):
+		employee = get_employee()
+		leave_type = create_earned_leave_type("Test Earned Leave")
+		leave_period = create_leave_period("Test Earned Leave Period",
+			start_date=get_first_day(add_months(getdate(), -1)))
+		leave_policy = frappe.get_doc({
+			"doctype": "Leave Policy",
+			"title": "Test Leave Policy",
+			"leave_policy_details": [{"leave_type": leave_type.name, "annual_allocation": 12}]
+		}).insert()
+
+		# Case 1: assignment created one month after the leave period, should allocate 1 leave
+		frappe.flags.current_date = get_first_day(getdate())
+		data = {
+			"assignment_based_on": "Leave Period",
+			"leave_policy": leave_policy.name,
+			"leave_period": leave_period.name
+		}
+		leave_policy_assignments = create_assignment_for_multiple_employees([employee.name], frappe._dict(data))
+
+		leaves_allocated = frappe.db.get_value("Leave Allocation", {
+			"leave_policy_assignment": leave_policy_assignments[0]
+		}, "total_leaves_allocated")
+		self.assertEqual(leaves_allocated, 1)
+
+	def test_earned_leave_allocation_for_passed_months_on_month_end(self):
+		employee = get_employee()
+		leave_type = create_earned_leave_type("Test Earned Leave")
+		leave_period = create_leave_period("Test Earned Leave Period",
+			start_date=get_first_day(add_months(getdate(), -2)))
+		leave_policy = frappe.get_doc({
+			"doctype": "Leave Policy",
+			"title": "Test Leave Policy",
+			"leave_policy_details": [{"leave_type": leave_type.name, "annual_allocation": 12}]
+		}).insert()
+
+		# Case 2: assignment created on the last day of the leave period's latter month
+		# should allocate 1 leave for current month even though the month has not ended
+		# since the daily job might have already executed
+		frappe.flags.current_date = get_last_day(getdate())
+
+		data = {
+			"assignment_based_on": "Leave Period",
+			"leave_policy": leave_policy.name,
+			"leave_period": leave_period.name
+		}
+		leave_policy_assignments = create_assignment_for_multiple_employees([employee.name], frappe._dict(data))
+
+		leaves_allocated = frappe.db.get_value("Leave Allocation", {
+			"leave_policy_assignment": leave_policy_assignments[0]
+		}, "total_leaves_allocated")
+		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 tearDown(self):
 		frappe.db.rollback()
 
@@ -137,14 +200,14 @@
 		doctype="Leave Type",
 		is_earned_leave=1,
 		earned_leave_frequency="Monthly",
-		rounding=0.5,
-		max_leaves_allowed=6
+		rounding=0.5
 	)).insert()
 
 
-def create_leave_period(name):
+def create_leave_period(name, start_date=None):
 	frappe.delete_doc_if_exists("Leave Period", name, force=1)
-	start_date = get_first_day(getdate())
+	if not start_date:
+		start_date = get_first_day(getdate())
 
 	return frappe.get_doc(dict(
 		name=name,