test: earned leave allocations based on DOJ
diff --git a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py
index 1917f22..c11a821 100644
--- a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py
+++ b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py
@@ -144,7 +144,7 @@
 	if based_on_doj:
 		# if leave type allocation is based on DOJ, and the date of assignment creation is same as DOJ,
 		# then the month should be considered
-		if date == date_of_joining:
+		if date.day == date_of_joining.day:
 			months_passed += 1
 	else:
 		last_day_of_month = get_last_day(date)
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 dcdd7b9..862a1c5 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
@@ -20,7 +20,7 @@
 class TestLeavePolicyAssignment(unittest.TestCase):
 	def setUp(self):
 		for doctype in ["Leave Period", "Leave Application", "Leave Allocation", "Leave Policy Assignment", "Leave Ledger Entry"]:
-			frappe.db.sql("delete from `tab{0}`".format(doctype)) #nosec
+			frappe.db.delete(doctype)
 
 		self.employee = get_employee()
 
@@ -86,7 +86,7 @@
 			"doctype": "Leave Policy",
 			"title": "Test Leave Policy",
 			"leave_policy_details": [{"leave_type": leave_type.name, "annual_allocation": 6}]
-		}).insert()
+		}).submit()
 
 		data = {
 			"assignment_based_on": "Leave Period",
@@ -118,7 +118,7 @@
 		}, "total_leaves_allocated")
 		self.assertEqual(leaves_allocated, 1)
 
-	def test_earned_leave_alloc_for_passed_months_based_on_leave_period(self):
+	def test_earned_leave_alloc_for_passed_months_on_month_end_based_on_leave_period(self):
 		leave_period, leave_policy = setup_leave_period_and_policy(get_first_day(add_months(getdate(), -2)))
 		# 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
@@ -179,15 +179,132 @@
 		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)
+		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")
+		leave_policy = frappe.get_doc({
+			"doctype": "Leave Policy",
+			"title": "Test Leave Policy",
+			"leave_policy_details": [{"leave_type": leave_type.name, "annual_allocation": 12}]
+		}).submit()
+
+		# joining date set to 2 months back
+		doj = self.employee.date_of_joining
+		self.employee.date_of_joining = get_first_day(add_months(getdate(), -2))
+		self.employee.save()
+
+		# assignment created on the last day of the current month
+		frappe.flags.current_date = get_last_day(getdate())
+		data = {
+			"assignment_based_on": "Joining Date",
+			"leave_policy": leave_policy.name
+		}
+		leave_policy_assignments = create_assignment_for_multiple_employees([self.employee.name], frappe._dict(data))
+		leaves_allocated = frappe.db.get_value("Leave Allocation", {"leave_policy_assignment": leave_policy_assignments[0]},
+			"total_leaves_allocated")
+		effective_from = frappe.db.get_value("Leave Policy Assignment", leave_policy_assignments[0], "effective_from")
+		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)
+
+		# reset DOJ
+		frappe.db.set_value("Employee", self.employee.name, "date_of_joining", doj)
+
+	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(get_first_day(add_months(getdate(), -2)), based_on_doj=True)
+
+		# joining date set to 2 months back
+		doj = self.employee.date_of_joining
+		self.employee.date_of_joining = get_first_day(add_months(getdate(), -2))
+		self.employee.save()
+
+		# assignment created on the same day of the current month, should allocate leaves including the current month
+		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([self.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
+		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)
+
+		# reset DOJ
+		frappe.db.set_value("Employee", self.employee.name, "date_of_joining", doj)
+
+	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)
+		leave_policy = frappe.get_doc({
+			"doctype": "Leave Policy",
+			"title": "Test Leave Policy",
+			"leave_policy_details": [{"leave_type": leave_type.name, "annual_allocation": 12}]
+		}).submit()
+
+		# joining date set to 2 months back
+		# leave should be allocated for current month too since this day is same as the joining day
+		doj = self.employee.date_of_joining
+		self.employee.date_of_joining = get_first_day(add_months(getdate(), -2))
+		self.employee.save()
+
+		# assignment created on the first day of the current month
+		frappe.flags.current_date = get_first_day(getdate())
+		data = {
+			"assignment_based_on": "Joining Date",
+			"leave_policy": leave_policy.name
+		}
+		leave_policy_assignments = create_assignment_for_multiple_employees([self.employee.name], frappe._dict(data))
+		leaves_allocated = frappe.db.get_value("Leave Allocation", {"leave_policy_assignment": leave_policy_assignments[0]},
+			"total_leaves_allocated")
+		effective_from = frappe.db.get_value("Leave Policy Assignment", leave_policy_assignments[0], "effective_from")
+		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)
+
+		# reset DOJ
+		frappe.db.set_value("Employee", self.employee.name, "date_of_joining", doj)
+
 	def tearDown(self):
 		frappe.db.rollback()
 
 
-def create_earned_leave_type(leave_type):
+def create_earned_leave_type(leave_type, based_on_doj=False):
 	frappe.delete_doc_if_exists("Leave Type", leave_type, force=1)
 
 	return frappe.get_doc(dict(
@@ -196,7 +313,8 @@
 		is_earned_leave=1,
 		earned_leave_frequency="Monthly",
 		rounding=0.5,
-		is_carry_forward=1
+		is_carry_forward=1,
+		based_on_date_of_joining=based_on_doj
 	)).insert()
 
 
@@ -215,8 +333,8 @@
 	)).insert()
 
 
-def setup_leave_period_and_policy(start_date):
-	leave_type = create_earned_leave_type("Test Earned Leave")
+def setup_leave_period_and_policy(start_date, based_on_doj=False):
+	leave_type = create_earned_leave_type("Test Earned Leave", based_on_doj)
 	leave_period = create_leave_period("Test Earned Leave Period",
 		start_date=start_date)
 	leave_policy = frappe.get_doc({
diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py
index ae4411b..c174047 100644
--- a/erpnext/hr/utils.py
+++ b/erpnext/hr/utils.py
@@ -305,13 +305,10 @@
 		get_leave_type_details,
 	)
 
-	assignment = frappe.get_doc("Leave Policy Assignment", allocation.leave_policy_assignment)
-	if assignment.assignment_based_on == "Joining Date":
-		return False
-
 	leave_type_details = get_leave_type_details()
 	date_of_joining = frappe.db.get_value("Employee", allocation.employee, "date_of_joining")
 
+	assignment = frappe.get_doc("Leave Policy Assignment", allocation.leave_policy_assignment)
 	leaves_for_passed_months = assignment.get_leaves_for_passed_months(allocation.leave_type,
 		annual_allocation, leave_type_details, date_of_joining)