diff --git a/erpnext/hr/doctype/salary_component/salary_component.py b/erpnext/hr/doctype/salary_component/salary_component.py index 9108f31f9b7..beffaec21f7 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.py +++ b/erpnext/hr/doctype/salary_component/salary_component.py @@ -18,4 +18,13 @@ class SalaryComponent(Document): 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 984a78c75ff..ba8cc0235d6 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.hr.doctype.employee.employee import get_holiday_list_for_employee 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 @@ class SalarySlip(TransactionBase): 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 @@ class SalarySlip(TransactionBase): 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 bd0ec6be319..8e6c1d86ae2 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 df720c4cc6d..315368dbab6 100644 --- a/erpnext/hr/utils.py +++ b/erpnext/hr/utils.py @@ -234,3 +234,10 @@ def get_leave_period(from_date, to_date, company): 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