Merge pull request #14108 from ESS-LLP/tax_deduction
Variable tax deduction
This commit is contained in:
commit
4444430200
@ -139,6 +139,37 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "total_exemption_amount",
|
||||
"fieldtype": "Currency",
|
||||
"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,
|
||||
"label": "Total Exemption Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"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_on_submit": 0,
|
||||
@ -243,7 +274,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-05-15 16:16:46.075493",
|
||||
"modified": "2018-05-16 19:03:57.624215",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee Tax Exemption Declaration",
|
||||
|
@ -19,3 +19,6 @@ class EmployeeTaxExemptionDeclaration(Document):
|
||||
"docstatus": 1}):
|
||||
frappe.throw(_("Tax Declaration of {0} for period {1} already submitted.")\
|
||||
.format(self.employee, self.payroll_period), frappe.DocstatusTransitionError)
|
||||
self.total_exemption_amount = 0
|
||||
for item in self.declarations:
|
||||
self.total_exemption_amount += item.amount
|
||||
|
@ -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]})
|
||||
'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
|
||||
|
@ -40,6 +40,7 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -72,6 +73,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -101,6 +103,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -132,6 +135,100 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "is_tax_applicable",
|
||||
"fieldtype": "Check",
|
||||
"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,
|
||||
"label": "Is Tax Applicable",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "is_flexible_benefit",
|
||||
"fieldtype": "Check",
|
||||
"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,
|
||||
"label": "Is Flexible Benefit",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "variable_based_on_taxable_salary",
|
||||
"fieldtype": "Check",
|
||||
"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,
|
||||
"label": "Variable Based On Taxable Salary",
|
||||
"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
|
||||
},
|
||||
{
|
||||
@ -161,6 +258,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -192,6 +290,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -225,6 +324,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -258,6 +358,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -290,6 +391,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -321,6 +423,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -351,6 +454,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -383,6 +487,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -413,6 +518,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -445,6 +551,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
@ -458,7 +565,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-10-02 13:57:22.769751",
|
||||
"modified": "2018-05-16 22:42:59.974450",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Salary Detail",
|
||||
|
@ -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.name, "docstatus": 1}):
|
||||
exemption_amount = frappe.db.get_value("Employee Tax Exemption Declaration",
|
||||
{"employee": self.employee, "payroll_period": payroll_period.name, "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))
|
||||
|
@ -201,17 +201,20 @@ frappe.ui.form.on('Salary Detail', {
|
||||
callback: function(data) {
|
||||
if(data.message){
|
||||
var result = data.message;
|
||||
frappe.model.set_value(cdt, cdn, 'condition',result.condition);
|
||||
frappe.model.set_value(cdt, cdn, 'amount_based_on_formula',result.amount_based_on_formula);
|
||||
frappe.model.set_value(cdt, cdn, 'condition', result.condition);
|
||||
frappe.model.set_value(cdt, cdn, 'amount_based_on_formula', result.amount_based_on_formula);
|
||||
if(result.amount_based_on_formula == 1){
|
||||
frappe.model.set_value(cdt, cdn, 'formula',result.formula);
|
||||
frappe.model.set_value(cdt, cdn, 'formula', result.formula);
|
||||
}
|
||||
else{
|
||||
frappe.model.set_value(cdt, cdn, 'amount',result.amount);
|
||||
frappe.model.set_value(cdt, cdn, 'amount', result.amount);
|
||||
}
|
||||
frappe.model.set_value(cdt, cdn, 'statistical_component',result.statistical_component);
|
||||
frappe.model.set_value(cdt, cdn, 'depends_on_lwp',result.depends_on_lwp);
|
||||
frappe.model.set_value(cdt, cdn, 'do_not_include_in_total',result.do_not_include_in_total);
|
||||
frappe.model.set_value(cdt, cdn, 'statistical_component', result.statistical_component);
|
||||
frappe.model.set_value(cdt, cdn, 'depends_on_lwp', result.depends_on_lwp);
|
||||
frappe.model.set_value(cdt, cdn, 'do_not_include_in_total', result.do_not_include_in_total);
|
||||
frappe.model.set_value(cdt, cdn, 'variable_based_on_taxable_salary', result.variable_based_on_taxable_salary);
|
||||
frappe.model.set_value(cdt, cdn, 'is_tax_applicable', result.is_tax_applicable);
|
||||
frappe.model.set_value(cdt, cdn, 'is_flexible_benefit', result.is_flexible_benefit);
|
||||
refresh_field("earnings");
|
||||
refresh_field("deductions");
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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 pp.name, 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user