fix: explicitly check if additional salary is recurring while fetching components for payroll (#30489)
diff --git a/erpnext/payroll/doctype/additional_salary/additional_salary.py b/erpnext/payroll/doctype/additional_salary/additional_salary.py
index 256a3b5..18bd3b7 100644
--- a/erpnext/payroll/doctype/additional_salary/additional_salary.py
+++ b/erpnext/payroll/doctype/additional_salary/additional_salary.py
@@ -147,6 +147,8 @@
@frappe.whitelist()
def get_additional_salaries(employee, start_date, end_date, component_type):
+ from frappe.query_builder import Criterion
+
comp_type = "Earning" if component_type == "earnings" else "Deduction"
additional_sal = frappe.qb.DocType("Additional Salary")
@@ -170,8 +172,23 @@
& (additional_sal.type == comp_type)
)
.where(
- additional_sal.payroll_date[start_date:end_date]
- | ((additional_sal.from_date <= end_date) & (additional_sal.to_date >= end_date))
+ Criterion.any(
+ [
+ Criterion.all(
+ [ # is recurring and additional salary dates fall within the payroll period
+ additional_sal.is_recurring == 1,
+ additional_sal.from_date <= end_date,
+ additional_sal.to_date >= end_date,
+ ]
+ ),
+ Criterion.all(
+ [ # is not recurring and additional salary's payroll date falls within the payroll period
+ additional_sal.is_recurring == 0,
+ additional_sal.payroll_date[start_date:end_date],
+ ]
+ ),
+ ]
+ )
)
.run(as_dict=True)
)
diff --git a/erpnext/payroll/doctype/additional_salary/test_additional_salary.py b/erpnext/payroll/doctype/additional_salary/test_additional_salary.py
index 7d5d9e0..bd73936 100644
--- a/erpnext/payroll/doctype/additional_salary/test_additional_salary.py
+++ b/erpnext/payroll/doctype/additional_salary/test_additional_salary.py
@@ -4,7 +4,8 @@
import unittest
import frappe
-from frappe.utils import add_days, nowdate
+from frappe.tests.utils import FrappeTestCase
+from frappe.utils import add_days, add_months, nowdate
import erpnext
from erpnext.hr.doctype.employee.test_employee import make_employee
@@ -16,19 +17,10 @@
from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure
-class TestAdditionalSalary(unittest.TestCase):
+class TestAdditionalSalary(FrappeTestCase):
def setUp(self):
setup_test()
- def tearDown(self):
- for dt in [
- "Salary Slip",
- "Additional Salary",
- "Salary Structure Assignment",
- "Salary Structure",
- ]:
- frappe.db.sql("delete from `tab%s`" % dt)
-
def test_recurring_additional_salary(self):
amount = 0
salary_component = None
@@ -46,19 +38,66 @@
if earning.salary_component == "Recurring Salary Component":
amount = earning.amount
salary_component = earning.salary_component
+ break
self.assertEqual(amount, add_sal.amount)
self.assertEqual(salary_component, add_sal.salary_component)
+ def test_non_recurring_additional_salary(self):
+ amount = 0
+ salary_component = None
+ date = nowdate()
-def get_additional_salary(emp_id):
+ emp_id = make_employee("test_additional@salary.com")
+ frappe.db.set_value("Employee", emp_id, "relieving_date", add_days(date, 1800))
+ salary_structure = make_salary_structure(
+ "Test Salary Structure Additional Salary", "Monthly", employee=emp_id
+ )
+ add_sal = get_additional_salary(emp_id, recurring=False, payroll_date=date)
+
+ ss = make_employee_salary_slip(
+ "test_additional@salary.com", "Monthly", salary_structure=salary_structure.name
+ )
+
+ amount, salary_component = None, None
+ for earning in ss.earnings:
+ if earning.salary_component == "Recurring Salary Component":
+ amount = earning.amount
+ salary_component = earning.salary_component
+ break
+
+ self.assertEqual(amount, add_sal.amount)
+ self.assertEqual(salary_component, add_sal.salary_component)
+
+ # should not show up in next months
+ ss.posting_date = add_months(date, 1)
+ ss.start_date = ss.end_date = None
+ ss.earnings = []
+ ss.deductions = []
+ ss.save()
+
+ amount, salary_component = None, None
+ for earning in ss.earnings:
+ if earning.salary_component == "Recurring Salary Component":
+ amount = earning.amount
+ salary_component = earning.salary_component
+ break
+
+ self.assertIsNone(amount)
+ self.assertIsNone(salary_component)
+
+
+def get_additional_salary(emp_id, recurring=True, payroll_date=None):
create_salary_component("Recurring Salary Component")
add_sal = frappe.new_doc("Additional Salary")
add_sal.employee = emp_id
add_sal.salary_component = "Recurring Salary Component"
- add_sal.is_recurring = 1
+
+ add_sal.is_recurring = 1 if recurring else 0
add_sal.from_date = add_days(nowdate(), -50)
add_sal.to_date = add_days(nowdate(), 180)
+ add_sal.payroll_date = payroll_date
+
add_sal.amount = 5000
add_sal.currency = erpnext.get_default_currency()
add_sal.save()