Salary Slip calc tax, except for flexi benefits
diff --git a/erpnext/hr/doctype/salary_component/salary_component.py b/erpnext/hr/doctype/salary_component/salary_component.py
index 9108f31..beffaec 100644
--- a/erpnext/hr/doctype/salary_component/salary_component.py
+++ b/erpnext/hr/doctype/salary_component/salary_component.py
@@ -18,4 +18,13 @@
self.salary_component_abbr = self.salary_component_abbr.strip()
self.salary_component_abbr = append_number_if_name_exists('Salary Component', self.salary_component_abbr,
- 'salary_component_abbr', separator='_', filters={"name": ["!=", self.name]})
\ No newline at end of file
+ 'salary_component_abbr', separator='_', filters={"name": ["!=", self.name]})
+
+ def calculate_tax(self, annual_earning):
+ taxable_amount = 0
+ for slab in self.taxable_salary_slabs:
+ 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
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py
index 984a78c..ba8cc02 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.py
@@ -13,6 +13,7 @@
from erpnext.utilities.transaction_base import TransactionBase
from frappe.utils.background_jobs import enqueue
from erpnext.hr.doctype.additional_salary_component.additional_salary_component import get_additional_salary_component
+from erpnext.hr.utils import get_payroll_period
class SalarySlip(TransactionBase):
def autoname(self):
@@ -58,6 +59,10 @@
amount = self.eval_condition_and_formula(struct_row, data)
if amount and struct_row.statistical_component == 0:
self.update_component_row(struct_row, amount, key)
+ if key=="deductions" and struct_row.variable_based_on_taxable_salary:
+ tax_row, amount = self.calculate_pro_rata_tax(struct_row.salary_component)
+ if tax_row and amount:
+ self.update_component_row(frappe._dict(tax_row), amount, key)
additional_components = get_additional_salary_component(self.employee, self.start_date, self.end_date)
if additional_components:
@@ -464,6 +469,52 @@
status = "Cancelled"
return status
+ def calculate_pro_rata_tax(self, salary_component):
+ # Calculate total tax payable earnings
+ tax_applicable_components = []
+ for earning in self._salary_structure_doc.earnings:
+ #all tax applicable earnings which are not flexi
+ if earning.is_tax_applicable and not earning.is_flexible_benefit:
+ tax_applicable_components.append(earning.salary_component)
+ total_taxable_earning = 0
+ for earning in self.earnings:
+ if earning.salary_component in tax_applicable_components:
+ total_taxable_earning += earning.amount
+
+ # Get payroll period, prorata frequency
+ days = date_diff(self.end_date, self.start_date) + 1
+ payroll_period = get_payroll_period(self.start_date, self.end_date, self.company)
+ if not payroll_period:
+ frappe.throw(_("Start and end dates not in a valid Payroll Period"))
+ total_days = date_diff(payroll_period.end_date, payroll_period.start_date) + 1
+ prorata_frequency = flt(total_days)/flt(days)
+ annual_earning = total_taxable_earning * prorata_frequency
+
+ # Calculate total exemption declaration
+ exemption_amount = 0
+ if frappe.db.exists("Employee Tax Exemption Declaration", {"employee": self.employee,
+ "payroll_period": payroll_period.parent, "docstatus": 1}):
+ exemption_amount = frappe.db.get_value("Employee Tax Exemption Declaration",
+ {"employee": self.employee, "payroll_period": "2018", "docstatus": 1}, #fix period
+ "total_exemption_amount")
+ annual_earning = annual_earning - exemption_amount
+
+ # Get tax calc by component
+ component = frappe.get_doc("Salary Component", salary_component)
+ annual_tax = component.calculate_tax(annual_earning)
+
+ # Calc prorata tax
+ pro_rata_tax = annual_tax/prorata_frequency
+
+ # Data for update_component_row
+ struct_row = {}
+ struct_row['depends_on_lwp'] = 0
+ struct_row['salary_component'] = component.name
+ struct_row['abbr'] = component.salary_component_abbr
+ struct_row['do_not_include_in_total'] = 0
+
+ return struct_row, pro_rata_tax
+
def unlink_ref_doc_from_salary_slip(ref_no):
linked_ss = frappe.db.sql_list("""select name from `tabSalary Slip`
where journal_entry=%s and docstatus < 2""", (ref_no))
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 bd0ec6b..8e6c1d8 100644
--- a/erpnext/hr/doctype/taxable_salary_slab/taxable_salary_slab.json
+++ b/erpnext/hr/doctype/taxable_salary_slab/taxable_salary_slab.json
@@ -50,7 +50,7 @@
"collapsible": 0,
"columns": 0,
"fieldname": "to_amount",
- "fieldtype": "Data",
+ "fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -147,7 +147,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2018-04-13 20:09:36.675987",
+ "modified": "2018-05-16 18:18:23.802576",
"modified_by": "Administrator",
"module": "HR",
"name": "Taxable Salary Slab",
diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py
index df720c4..315368d 100644
--- a/erpnext/hr/utils.py
+++ b/erpnext/hr/utils.py
@@ -234,3 +234,10 @@
if leave_period:
return leave_period
+
+def get_payroll_period(from_date, to_date, company):
+ payroll_period = frappe.db.sql("""select pd.parent, pd.start_date, pd.end_date from
+ `tabPayroll Period Date` pd join `tabPayroll Period` pp on
+ pd.parent=pp.name where pd.start_date<=%s and pd.end_date>= %s
+ and pp.company=%s""", (from_date, to_date, company), as_dict=1)
+ return payroll_period[0] if payroll_period else None