diff --git a/erpnext/hr/report/employee_leave_balance/test_employee_leave_balance.py b/erpnext/hr/report/employee_leave_balance/test_employee_leave_balance.py index f844be5ff11..aecf0a4d4e5 100644 --- a/erpnext/hr/report/employee_leave_balance/test_employee_leave_balance.py +++ b/erpnext/hr/report/employee_leave_balance/test_employee_leave_balance.py @@ -31,13 +31,13 @@ class TestEmployeeLeaveBalance(unittest.TestCase): frappe.set_user('Administrator') self.employee_id = make_employee('test_emp_leave_balance@example.com', company='_Test Company') - self.holiday_list = make_holiday_list('_Test Emp Balance Holiday List', get_year_start(getdate()), get_year_ending(getdate())) self.date = getdate() self.year_start = getdate(get_year_start(self.date)) self.mid_year = add_months(self.year_start, 6) self.year_end = getdate(get_year_ending(self.date)) + self.holiday_list = make_holiday_list('_Test Emp Balance Holiday List', self.year_start, self.year_end) def tearDown(self): frappe.db.rollback() @@ -56,7 +56,7 @@ class TestEmployeeLeaveBalance(unittest.TestCase): # 4 days leave first_sunday = get_first_sunday(self.holiday_list, for_date=self.year_start) - leave_application = make_leave_application(self.employee_id, first_sunday, add_days(first_sunday, 3), '_Test Leave Type') + leave_application = make_leave_application(self.employee_id, add_days(first_sunday, 1), add_days(first_sunday, 4), '_Test Leave Type') leave_application.reload() filters = { @@ -89,7 +89,7 @@ class TestEmployeeLeaveBalance(unittest.TestCase): allocation1 = make_allocation_record(employee=self.employee_id, from_date=self.year_start, to_date=self.year_end) # 4 days leave application in the first allocation first_sunday = get_first_sunday(self.holiday_list, for_date=self.year_start) - leave_application = make_leave_application(self.employee_id, first_sunday, add_days(first_sunday, 3), '_Test Leave Type') + leave_application = make_leave_application(self.employee_id, add_days(first_sunday, 1), add_days(first_sunday, 4), '_Test Leave Type') leave_application.reload() # Case 1: opening balance for first alloc boundary diff --git a/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py index 936184a9c0d..e484d9e3a11 100644 --- a/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py +++ b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py @@ -12,6 +12,7 @@ from erpnext.hr.report.employee_leave_balance.employee_leave_balance import ( def execute(filters=None): + filters = frappe._dict(filters or {}) leave_types = frappe.db.sql_list("select name from `tabLeave Type` order by name asc") columns = get_columns(leave_types) diff --git a/erpnext/hr/report/employee_leave_balance_summary/test_employee_leave_balance_summary.py b/erpnext/hr/report/employee_leave_balance_summary/test_employee_leave_balance_summary.py new file mode 100644 index 00000000000..9b953de0dc2 --- /dev/null +++ b/erpnext/hr/report/employee_leave_balance_summary/test_employee_leave_balance_summary.py @@ -0,0 +1,117 @@ +# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + + +import unittest + +import frappe +from frappe.utils import add_days, flt, get_year_ending, get_year_start, getdate + +from erpnext.hr.doctype.employee.test_employee import make_employee +from erpnext.hr.doctype.holiday_list.test_holiday_list import set_holiday_list +from erpnext.hr.doctype.leave_application.test_leave_application import ( + get_first_sunday, + make_allocation_record, +) +from erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry import process_expired_allocation +from erpnext.hr.report.employee_leave_balance_summary.employee_leave_balance_summary import execute +from erpnext.payroll.doctype.salary_slip.test_salary_slip import ( + make_holiday_list, + make_leave_application, +) + +test_records = frappe.get_test_records('Leave Type') + +class TestEmployeeLeaveBalance(unittest.TestCase): + def setUp(self): + for dt in ['Leave Application', 'Leave Allocation', 'Salary Slip', 'Leave Ledger Entry', 'Leave Type']: + frappe.db.delete(dt) + + frappe.set_user('Administrator') + + self.employee_id = make_employee('test_emp_leave_balance@example.com', company='_Test Company') + self.employee_id = make_employee('test_emp_leave_balance@example.com', company='_Test Company') + + self.date = getdate() + self.year_start = getdate(get_year_start(self.date)) + self.year_end = getdate(get_year_ending(self.date)) + + self.holiday_list = make_holiday_list('_Test Emp Balance Holiday List', self.year_start, self.year_end) + + def tearDown(self): + frappe.db.rollback() + + @set_holiday_list('_Test Emp Balance Holiday List', '_Test Company') + def test_employee_leave_balance_summary(self): + frappe.get_doc(test_records[0]).insert() + + # 5 leaves + allocation1 = make_allocation_record(employee=self.employee_id, from_date=add_days(self.year_start, -11), + to_date=add_days(self.year_start, -1), leaves=5) + # 30 leaves + allocation2 = make_allocation_record(employee=self.employee_id, from_date=self.year_start, to_date=self.year_end) + + # 2 days leave within the first allocation + leave_application1 = make_leave_application(self.employee_id, add_days(self.year_start, -11), add_days(self.year_start, -10), + '_Test Leave Type') + leave_application1.reload() + + # expires 3 leaves + process_expired_allocation() + + # 4 days leave within the second allocation + first_sunday = get_first_sunday(self.holiday_list, for_date=self.year_start) + leave_application2 = make_leave_application(self.employee_id, add_days(first_sunday, 1), add_days(first_sunday, 4), '_Test Leave Type') + leave_application2.reload() + + filters = { + 'date': self.date, + 'company': '_Test Company', + 'employee': self.employee_id + } + + report = execute(filters) + + expected_data = [[ + self.employee_id, + 'test_emp_leave_balance@example.com', + frappe.db.get_value('Employee', self.employee_id, 'department'), + flt( + allocation1.new_leaves_allocated # allocated = 5 + + allocation2.new_leaves_allocated # allocated = 30 + - leave_application1.total_leave_days # leaves taken in the 1st alloc = 2 + - (allocation1.new_leaves_allocated - leave_application1.total_leave_days) # leaves expired from 1st alloc = 3 + - leave_application2.total_leave_days # leaves taken in the 2nd alloc = 4 + ) + ]] + + self.assertEqual(report[1], expected_data) + + @set_holiday_list('_Test Emp Balance Holiday List', '_Test Company') + def test_get_leave_balance_near_alloc_expiry(self): + frappe.get_doc(test_records[0]).insert() + + # 30 leaves allocated + allocation = make_allocation_record(employee=self.employee_id, from_date=self.year_start, to_date=self.year_end) + # 4 days leave application in the first allocation + first_sunday = get_first_sunday(self.holiday_list, for_date=self.year_start) + leave_application = make_leave_application(self.employee_id, add_days(first_sunday, 1), add_days(first_sunday, 4), '_Test Leave Type') + leave_application.reload() + + # Leave balance should show actual balance, and not "consumption balance as per remaining days", near alloc end date + # eg: 3 days left for alloc to end, leave balance should still be 26 and not 3 + filters = { + 'date': add_days(self.year_end, -3), + 'company': '_Test Company', + 'employee': self.employee_id + } + report = execute(filters) + + expected_data = [[ + self.employee_id, + 'test_emp_leave_balance@example.com', + frappe.db.get_value('Employee', self.employee_id, 'department'), + flt(allocation.new_leaves_allocated - leave_application.total_leave_days) + ]] + + self.assertEqual(report[1], expected_data)