diff --git a/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py b/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py index a53d4a82ba6..6b3636db355 100644 --- a/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py +++ b/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py @@ -1,24 +1,26 @@ import unittest import frappe +from frappe.tests.utils import FrappeTestCase from frappe.utils import add_days, add_months, getdate, nowdate import erpnext from erpnext.hr.doctype.employee.test_employee import make_employee +from erpnext.hr.doctype.leave_allocation.leave_allocation import ( + BackDatedAllocationError, + OverAllocationError, +) from erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry import process_expired_allocation from erpnext.hr.doctype.leave_type.test_leave_type import create_leave_type -class TestLeaveAllocation(unittest.TestCase): - @classmethod - def setUpClass(cls): - frappe.db.sql("delete from `tabLeave Period`") +class TestLeaveAllocation(FrappeTestCase): + def setUp(self): + frappe.db.delete("Leave Period") + frappe.db.delete("Leave Allocation") emp_id = make_employee("test_emp_leave_allocation@salary.com") - cls.employee = frappe.get_doc("Employee", emp_id) - - def tearDown(self): - frappe.db.rollback() + self.employee = frappe.get_doc("Employee", emp_id) def test_overlapping_allocation(self): leaves = [ @@ -65,7 +67,7 @@ class TestLeaveAllocation(unittest.TestCase): # invalid period self.assertRaises(frappe.ValidationError, doc.save) - def test_allocated_leave_days_over_period(self): + def test_validation_for_over_allocation(self): doc = frappe.get_doc( { "doctype": "Leave Allocation", @@ -80,7 +82,135 @@ class TestLeaveAllocation(unittest.TestCase): ) # allocated leave more than period - self.assertRaises(frappe.ValidationError, doc.save) + self.assertRaises(OverAllocationError, doc.save) + + def test_validation_for_over_allocation_post_submission(self): + allocation = frappe.get_doc( + { + "doctype": "Leave Allocation", + "__islocal": 1, + "employee": self.employee.name, + "employee_name": self.employee.employee_name, + "leave_type": "_Test Leave Type", + "from_date": getdate("2015-09-1"), + "to_date": getdate("2015-09-30"), + "new_leaves_allocated": 15, + } + ).submit() + allocation.reload() + # allocated leaves more than period after submission + allocation.new_leaves_allocated = 35 + self.assertRaises(OverAllocationError, allocation.save) + + def test_validation_for_over_allocation_based_on_leave_setup(self): + frappe.delete_doc_if_exists("Leave Period", "Test Allocation Period") + leave_period = frappe.get_doc( + dict( + name="Test Allocation Period", + doctype="Leave Period", + from_date=add_months(nowdate(), -6), + to_date=add_months(nowdate(), 6), + company="_Test Company", + is_active=1, + ) + ).insert() + + leave_type = create_leave_type(leave_type_name="_Test Allocation Validation", is_carry_forward=1) + leave_type.max_leaves_allowed = 25 + leave_type.save() + + # 15 leaves allocated in this period + allocation = create_leave_allocation( + leave_type=leave_type.name, + employee=self.employee.name, + employee_name=self.employee.employee_name, + from_date=leave_period.from_date, + to_date=nowdate(), + ) + allocation.submit() + + # trying to allocate additional 15 leaves + allocation = create_leave_allocation( + leave_type=leave_type.name, + employee=self.employee.name, + employee_name=self.employee.employee_name, + from_date=add_days(nowdate(), 1), + to_date=leave_period.to_date, + ) + self.assertRaises(OverAllocationError, allocation.save) + + def test_validation_for_over_allocation_based_on_leave_setup_post_submission(self): + frappe.delete_doc_if_exists("Leave Period", "Test Allocation Period") + leave_period = frappe.get_doc( + dict( + name="Test Allocation Period", + doctype="Leave Period", + from_date=add_months(nowdate(), -6), + to_date=add_months(nowdate(), 6), + company="_Test Company", + is_active=1, + ) + ).insert() + + leave_type = create_leave_type(leave_type_name="_Test Allocation Validation", is_carry_forward=1) + leave_type.max_leaves_allowed = 30 + leave_type.save() + + # 15 leaves allocated + allocation = create_leave_allocation( + leave_type=leave_type.name, + employee=self.employee.name, + employee_name=self.employee.employee_name, + from_date=leave_period.from_date, + to_date=nowdate(), + ) + allocation.submit() + allocation.reload() + + # allocate additional 15 leaves + allocation = create_leave_allocation( + leave_type=leave_type.name, + employee=self.employee.name, + employee_name=self.employee.employee_name, + from_date=add_days(nowdate(), 1), + to_date=leave_period.to_date, + ) + allocation.submit() + allocation.reload() + + # trying to allocate 25 leaves in 2nd alloc within leave period + # total leaves = 40 which is more than `max_leaves_allowed` setting i.e. 30 + allocation.new_leaves_allocated = 25 + self.assertRaises(OverAllocationError, allocation.save) + + def test_validate_back_dated_allocation_update(self): + leave_type = create_leave_type(leave_type_name="_Test_CF_leave", is_carry_forward=1) + leave_type.save() + + # initial leave allocation = 15 + leave_allocation = create_leave_allocation( + employee=self.employee.name, + employee_name=self.employee.employee_name, + leave_type="_Test_CF_leave", + from_date=add_months(nowdate(), -12), + to_date=add_months(nowdate(), -1), + carry_forward=0, + ) + leave_allocation.submit() + + # new_leaves = 15, carry_forwarded = 10 + leave_allocation_1 = create_leave_allocation( + employee=self.employee.name, + employee_name=self.employee.employee_name, + leave_type="_Test_CF_leave", + carry_forward=1, + ) + leave_allocation_1.submit() + + # try updating initial leave allocation + leave_allocation.reload() + leave_allocation.new_leaves_allocated = 20 + self.assertRaises(BackDatedAllocationError, leave_allocation.save) def test_carry_forward_calculation(self): leave_type = create_leave_type(leave_type_name="_Test_CF_leave", is_carry_forward=1) @@ -108,8 +238,10 @@ class TestLeaveAllocation(unittest.TestCase): carry_forward=1, ) leave_allocation_1.submit() + leave_allocation_1.reload() self.assertEqual(leave_allocation_1.unused_leaves, 10) + self.assertEqual(leave_allocation_1.total_leaves_allocated, 25) leave_allocation_1.cancel() @@ -197,9 +329,12 @@ class TestLeaveAllocation(unittest.TestCase): employee=self.employee.name, employee_name=self.employee.employee_name ) leave_allocation.submit() + leave_allocation.reload() self.assertTrue(leave_allocation.total_leaves_allocated, 15) + leave_allocation.new_leaves_allocated = 40 leave_allocation.submit() + leave_allocation.reload() self.assertTrue(leave_allocation.total_leaves_allocated, 40) def test_leave_subtraction_after_submit(self): @@ -207,9 +342,12 @@ class TestLeaveAllocation(unittest.TestCase): employee=self.employee.name, employee_name=self.employee.employee_name ) leave_allocation.submit() + leave_allocation.reload() self.assertTrue(leave_allocation.total_leaves_allocated, 15) + leave_allocation.new_leaves_allocated = 10 leave_allocation.submit() + leave_allocation.reload() self.assertTrue(leave_allocation.total_leaves_allocated, 10) def test_validation_against_leave_application_after_submit(self):