diff --git a/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py b/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py index d54a47e3c96..32473694c80 100644 --- a/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py +++ b/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.py @@ -12,7 +12,7 @@ class ModeofPayment(Document): self.validate_accounts() self.validate_repeating_companies() self.validate_pos_mode_of_payment() - + def validate_repeating_companies(self): """Error when Same Company is entered multiple times in accounts""" accounts_list = [] @@ -31,10 +31,10 @@ class ModeofPayment(Document): def validate_pos_mode_of_payment(self): if not self.enabled: - pos_profiles = frappe.db.sql("""SELECT sip.parent FROM `tabSales Invoice Payment` sip + pos_profiles = frappe.db.sql("""SELECT sip.parent FROM `tabSales Invoice Payment` sip WHERE sip.parenttype = 'POS Profile' and sip.mode_of_payment = %s""", (self.name)) pos_profiles = list(map(lambda x: x[0], pos_profiles)) - + if pos_profiles: message = "POS Profile " + frappe.bold(", ".join(pos_profiles)) + " contains \ Mode of Payment " + frappe.bold(str(self.name)) + ". Please remove them to disable this mode." diff --git a/erpnext/patches/v13_0/setup_gratuity_rule_for_india_and_uae.py b/erpnext/patches/v13_0/setup_gratuity_rule_for_india_and_uae.py index 5de355f747a..93cadf576cb 100644 --- a/erpnext/patches/v13_0/setup_gratuity_rule_for_india_and_uae.py +++ b/erpnext/patches/v13_0/setup_gratuity_rule_for_india_and_uae.py @@ -3,13 +3,16 @@ from __future__ import unicode_literals -import erpnext +import erpnext, frappe def execute(): + frappe.reload_doc('payroll', 'doctype', 'gratuity_rule') + frappe.reload_doc('payroll', 'doctype', 'gratuity_rule_slab') + frappe.reload_doc('payroll', 'doctype', 'gratuity_applicable_component') region = erpnext.get_region() if region == "India": - from erpnext.regional.india.setup import create_standard_documents - create_standard_documents() + from erpnext.regional.india.setup import create_gratuity_rule + create_gratuity_rule() elif region == "United Arab Emirates": - from erpnext.regional.united_arab_emirates.setup import create_standard_documents - create_standard_documents() \ No newline at end of file + from erpnext.regional.united_arab_emirates.setup import create_gratuity_rule + create_gratuity_rule() \ No newline at end of file diff --git a/erpnext/payroll/doctype/gratuity/gratuity.py b/erpnext/payroll/doctype/gratuity/gratuity.py index 9f592803933..815e24d6e4b 100644 --- a/erpnext/payroll/doctype/gratuity/gratuity.py +++ b/erpnext/payroll/doctype/gratuity/gratuity.py @@ -12,7 +12,9 @@ from math import floor from frappe.utils import get_datetime class Gratuity(Document): def validate(self): - calculate_work_experience_and_amount(self.employee, self.gratuity_rule) + data = calculate_work_experience_and_amount(self.employee, self.gratuity_rule) + self.current_work_experience = data["current_work_experience"] + self.amount = data["amount"] def before_submit(self): self.status = "Unpaid" diff --git a/erpnext/payroll/doctype/gratuity/test_gratuity.py b/erpnext/payroll/doctype/gratuity/test_gratuity.py index 92c1248b73f..fb2488cf85e 100644 --- a/erpnext/payroll/doctype/gratuity/test_gratuity.py +++ b/erpnext/payroll/doctype/gratuity/test_gratuity.py @@ -3,8 +3,178 @@ # See license.txt from __future__ import unicode_literals -# import frappe +import frappe import unittest +from erpnext.hr.doctype.employee.test_employee import make_employee +from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_employee_salary_slip +from erpnext.payroll.doctype.gratuity.gratuity import get_last_salary_slip +from erpnext.regional.united_arab_emirates.setup import create_gratuity_rule +from frappe.utils import getdate, add_days, get_datetime, flt + class TestGratuity(unittest.TestCase): - pass + + def setUp(self): + frappe.db.sql("DELETE FROM `tabgratuity`") + frappe.db.sql("DELETE FROM `tabAdditional Salary` WHERE ref_doctype = 'Gratuity'") + + + def test_check_gratuity_amount_based_on_current_slab_and_additional_salary_creation(self): + employee, sal_slip = create_employee_and_get_last_salary_slip() + rule = frappe.db.exists("Gratuity Rule", "Rule Under Unlimited Contract on termination (UAE)") + if not rule: + create_gratuity_rule() + else: + rule = frappe.get_doc("Gratuity Rule", "Rule Under Unlimited Contract on termination (UAE)") + rule.applicable_earnings_component = [] + rule.append("applicable_earnings_component", { + "salary_component": "Basic Salary" + }) + rule.save() + rule.reload() + + gra = frappe.new_doc("Gratuity") + gra.employee = employee + gra.posting_date = getdate() + gra.gratuity_rule = rule.name + gra.pay_via_salary_slip = 1 + gra.salary_component = "Performance Bonus" + gra.payroll_date = getdate() + gra.save() + gra.submit() + + #work experience calculation + date_of_joining, relieving_date = frappe.db.get_value('Employee', employee, ['date_of_joining', 'relieving_date']) + employee_total_workings_days = (get_datetime(relieving_date) - get_datetime(date_of_joining)).days + + experience = employee_total_workings_days/rule.total_working_days_per_year + + gra.reload() + + from math import floor + + self.assertEqual(floor(experience), gra.current_work_experience) + + #amount Calculation 6 + component_amount = frappe.get_list("Salary Detail", + filters={ + "docstatus": 1, + 'parent': sal_slip, + "parentfield": "earnings", + 'salary_component': "Basic Salary" + }, + fields=["amount"]) + + ''' 5 - 0 fraction is 1 ''' + + gratuity_amount = component_amount[0].amount * experience + gra.reload() + + self.assertEqual(flt(gratuity_amount, 2), flt(gra.amount, 2)) + + #additional salary creation (Pay via salary slip) + self.assertTrue(frappe.db.exists("Additional Salary", {"ref_docname": gra.name})) + self.assertEqual(gra.status, "Paid") + + + + def test_check_gratuity_amount_based_on_all_previous_slabs(self): + employee, sal_slip = create_employee_and_get_last_salary_slip() + rule = frappe.db.exists("Gratuity Rule", "Rule Under Limited Contract (UAE)") + if not rule: + create_gratuity_rule() + else: + rule = frappe.get_doc("Gratuity Rule", rule) + rule.applicable_earnings_component = [] + rule = frappe.get_doc("Gratuity Rule", "Rule Under Limited Contract (UAE)") + rule.append("applicable_earnings_component", { + "salary_component": "Basic Salary" + }) + rule.save() + rule.reload() + + mof = frappe.get_doc("Mode of Payment", "Cheque") + mof.accounts = [] + mof.append("accounts", { + "company": "_Test Company", + "default_account": "_Test Bank - _TC" + }) + + mof.save() + + gra = frappe.new_doc("Gratuity") + gra.employee = employee + gra.posting_date = getdate() + gra.gratuity_rule = rule.name + gra.pay_via_salary_slip = 0 + gra.payroll_date = getdate() + gra.expense_account = "Payment Account - _TC" + gra.mode_of_payment = "Cheque" + + gra.save() + gra.submit() + + #work experience calculation + date_of_joining, relieving_date = frappe.db.get_value('Employee', employee, ['date_of_joining', 'relieving_date']) + employee_total_workings_days = (get_datetime(relieving_date) - get_datetime(date_of_joining)).days + + experience = employee_total_workings_days/rule.total_working_days_per_year + + gra.reload() + + from math import floor + + self.assertEqual(floor(experience), gra.current_work_experience) + + #amount Calculation 6 + component_amount = frappe.get_list("Salary Detail", + filters={ + "docstatus": 1, + 'parent': sal_slip, + "parentfield": "earnings", + 'salary_component': "Basic Salary" + }, + fields=["amount"]) + + + ''' range | Fraction + 0-1 | 0 + 1-5 | 0.7 + 5-0 | 1 + ''' + + + gratuity_amount = ((0 * 1) + (4 * 0.7) + (1 * 1)) * component_amount[0].amount + gra.reload() + + self.assertEqual(flt(gratuity_amount, 2), flt(gra.amount, 2)) + self.assertEqual(gra.status, "Unpaid") + + + from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry + + pay_entry = get_payment_entry("Gratuity", gra.name) + pay_entry.reference_no = "123467" + pay_entry.reference_date = getdate() + + pay_entry.save() + pay_entry.submit() + + gra.reload() + + self.assertEqual(gra.status, "Paid") + self.assertEqual(gra.paid_amount, flt(gra.amount, 2)) + +def create_employee_and_get_last_salary_slip(): + employee = make_employee("test_employee@salary.com") + frappe.db.set_value("Employee", employee, "relieving_date", getdate()) + frappe.db.set_value("Employee", employee, "date_of_joining", add_days(getdate(), - (6*365))) + if not frappe.db.exists("Salary Slip", {"employee":employee}): + salary_slip = make_employee_salary_slip("test_employee@salary.com", "Monthly") + salary_slip.submit() + salary_slip = salary_slip.name + else: + salary_slip = get_last_salary_slip(employee) + + return employee, salary_slip + diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py index a8ff3f84849..9be5239d5e1 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -21,7 +21,7 @@ def setup_company_independent_fixtures(): add_permissions() add_custom_roles_for_reports() frappe.enqueue('erpnext.regional.india.setup.add_hsn_sac_codes', now=frappe.flags.in_test) - create_standard_documents() + create_gratuity_rule() add_print_formats() def add_hsn_sac_codes(): @@ -796,7 +796,7 @@ def get_tds_details(accounts, fiscal_year): "single_threshold": 2500, "cumulative_threshold": 0}]) ] -def create_standard_documents(): +def create_gratuity_rule(): # Standard Indain Gratuity Rule diff --git a/erpnext/regional/united_arab_emirates/setup.py b/erpnext/regional/united_arab_emirates/setup.py index 1a899272f45..72d7c132042 100644 --- a/erpnext/regional/united_arab_emirates/setup.py +++ b/erpnext/regional/united_arab_emirates/setup.py @@ -11,9 +11,13 @@ from erpnext.setup.setup_wizard.operations.taxes_setup import create_sales_tax def setup(company=None, patch=True): make_custom_fields() add_print_formats() +<<<<<<< HEAD add_custom_roles_for_reports() add_permissions() create_standard_documents() +======= + create_gratuity_rule() +>>>>>>> test: gratuity if company: create_sales_tax(company) @@ -155,7 +159,8 @@ def add_permissions(): add_permission(doctype, role, 0) update_permission_property(doctype, role, 0, 'write', 1) update_permission_property(doctype, role, 0, 'create', 1) -def create_standard_documents(): + +def create_gratuity_rule(): # Standard Gratuity Rules for UAE