Merge pull request #29711 from ruchamahabal/leave-policy-assgn-fixes

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 41a9558..c11a821 100644
--- a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py
+++ b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py
@@ -8,11 +8,10 @@
 import frappe
 from frappe import _, bold
 from frappe.model.document import Document
-from frappe.utils import date_diff, flt, formatdate, get_datetime, get_last_day, getdate
+from frappe.utils import date_diff, flt, formatdate, get_last_day, getdate
 
 
 class LeavePolicyAssignment(Document):
-
 	def validate(self):
 		self.validate_policy_assignment_overlap()
 		self.set_dates()
@@ -94,10 +93,12 @@
 			new_leaves_allocated = 0
 
 		elif leave_type_details.get(leave_type).is_earned_leave == 1:
-			if self.assignment_based_on == "Leave Period":
-				new_leaves_allocated = self.get_leaves_for_passed_months(leave_type, new_leaves_allocated, leave_type_details, date_of_joining)
-			else:
+			if not self.assignment_based_on:
 				new_leaves_allocated = 0
+			else:
+				# get leaves for past months if assignment is based on Leave Period / Joining Date
+				new_leaves_allocated = self.get_leaves_for_passed_months(leave_type, new_leaves_allocated, leave_type_details, date_of_joining)
+
 		# Calculate leaves at pro-rata basis for employees joining after the beginning of the given leave period
 		elif getdate(date_of_joining) > getdate(self.effective_from):
 			remaining_period = ((date_diff(self.effective_to, date_of_joining) + 1) / (date_diff(self.effective_to, self.effective_from) + 1))
@@ -108,25 +109,24 @@
 	def get_leaves_for_passed_months(self, leave_type, new_leaves_allocated, leave_type_details, date_of_joining):
 		from erpnext.hr.utils import get_monthly_earned_leave
 
-		current_month = get_datetime(frappe.flags.current_date).month or get_datetime().month
-		current_year = get_datetime(frappe.flags.current_date).year or get_datetime().year
+		current_date = frappe.flags.current_date or getdate()
+		if current_date > getdate(self.effective_to):
+			current_date = getdate(self.effective_to)
 
-		from_date = frappe.db.get_value("Leave Period", self.leave_period, "from_date")
-		if getdate(date_of_joining) > getdate(from_date):
-			from_date = date_of_joining
-
-		from_date_month = get_datetime(from_date).month
-		from_date_year = get_datetime(from_date).year
+		from_date = getdate(self.effective_from)
+		if getdate(date_of_joining) > from_date:
+			from_date = getdate(date_of_joining)
 
 		months_passed = 0
+		based_on_doj = leave_type_details.get(leave_type).based_on_date_of_joining
 
-		if current_year == from_date_year and current_month > from_date_month:
-			months_passed = current_month - from_date_month
-			months_passed = add_current_month_if_applicable(months_passed)
+		if current_date.year == from_date.year and current_date.month >= from_date.month:
+			months_passed = current_date.month - from_date.month
+			months_passed = add_current_month_if_applicable(months_passed, date_of_joining, based_on_doj)
 
-		elif current_year > from_date_year:
-			months_passed = (12 - from_date_month) + current_month
-			months_passed = add_current_month_if_applicable(months_passed)
+		elif current_date.year > from_date.year:
+			months_passed = (12 - from_date.month) + current_date.month
+			months_passed = add_current_month_if_applicable(months_passed, date_of_joining, based_on_doj)
 
 		if months_passed > 0:
 			monthly_earned_leave = get_monthly_earned_leave(new_leaves_allocated,
@@ -138,13 +138,19 @@
 		return new_leaves_allocated
 
 
-def add_current_month_if_applicable(months_passed):
+def add_current_month_if_applicable(months_passed, date_of_joining, based_on_doj):
 	date = getdate(frappe.flags.current_date) or getdate()
-	last_day_of_month = get_last_day(date)
 
-	# if its the last day of the month, then that month should also be considered
-	if last_day_of_month == date:
-		months_passed += 1
+	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.day == date_of_joining.day:
+			months_passed += 1
+	else:
+		last_day_of_month = get_last_day(date)
+		# if its the last day of the month, then that month should be considered
+		if last_day_of_month == date:
+			months_passed += 1
 
 	return months_passed
 
@@ -183,7 +189,7 @@
 def get_leave_type_details():
 	leave_type_details = frappe._dict()
 	leave_types = frappe.get_all("Leave Type",
-		fields=["name", "is_lwp", "is_earned_leave", "is_compensatory",
+		fields=["name", "is_lwp", "is_earned_leave", "is_compensatory", "based_on_date_of_joining",
 			"is_carry_forward", "expire_carry_forwarded_leaves_after_days", "earned_leave_frequency", "rounding"])
 	for d in leave_types:
 		leave_type_details.setdefault(d.name, d)
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 8c76ca1..a19ddce 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,36 +20,31 @@
 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)
+
+		employee = get_employee()
+		self.original_doj = employee.date_of_joining
+		self.employee = employee
 
 	def test_grant_leaves(self):
 		leave_period = get_leave_period()
-		employee = get_employee()
-
-		# create the leave policy with leave type "_Test Leave Type", allocation = 10
+		# allocation = 10
 		leave_policy = create_leave_policy()
 		leave_policy.submit()
 
-
 		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))
-
-		leave_policy_assignment_doc = frappe.get_doc("Leave Policy Assignment", leave_policy_assignments[0])
-		leave_policy_assignment_doc.reload()
-
-		self.assertEqual(leave_policy_assignment_doc.leaves_allocated, 1)
+		leave_policy_assignments = create_assignment_for_multiple_employees([self.employee.name], frappe._dict(data))
+		self.assertEqual(frappe.db.get_value("Leave Policy Assignment", leave_policy_assignments[0], "leaves_allocated"), 1)
 
 		leave_allocation = frappe.get_list("Leave Allocation", filters={
-			"employee": employee.name,
+			"employee": self.employee.name,
 			"leave_policy":leave_policy.name,
 			"leave_policy_assignment": leave_policy_assignments[0],
 			"docstatus": 1})[0]
-
 		leave_alloc_doc = frappe.get_doc("Leave Allocation", leave_allocation)
 
 		self.assertEqual(leave_alloc_doc.new_leaves_allocated, 10)
@@ -61,63 +56,46 @@
 
 	def test_allow_to_grant_all_leave_after_cancellation_of_every_leave_allocation(self):
 		leave_period = get_leave_period()
-		employee = get_employee()
-
 		# create the leave policy with leave type "_Test Leave Type", allocation = 10
 		leave_policy = create_leave_policy()
 		leave_policy.submit()
 
-
 		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))
-
-		leave_policy_assignment_doc = frappe.get_doc("Leave Policy Assignment", leave_policy_assignments[0])
-		leave_policy_assignment_doc.reload()
-
+		leave_policy_assignments = create_assignment_for_multiple_employees([self.employee.name], frappe._dict(data))
 
 		# every leave is allocated no more leave can be granted now
-		self.assertEqual(leave_policy_assignment_doc.leaves_allocated, 1)
-
+		self.assertEqual(frappe.db.get_value("Leave Policy Assignment", leave_policy_assignments[0], "leaves_allocated"), 1)
 		leave_allocation = frappe.get_list("Leave Allocation", filters={
-			"employee": employee.name,
+			"employee": self.employee.name,
 			"leave_policy":leave_policy.name,
 			"leave_policy_assignment": leave_policy_assignments[0],
 			"docstatus": 1})[0]
 
 		leave_alloc_doc = frappe.get_doc("Leave Allocation", leave_allocation)
-
-		# User all allowed to grant leave when there is no allocation against assignment
 		leave_alloc_doc.cancel()
 		leave_alloc_doc.delete()
-
-		leave_policy_assignment_doc.reload()
-
-
-		# User are now allowed to grant leave
-		self.assertEqual(leave_policy_assignment_doc.leaves_allocated, 0)
+		self.assertEqual(frappe.db.get_value("Leave Policy Assignment", leave_policy_assignments[0], "leaves_allocated"), 0)
 
 	def test_earned_leave_allocation(self):
 		leave_period = create_leave_period("Test Earned Leave Period")
-		employee = get_employee()
 		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": 6}]
-		}).insert()
+		}).submit()
 
 		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))
+		leave_policy_assignments = create_assignment_for_multiple_employees([self.employee.name], frappe._dict(data))
 
 		# leaves allocated should be 0 since it is an earned leave and allocation happens via scheduler based on set frequency
 		leaves_allocated = frappe.db.get_value("Leave Allocation", {
@@ -125,16 +103,8 @@
 		}, "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()
+	def test_earned_leave_alloc_for_passed_months_based_on_leave_period(self):
+		leave_period, leave_policy = setup_leave_period_and_policy(get_first_day(add_months(getdate(), -1)))
 
 		# Case 1: assignment created one month after the leave period, should allocate 1 leave
 		frappe.flags.current_date = get_first_day(getdate())
@@ -143,24 +113,15 @@
 			"leave_policy": leave_policy.name,
 			"leave_period": leave_period.name
 		}
-		leave_policy_assignments = create_assignment_for_multiple_employees([employee.name], frappe._dict(data))
+		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, 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()
-
+	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
 		# since the daily job might have already executed
@@ -171,7 +132,7 @@
 			"leave_policy": leave_policy.name,
 			"leave_period": leave_period.name
 		}
-		leave_policy_assignments = create_assignment_for_multiple_employees([employee.name], frappe._dict(data))
+		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]
@@ -188,33 +149,17 @@
 		}, "total_leaves_allocated")
 		self.assertEqual(leaves_allocated, 3)
 
-	def test_earned_leave_allocation_for_passed_months_with_carry_forwarded_leaves(self):
+	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
 
-		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()
-
+		leave_period, leave_policy = setup_leave_period_and_policy(get_first_day(add_months(getdate(), -2)))
 		# initial leave allocation = 5
-		leave_allocation = create_leave_allocation(
-			employee=employee.name,
-			employee_name=employee.employee_name,
-			leave_type=leave_type.name,
-			from_date=add_months(getdate(), -12),
-			to_date=add_months(getdate(), -3),
-			new_leaves_allocated=5,
-			carry_forward=0)
+		leave_allocation = create_leave_allocation(employee=self.employee.name, employee_name=self.employee.employee_name, leave_type="Test Earned Leave",
+			from_date=add_months(getdate(), -12), to_date=add_months(getdate(), -3), new_leaves_allocated=5, carry_forward=0)
 		leave_allocation.submit()
 
 		# Case 3: assignment created on the last day of the leave period's latter month with carry forwarding
 		frappe.flags.current_date = get_last_day(add_months(getdate(), -1))
-
 		data = {
 			"assignment_based_on": "Leave Period",
 			"leave_policy": leave_policy.name,
@@ -222,7 +167,7 @@
 			"carry_forward": 1
 		}
 		# carry forwarded leaves = 5, 3 leaves allocated for passed months
-		leave_policy_assignments = create_assignment_for_multiple_employees([employee.name], frappe._dict(data))
+		leave_policy_assignments = create_assignment_for_multiple_employees([self.employee.name], frappe._dict(data))
 
 		details = frappe.db.get_value("Leave Allocation", {
 			"leave_policy_assignment": leave_policy_assignments[0]
@@ -236,15 +181,122 @@
 		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
+		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)
+
+	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
+		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)
+
+	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
+		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)
+
 	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
 
 
-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(
@@ -253,7 +305,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()
 
 
@@ -269,4 +322,17 @@
 		to_date=add_months(start_date, 12),
 		company="_Test Company",
 		is_active=1
-	)).insert()
\ No newline at end of file
+	)).insert()
+
+
+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({
+		"doctype": "Leave Policy",
+		"title": "Test Leave Policy",
+		"leave_policy_details": [{"leave_type": leave_type.name, "annual_allocation": 12}]
+	}).insert()
+
+	return leave_period, leave_policy
\ No newline at end of file
diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py
index 7fd3a98..c174047 100644
--- a/erpnext/hr/utils.py
+++ b/erpnext/hr/utils.py
@@ -261,10 +261,10 @@
 
 			from_date=allocation.from_date
 
-			if e_leave_type.based_on_date_of_joining_date:
+			if e_leave_type.based_on_date_of_joining:
 				from_date  = frappe.db.get_value("Employee", allocation.employee, "date_of_joining")
 
-			if check_effective_date(from_date, today, e_leave_type.earned_leave_frequency, e_leave_type.based_on_date_of_joining_date):
+			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)
 
 def update_previous_leave_allocation(allocation, annual_allocation, e_leave_type, ignore_duplicates=False):
@@ -343,7 +343,7 @@
 	allocation.unused_leaves = 0
 	allocation.create_leave_ledger_entry()
 
-def check_effective_date(from_date, to_date, frequency, based_on_date_of_joining_date):
+def check_effective_date(from_date, to_date, frequency, based_on_date_of_joining):
 	import calendar
 
 	from dateutil import relativedelta
@@ -354,7 +354,7 @@
 	#last day of month
 	last_day =  calendar.monthrange(to_date.year, to_date.month)[1]
 
-	if (from_date.day == to_date.day and based_on_date_of_joining_date) or (not based_on_date_of_joining_date and to_date.day == last_day):
+	if (from_date.day == to_date.day and based_on_date_of_joining) or (not based_on_date_of_joining and to_date.day == last_day):
 		if frequency == "Monthly":
 			return True
 		elif frequency == "Quarterly" and rd.months % 3: