From 3ced42f302fcae2983b8b4022805b8c2d684bc14 Mon Sep 17 00:00:00 2001 From: Anurag Mishra Date: Fri, 13 Mar 2020 19:14:56 +0530 Subject: [PATCH] feat: reverse linking and multiple additonal salaries in salary slip --- .../additional_salary/additional_salary.py | 63 ++++++++++++------- .../employee_advance/employee_advance.json | 3 +- .../employee_incentive/employee_incentive.py | 32 +++------- .../leave_encashment/leave_encashment.py | 11 ++-- erpnext/hr/doctype/salary_slip/salary_slip.py | 26 ++++---- 5 files changed, 72 insertions(+), 63 deletions(-) diff --git a/erpnext/hr/doctype/additional_salary/additional_salary.py b/erpnext/hr/doctype/additional_salary/additional_salary.py index d8f7444beb..4076ffef18 100644 --- a/erpnext/hr/doctype/additional_salary/additional_salary.py +++ b/erpnext/hr/doctype/additional_salary/additional_salary.py @@ -9,6 +9,13 @@ from frappe import _ from frappe.utils import getdate, date_diff class AdditionalSalary(Document): + + def on_submit(self): + if self.ref_doctype == "Employee Advance" and self.ref_docname: + emp_adv = frappe.get_doc(self.ref_doctype, self.ref_docname) + emp_adv.return_amount = self.amount + emp_adv.save() + def before_insert(self): if frappe.db.exists("Additional Salary", {"employee": self.employee, "salary_component": self.salary_component, "amount": self.amount, "payroll_date": self.payroll_date, "company": self.company, "docstatus": 1}): @@ -49,8 +56,8 @@ class AdditionalSalary(Document): @frappe.whitelist() def get_additional_salary_component(employee, start_date, end_date, component_type): - additional_components = frappe.db.sql(""" - select name, salary_component, amount, overwrite_salary_structure_amount, deduct_full_tax_on_selected_payroll_date + additional_salaries = frappe.db.sql(""" + select name, salary_component, type, amount, overwrite_salary_structure_amount, deduct_full_tax_on_selected_payroll_date from `tabAdditional Salary` where employee=%(employee)s and docstatus = 1 @@ -60,7 +67,7 @@ def get_additional_salary_component(employee, start_date, end_date, component_ty from_date <= %(to_date)s and to_date >= %(to_date)s ) and type = %(component_type)s - order by salary_component, overwrite_salary_structure_amount + order by salary_component, overwrite_salary_structure_amount DESC """, { 'employee': employee, 'from_date': start_date, @@ -68,26 +75,38 @@ def get_additional_salary_component(employee, start_date, end_date, component_ty 'component_type': "Earning" if component_type == "earnings" else "Deduction" }, as_dict=1) - additional_components_list = [] - existing_salary_components = [] + existing_salary_components= [] + salary_components_details = {} + additional_salary_details = [] + + overwrites_components = [ele.salary_component for ele in additional_salaries if ele.overwrite_salary_structure_amount == 1] + component_fields = ["depends_on_payment_days", "salary_component_abbr", "is_tax_applicable", "variable_based_on_taxable_salary", 'type'] - for d in additional_components: - if d.salary_component in existing_salary_components: - frappe.throw(_('Multiple additional Salary is created for Salary Component {0}'.format(d.salary_component))) - struct_row = frappe._dict({'salary_component': d.salary_component}) - component = frappe.get_all("Salary Component", filters={'name': d.salary_component}, fields=component_fields) - if component: - struct_row.update(component[0]) + for d in additional_salaries: - struct_row['deduct_full_tax_on_selected_payroll_date'] = d.deduct_full_tax_on_selected_payroll_date - struct_row['is_additional_component'] = 1 - struct_row['additional_salary'] = d.name + if d.salary_component not in existing_salary_components: + component = frappe.get_all("Salary Component", filters={'name': d.salary_component}, fields=component_fields) + struct_row = frappe._dict({'salary_component': d.salary_component}) + if component: + struct_row.update(component[0]) + + struct_row['deduct_full_tax_on_selected_payroll_date'] = d.deduct_full_tax_on_selected_payroll_date + struct_row['is_additional_component'] = 1 + + salary_components_details[d.salary_component] = struct_row + + + if overwrites_components.count(d.salary_component) > 1: + frappe.throw(_("Multiple Additional Salaries with overwrite property exist for Salary Component: {0} between {1} and {2}.".format(d.salary_component, start_date, end_date)), title=_("Error")) + else: + additional_salary_details.append({ + 'name': d.name, + 'component': d.salary_component, + 'amount': d.amount, + 'type': d.type, + 'overwrite': d.overwrite_salary_structure_amount, + }) - additional_components_list.append(frappe._dict({ - 'amount': d.amount, - 'type': component[0].type, - 'struct_row': struct_row, - 'overwrite': d.overwrite_salary_structure_amount, - })) existing_salary_components.append(d.salary_component) - return additional_components_list \ No newline at end of file + + return salary_components_details, additional_salary_details \ No newline at end of file diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.json b/erpnext/hr/doctype/employee_advance/employee_advance.json index 1ab2356c8e..8c5ce42d87 100644 --- a/erpnext/hr/doctype/employee_advance/employee_advance.json +++ b/erpnext/hr/doctype/employee_advance/employee_advance.json @@ -165,6 +165,7 @@ "options": "Mode of Payment" }, { + "allow_on_submit": 1, "fieldname": "return_amount", "fieldtype": "Currency", "label": "Returned Amount", @@ -180,7 +181,7 @@ ], "is_submittable": 1, "links": [], - "modified": "2020-03-05 16:31:50.417539", + "modified": "2020-03-06 15:11:33.747535", "modified_by": "Administrator", "module": "HR", "name": "Employee Advance", diff --git a/erpnext/hr/doctype/employee_incentive/employee_incentive.py b/erpnext/hr/doctype/employee_incentive/employee_incentive.py index 1cc52e1112..44763fc077 100644 --- a/erpnext/hr/doctype/employee_incentive/employee_incentive.py +++ b/erpnext/hr/doctype/employee_incentive/employee_incentive.py @@ -9,27 +9,13 @@ from frappe.model.document import Document class EmployeeIncentive(Document): def on_submit(self): company = frappe.db.get_value('Employee', self.employee, 'company') - additional_salary = frappe.db.exists('Additional Salary', { - 'employee': self.employee, - 'ref_doctype': self.doctype, - 'ref_docname': self.name, - 'salary_component': self.salary_component, - 'payroll_date': self.payroll_date, - 'company': company, - 'docstatus': ["!=", 2] - }) - - if not additional_salary: - additional_salary = frappe.new_doc('Additional Salary') - additional_salary.employee = self.employee - additional_salary.salary_component = self.salary_component - additional_salary.amount = self.incentive_amount - additional_salary.payroll_date = self.payroll_date - additional_salary.company = company - additional_salary.ref_doctype = self.doctype - additional_salary.ref_docname = self.name - additional_salary.submit() - else: - incentive_added = frappe.db.get_value('Additional Salary', additional_salary, 'amount') + self.incentive_amount - frappe.db.set_value('Additional Salary', additional_salary, {'amount', incentive_added}) + additional_salary = frappe.new_doc('Additional Salary') + additional_salary.employee = self.employee + additional_salary.salary_component = self.salary_component + additional_salary.amount = self.incentive_amount + additional_salary.payroll_date = self.payroll_date + additional_salary.company = company + additional_salary.ref_doctype = self.doctype + additional_salary.ref_docname = self.name + additional_salary.submit() diff --git a/erpnext/hr/doctype/leave_encashment/leave_encashment.py b/erpnext/hr/doctype/leave_encashment/leave_encashment.py index ad2cc02fd7..56f2f4ca08 100644 --- a/erpnext/hr/doctype/leave_encashment/leave_encashment.py +++ b/erpnext/hr/doctype/leave_encashment/leave_encashment.py @@ -31,13 +31,16 @@ class LeaveEncashment(Document): additional_salary = frappe.new_doc("Additional Salary") additional_salary.company = frappe.get_value("Employee", self.employee, "company") additional_salary.employee = self.employee - additional_salary.salary_component = frappe.get_value("Leave Type", self.leave_type, "earning_component") + earning_component = frappe.get_value("Leave Type", self.leave_type, "earning_component") + if not earning_component: + frappe.throw(_("Please set Earning Component for Leave type: {0}.".format(self.leave_type))) + additional_salary.salary_component = earning_component additional_salary.payroll_date = self.encashment_date additional_salary.amount = self.encashment_amount + additional_salary.ref_doctype = self.doctype + additional_salary.ref_docname = self.name additional_salary.submit() - self.db_set("additional_salary", additional_salary.name) - # Set encashed leaves in Allocation frappe.db.set_value("Leave Allocation", self.leave_allocation, "total_leaves_encashed", frappe.db.get_value('Leave Allocation', self.leave_allocation, 'total_leaves_encashed') + self.encashable_days) @@ -119,4 +122,4 @@ def create_leave_encashment(leave_allocation): leave_type=allocation.leave_type, encashment_date=allocation.to_date )) - leave_encashment.insert(ignore_permissions=True) + leave_encashment.insert(ignore_permissions=True) \ No newline at end of file diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index ac55c679a6..1d19427dc4 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -74,7 +74,6 @@ class SalarySlip(TransactionBase): def on_cancel(self): self.set_status() self.update_status() - self.update_salary_slip_in_additional_salary() self.cancel_loan_repayment_entry() def on_trash(self): @@ -405,14 +404,15 @@ class SalarySlip(TransactionBase): self.update_component_row(frappe._dict(last_benefit.struct_row), amount, "earnings") def add_additional_salary_components(self, component_type): - additional_components = get_additional_salary_component(self.employee, + salary_components_details, additional_salary_details = get_additional_salary_component(self.employee, self.start_date, self.end_date, component_type) - if additional_components: - for additional_component in additional_components: - amount = additional_component.amount - overwrite = additional_component.overwrite - self.update_component_row(frappe._dict(additional_component.struct_row), amount, - component_type, overwrite=overwrite) + if salary_components_details and additional_salary_details: + for additional_salary in additional_salary_details: + additional_salary =frappe._dict(additional_salary) + amount = additional_salary.amount + overwrite = additional_salary.overwrite + self.update_component_row(frappe._dict(salary_components_details[additional_salary.component]), amount, + component_type, overwrite=overwrite, additional_salary=additional_salary.name) def add_tax_components(self, payroll_period): # Calculate variable_based_on_taxable_salary after all components updated in salary slip @@ -432,21 +432,20 @@ class SalarySlip(TransactionBase): tax_row = self.get_salary_slip_row(d) self.update_component_row(tax_row, tax_amount, "deductions") - def update_component_row(self, struct_row, amount, key, overwrite=1): + def update_component_row(self, struct_row, amount, key, overwrite=1, additional_salary = ''): component_row = None for d in self.get(key): if d.salary_component == struct_row.salary_component: component_row = d - - if not component_row: + if not component_row or (struct_row.get("is_additional_component") and not overwrite): if amount: self.append(key, { 'amount': amount, - 'additional_salary': '' if not struct_row.get("additional_salary") else struct_row.get("additional_salary"), 'default_amount': amount if not struct_row.get("is_additional_component") else 0, 'depends_on_payment_days' : struct_row.depends_on_payment_days, 'salary_component' : struct_row.salary_component, 'abbr' : struct_row.abbr, + 'additional_salary': additional_salary, 'do_not_include_in_total' : struct_row.do_not_include_in_total, 'is_tax_applicable': struct_row.is_tax_applicable, 'is_flexible_benefit': struct_row.is_flexible_benefit, @@ -458,6 +457,7 @@ class SalarySlip(TransactionBase): if struct_row.get("is_additional_component"): if overwrite: component_row.additional_amount = amount - component_row.get("default_amount", 0) + component_row.additional_salary = additional_salary else: component_row.additional_amount = amount @@ -878,4 +878,4 @@ def unlink_ref_doc_from_salary_slip(ref_no): def generate_password_for_pdf(policy_template, employee): employee = frappe.get_doc("Employee", employee) - return policy_template.format(**employee.as_dict()) + return policy_template.format(**employee.as_dict()) \ No newline at end of file