From 616a6d2bc27203f30c37d90e3c501ebf55c0620c Mon Sep 17 00:00:00 2001 From: Manas Solanki Date: Wed, 20 Jun 2018 17:47:45 +0530 Subject: [PATCH] Test leave management (#14587) * test max allowed days in leave policy * test the leave period * test leave encashment --- .../leave_encashment/test_leave_encashment.py | 78 +++++++++++-------- .../hr/doctype/leave_period/leave_period.py | 25 +++++- .../doctype/leave_period/test_leave_period.py | 77 ++++++++++++------ .../doctype/leave_policy/test_leave_policy.py | 19 ++++- .../hr/doctype/leave_type/test_records.json | 36 ++++++--- .../salary_structure/test_salary_structure.py | 9 ++- 6 files changed, 169 insertions(+), 75 deletions(-) diff --git a/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py b/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py index 4af23b1717..2029973aac 100644 --- a/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py +++ b/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py @@ -5,38 +5,52 @@ from __future__ import unicode_literals import frappe import unittest +from frappe.utils import today, add_months +from erpnext.hr.doctype.employee.test_employee import make_employee +from erpnext.hr.doctype.salary_structure.test_salary_structure import make_salary_structure +from erpnext.hr.doctype.leave_period.test_leave_period import create_leave_period -# class TestLeaveEncashment(unittest.TestCase): -# def test_leave_balance_value_and_amount(self): -# employee = get_employee() -# leave_period = get_leave_period() -# today = get_today() -# -# leave_type = frappe.get_doc(dict( -# leave_type_name = 'Test Leave Type', -# doctype = 'Leave Type', -# allow_encashment = 1, -# encashment_threshold_days = 3, -# earning_component = 'Leave Encashment' -# )).insert() -# -# allocate_leave(employee, leave_period, leave_type.name, 5) -# -# leave_encashment = frappe.get_doc(dict( -# doctype = 'Leave Encashment', -# employee = employee, -# leave_period = leave_period, -# leave_type = leave_type.name, -# payroll_date = today -# )).insert() -# -# self.assertEqual(leave_encashment.leave_balance, 5) -# self.assertEqual(leave_encashment.encashable_days, 2) -# -# # TODO; validate value -# salary_structure = get_current_structure(employee, today) -# self.assertEqual(leave_encashment.encashment_value, -# 2 * frappe.db.get_value('Salary Structure', salary_structure, 'leave_encashment_amount_per_day')) +test_dependencies = ["Leave Type"] +class TestLeaveEncashment(unittest.TestCase): + def setUp(self): + frappe.db.sql('''delete from `tabLeave Period`''') + def test_leave_balance_value_and_amount(self): + employee = "test_employee_encashment@salary.com" + leave_type = "_Test Leave Type Encashment" - + # create the leave policy + leave_policy = frappe.get_doc({ + "doctype": "Leave Policy", + "leave_policy_details": [{ + "leave_type": leave_type, + "annual_allocation": 10 + }] + }).insert() + leave_policy.submit() + + # create employee, salary structure and assignment + employee = make_employee(employee) + frappe.db.set_value("Employee", employee, "leave_policy", leave_policy.name) + salary_structure = make_salary_structure("Salary Structure for Encashment", "Monthly", employee, + other_details={"leave_encashment_amount_per_day": 50}) + + # create the leave period and assign the leaves + leave_period = create_leave_period(add_months(today(), -3), add_months(today(), 3)) + leave_period.employee = employee + leave_period.grant_leave_allocation() + + leave_encashment = frappe.get_doc(dict( + doctype = 'Leave Encashment', + employee = employee, + leave_type = leave_type, + leave_period = leave_period.name, + payroll_date = today() + )).insert() + + self.assertEqual(leave_encashment.leave_balance, 10) + self.assertEqual(leave_encashment.encashable_days, 5) + self.assertEqual(leave_encashment.encashment_amount, 250) + + leave_encashment.submit() + self.assertTrue(frappe.db.get_value("Leave Encashment", leave_encashment.name, "additional_salary")) diff --git a/erpnext/hr/doctype/leave_period/leave_period.py b/erpnext/hr/doctype/leave_period/leave_period.py index 39001ee7b7..bcff89aaa5 100644 --- a/erpnext/hr/doctype/leave_period/leave_period.py +++ b/erpnext/hr/doctype/leave_period/leave_period.py @@ -30,15 +30,22 @@ class LeavePeriod(Document): def grant_leave_allocation(self): if self.employee: - self.grant_leave_alloc(self.employee) + leave_allocation = self.grant_leave_alloc(self.employee) + if leave_allocation: + self.print_message([leave_allocation]) else: self.grant_leave_alloc_for_employees() def grant_leave_alloc_for_employees(self): employees = self.get_employees() if employees: + leave_allocations = [] for employee in employees: - self.grant_leave_alloc(cstr(employee[0])) + leave_allocation = self.grant_leave_alloc(cstr(employee[0])) + if leave_allocation: + leave_allocations.append(leave_allocation) + if leave_allocations: + self.print_message(leave_allocations) else: frappe.msgprint(_("No employee found")) @@ -48,7 +55,11 @@ class LeavePeriod(Document): if leave_policy: for leave_policy_detail in leave_policy.leave_policy_details: if not frappe.db.get_value("Leave Type", leave_policy_detail.leave_type, "is_lwp"): - self.create_leave_allocation(employee, leave_policy_detail.leave_type, leave_policy_detail.annual_allocation) + return self.create_leave_allocation(employee, leave_policy_detail.leave_type, leave_policy_detail.annual_allocation) + else: + return None + else: + return None def validate_allocation_exists(self, employee): leave_alloc = frappe.db.exists({ @@ -79,4 +90,10 @@ class LeavePeriod(Document): allocation.carry_forward = self.carry_forward_leaves allocation.save(ignore_permissions = True) allocation.submit() - frappe.msgprint(_("Leave Allocation {0} created").format(allocation.name)) + return allocation.name + + + def print_message(self, leave_allocations): + if leave_allocations: + frappe.msgprint(_("Leave Allocations {0} created").format(", " + .join(map(lambda x: """ {0}""".format(x), leave_allocations)))) \ No newline at end of file diff --git a/erpnext/hr/doctype/leave_period/test_leave_period.py b/erpnext/hr/doctype/leave_period/test_leave_period.py index 3de9e60594..4a5b0f6bb8 100644 --- a/erpnext/hr/doctype/leave_period/test_leave_period.py +++ b/erpnext/hr/doctype/leave_period/test_leave_period.py @@ -3,29 +3,58 @@ # See license.txt from __future__ import unicode_literals -import frappe +import frappe, erpnext import unittest +from frappe.utils import today, add_months +from erpnext.hr.doctype.employee.test_employee import make_employee +from erpnext.hr.doctype.leave_application.leave_application import get_leave_balance_on -# class TestLeavePeriod(unittest.TestCase): -# def test_leave_grant(self): -# employee = get_employee() -# leave_policy = get_leave_policy() -# leave_period = get_leave_period() -# -# frappe.db.set_value('Employee', employee, 'leave_policy', leave_policy) -# -# leave_period.employee = employee -# -# clear_leave_allocation(employee) -# -# leave_period.grant_leaves() -# -# for d in leave_policy: -# self.assertEqual(get_leave_balance(employee, d.leave_type), d.annual_allocation) -# -# return leave_period -# -# def test_duplicate_grant(self): -# leave_period = self.test_leave_grant() -# self.assertRaises(DuplicateLeaveGrant, leave_period.grant_leaves) -# +test_dependencies = ["Employee", "Leave Type"] + +class TestLeavePeriod(unittest.TestCase): + def setUp(self): + frappe.db.sql("delete from `tabLeave Period`") + + def test_leave_grant(self): + leave_type = "_Test Leave Type" + + # create the leave policy + leave_policy = frappe.get_doc({ + "doctype": "Leave Policy", + "leave_policy_details": [{ + "leave_type": leave_type, + "annual_allocation": 20 + }] + }).insert() + leave_policy.submit() + + # create employee and assign the leave period + employee = "test_leave_period@employee.com" + employee_doc_name = make_employee(employee) + frappe.db.set_value("Employee", employee_doc_name, "leave_policy", leave_policy.name) + + # clear the already allocated leave + frappe.db.sql('''delete from `tabLeave Allocation` where employee=%s''', "test_leave_period@employee.com") + + # create the leave period + leave_period = create_leave_period(add_months(today(), -3), add_months(today(), 3)) + + # test leave_allocation + leave_period.employee = employee_doc_name + leave_period.grant_leave_allocation() + self.assertEqual(get_leave_balance_on(employee_doc_name, leave_type, today()), 20) + + # leave_period.grant_leave_alloc(employee_doc_name) + self.assertRaises(frappe.ValidationError, leave_period.grant_leave_allocation) + + +def create_leave_period(from_date, to_date): + leave_period = frappe.get_doc({ + "doctype": "Leave Period", + "name": "_Test Leave Period", + "company": erpnext.get_default_company(), + "from_date": from_date, + "to_date": to_date, + "is_active": 1 + }).insert() + return leave_period \ No newline at end of file diff --git a/erpnext/hr/doctype/leave_policy/test_leave_policy.py b/erpnext/hr/doctype/leave_policy/test_leave_policy.py index 3317ac3831..2c6f1d0a21 100644 --- a/erpnext/hr/doctype/leave_policy/test_leave_policy.py +++ b/erpnext/hr/doctype/leave_policy/test_leave_policy.py @@ -7,4 +7,21 @@ import frappe import unittest class TestLeavePolicy(unittest.TestCase): - pass + def test_max_leave_allowed(self): + random_leave_type = frappe.get_all("Leave Type", fields=["name", "max_leaves_allowed"]) + if random_leave_type: + random_leave_type = random_leave_type[0] + leave_type = frappe.get_doc("Leave Type", random_leave_type.name) + old_max_leaves_allowed = leave_type.max_leaves_allowed + leave_type.max_leaves_allowed = 2 + leave_type.save() + + leave_policy_details = { + "doctype": "Leave Policy", + "leave_policy_details": [{ + "leave_type": leave_type.name, + "annual_allocation": leave_type.max_leaves_allowed + 1 + }] + } + + self.assertRaises(frappe.ValidationError, frappe.get_doc(leave_policy_details).insert) diff --git a/erpnext/hr/doctype/leave_type/test_records.json b/erpnext/hr/doctype/leave_type/test_records.json index 2ac46cf626..f1f7d8fd14 100644 --- a/erpnext/hr/doctype/leave_type/test_records.json +++ b/erpnext/hr/doctype/leave_type/test_records.json @@ -1,13 +1,27 @@ [ - { - "doctype": "Leave Type", - "leave_type_name": "_Test Leave Type", - "include_holiday": 1 - }, - { - "doctype": "Leave Type", - "is_lwp": 1, - "leave_type_name": "_Test Leave Type LWP", - "include_holiday": 1 - } + { + "doctype": "Leave Type", + "leave_type_name": "_Test Leave Type", + "include_holiday": 1 + }, + { + "doctype": "Leave Type", + "is_lwp": 1, + "leave_type_name": "_Test Leave Type LWP", + "include_holiday": 1 + }, + { + "doctype": "Leave Type", + "leave_type_name": "_Test Leave Type Encashment", + "include_holiday": 1, + "allow_encashment": 1, + "encashment_threshold_days": 5, + "earning_component": "Leave Encashment" + }, + { + "doctype": "Leave Type", + "leave_type_name": "_Test Leave Type Earned", + "include_holiday": 1, + "is_earned_leave": 1 + } ] \ No newline at end of file diff --git a/erpnext/hr/doctype/salary_structure/test_salary_structure.py b/erpnext/hr/doctype/salary_structure/test_salary_structure.py index c15a8a23c9..78b16f29bf 100644 --- a/erpnext/hr/doctype/salary_structure/test_salary_structure.py +++ b/erpnext/hr/doctype/salary_structure/test_salary_structure.py @@ -72,9 +72,9 @@ class TestSalaryStructure(unittest.TestCase): self.assertFalse(("\n" in row.formula) or ("\n" in row.condition)) -def make_salary_structure(salary_structure, payroll_frequency, employee=None, dont_submit=False): +def make_salary_structure(salary_structure, payroll_frequency, employee=None, dont_submit=False, other_details=None): if not frappe.db.exists('Salary Structure', salary_structure): - salary_structure_doc = frappe.get_doc({ + details = { "doctype": "Salary Structure", "name": salary_structure, "company": erpnext.get_default_company(), @@ -82,7 +82,10 @@ def make_salary_structure(salary_structure, payroll_frequency, employee=None, do "deductions": get_deductions_component(), "payroll_frequency": payroll_frequency, "payment_account": get_random("Account") - }).insert() + } + if other_details and isinstance(other_details, dict): + details.update(other_details) + salary_structure_doc = frappe.get_doc(details).insert() if not dont_submit: salary_structure_doc.submit() else: