From 05d00397d091a693e994f6e4c5ed18b672dd40a9 Mon Sep 17 00:00:00 2001 From: Ranjith Kurungadam Date: Wed, 20 Jun 2018 12:33:02 +0530 Subject: [PATCH] Update tax calculation (#14564) * Tax Slab remove to_amt mandatory, condition data type Code * Salary Slip - consider condition in tax slab * Payroll Period - help text for tax slab condition --- erpnext/hr/doctype/salary_slip/salary_slip.py | 28 ++++++- .../taxable_salary_slab.json | 75 ++++++++++++++++++- 2 files changed, 98 insertions(+), 5 deletions(-) diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index 94f80e11da..4c36fe770e 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals import frappe, erpnext +import datetime from frappe.utils import add_days, cint, cstr, flt, getdate, rounded, date_diff, money_in_words from frappe.model.naming import make_autoname @@ -699,16 +700,41 @@ class SalarySlip(TransactionBase): return struct_row, tax_amount def calculate_tax_by_tax_slab(self, payroll_period, annual_earning): - # TODO consider condition in tax slab payroll_period_obj = frappe.get_doc("Payroll Period", payroll_period) + data = self.get_data_for_eval() taxable_amount = 0 for slab in payroll_period_obj.taxable_salary_slabs: + if slab.condition and not self.eval_tax_slab_condition(slab.condition, data): + continue + if not slab.to_amount and annual_earning > slab.from_amount: + taxable_amount += (annual_earning - slab.from_amount) * slab.percent_deduction *.01 + continue if annual_earning > slab.from_amount and annual_earning < slab.to_amount: taxable_amount += (annual_earning - slab.from_amount) * slab.percent_deduction *.01 elif annual_earning > slab.from_amount and annual_earning > slab.to_amount: taxable_amount += (slab.to_amount - slab.from_amount) * slab.percent_deduction * .01 return taxable_amount + def eval_tax_slab_condition(self, condition, data): + whitelisted_globals = { + "int": int, + "float": float, + "long": int, + "round": round, + "date": datetime.date + } + try: + condition = condition.strip() + if condition: + return frappe.safe_eval(condition, whitelisted_globals, data) + except NameError as err: + frappe.throw(_("Name error: {0}".format(err))) + except SyntaxError as err: + frappe.throw(_("Syntax error in condition: {0}".format(err))) + except Exception as e: + frappe.throw(_("Error in formula or condition: {0}".format(e))) + raise + def get_period_factor(self, period_start, period_end, start_date=None, end_date=None): payroll_days = date_diff(period_end, period_start) + 1 if start_date and end_date: diff --git a/erpnext/hr/doctype/taxable_salary_slab/taxable_salary_slab.json b/erpnext/hr/doctype/taxable_salary_slab/taxable_salary_slab.json index 8e6c1d86ae..41aa97eb8f 100644 --- a/erpnext/hr/doctype/taxable_salary_slab/taxable_salary_slab.json +++ b/erpnext/hr/doctype/taxable_salary_slab/taxable_salary_slab.json @@ -14,6 +14,7 @@ "fields": [ { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -45,6 +46,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -68,7 +70,7 @@ "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, - "reqd": 1, + "reqd": 0, "search_index": 0, "set_only_once": 0, "translatable": 0, @@ -76,12 +78,13 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, "fieldname": "percent_deduction", - "fieldtype": "Float", + "fieldtype": "Percent", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -107,12 +110,13 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, "fieldname": "condition", - "fieldtype": "Data", + "fieldtype": "Code", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -135,6 +139,69 @@ "set_only_once": 0, "translatable": 0, "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_5", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "html_6", + "fieldtype": "HTML", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "options": "

Condition Examples

\n
    \n
  1. Applying tax if employee born between 31-12-1937 and 01-01-1958 (Employees aged 60 to 80)
    \nCondition: date_of_birth>date(1937, 12, 31) and date_of_birth<date(1958, 01, 01)

  2. Applying tax by employee gender
    \nCondition: gender=\"Male\"

  3. \n
  4. Applying tax by Salary Component
    \nCondition: base > 10000
", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 } ], "has_web_view": 0, @@ -147,7 +214,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2018-05-16 18:18:23.802576", + "modified": "2018-06-19 10:10:23.732132", "modified_by": "Administrator", "module": "HR", "name": "Taxable Salary Slab",