From 15613e46ad0264b46e6c098baf5c3e2dcb2bd7a5 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Tue, 15 May 2018 18:48:44 +0530 Subject: [PATCH] Salary Copmonent - Defualt flexible componnent --- .../employee_benefit_application.py | 50 ++++++- .../salary_component/salary_component.json | 133 +++++++++--------- .../salary_component/salary_component.py | 17 ++- erpnext/hr/doctype/salary_slip/salary_slip.py | 7 + 4 files changed, 138 insertions(+), 69 deletions(-) diff --git a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py index 33ad75846f..c9c2685a90 100644 --- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py +++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py @@ -5,8 +5,9 @@ from __future__ import unicode_literals import frappe from frappe import _ -from frappe.utils import nowdate +from frappe.utils import nowdate, date_diff, getdate from frappe.model.document import Document +from erpnext.hr.doctype.payroll_period.payroll_period import get_payroll_period_days class EmployeeBenefitApplication(Document): def validate(self): @@ -71,3 +72,50 @@ def get_assigned_salary_sturecture(employee, _date): }) if salary_structure: return salary_structure + +def get_employee_benefit_application(salary_slip): + employee_benefits = frappe.db.sql(""" + select name from `tabEmployee Benefit Application` + where employee=%(employee)s + and docstatus = 1 + and (date between %(start_date)s and %(end_date)s) + """, { + 'employee': salary_slip.employee, + 'start_date': salary_slip.start_date, + 'end_date': salary_slip.end_date + }) + + if employee_benefits: + for employee_benefit in employee_benefits: + employee_benefit_obj = frappe.get_doc("Employee Benefit Application", employee_benefit[0]) + return get_components(employee_benefit_obj, salary_slip) + +def get_components(employee_benefit_application, salary_slip): + salary_components_array = [] + payroll_period_days = get_payroll_period_days(salary_slip.start_date, salary_slip.end_date, salary_slip.company) + for employee_benefit in employee_benefit_application.employee_benefits: + if employee_benefit.is_pro_rata_applicable == 1: + struct_row = {} + salary_components_dict = {} + salary_component = frappe.get_doc("Salary Component", employee_benefit.earning_component) + amount = get_amount(payroll_period_days, salary_slip.start_date, salary_slip.end_date, employee_benefit.amount) + struct_row['depends_on_lwp'] = salary_component.depends_on_lwp + struct_row['salary_component'] = salary_component.name + struct_row['abbr'] = salary_component.salary_component_abbr + struct_row['do_not_include_in_total'] = salary_component.do_not_include_in_total + salary_components_dict['amount'] = amount + salary_components_dict['struct_row'] = struct_row + salary_components_array.append(salary_components_dict) + + if len(salary_components_array) > 0: + return salary_components_array + return False + +def get_amount(payroll_period_days, start_date, end_date, amount): + salary_slip_days = date_diff(getdate(end_date), getdate(start_date)) + 1 + amount_per_day = amount / payroll_period_days + total_amount = amount_per_day * salary_slip_days + if total_amount > amount: + return amount + else: + return total_amount diff --git a/erpnext/hr/doctype/salary_component/salary_component.json b/erpnext/hr/doctype/salary_component/salary_component.json index cf85af4a76..6764e0ca92 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.json +++ b/erpnext/hr/doctype/salary_component/salary_component.json @@ -108,70 +108,6 @@ "translatable": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.type==\"Earning\"", - "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, - "default": "1", - "fieldname": "is_payable", - "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 Payable", - "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, @@ -366,6 +302,38 @@ "collapsible": 0, "columns": 0, "depends_on": "is_flexible_benefit", + "fieldname": "is_group", + "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 Group", + "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, + "depends_on": "eval:doc.is_flexible_benefit && !doc.is_group && !doc.flexi_default", "fieldname": "earning_component_group", "fieldtype": "Link", "hidden": 0, @@ -454,6 +422,38 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.is_flexible_benefit && doc.is_pro_rata_applicable", + "fieldname": "flexi_default", + "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": "Default Flexible Component", + "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, @@ -618,7 +618,6 @@ "bold": 0, "collapsible": 0, "columns": 0, - "depends_on": "is_payable", "fieldname": "section_break_5", "fieldtype": "Section Break", "hidden": 0, @@ -1002,7 +1001,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-05-16 12:15:43.117948", + "modified": "2018-05-16 12:27:03.005070", "modified_by": "Administrator", "module": "HR", "name": "Salary Component", @@ -1037,4 +1036,4 @@ "sort_order": "DESC", "track_changes": 0, "track_seen": 0 -} \ No newline at end of file +} diff --git a/erpnext/hr/doctype/salary_component/salary_component.py b/erpnext/hr/doctype/salary_component/salary_component.py index 9108f31f9b..be0bf17a09 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.py +++ b/erpnext/hr/doctype/salary_component/salary_component.py @@ -4,12 +4,27 @@ from __future__ import unicode_literals import frappe +from frappe import _ from frappe.model.document import Document from frappe.model.naming import append_number_if_name_exists class SalaryComponent(Document): def validate(self): self.validate_abbr() + self.validate_flexi_defualt() + + def validate_flexi_defualt(self): + if self.is_flexible_benefit and self.is_pro_rata_applicable and self.flexi_defualt: + salary_component = frappe.db.exists( + 'Salary Component', + { + 'is_flexible_benefit': 1, + 'is_pro_rata_applicable': 1, + 'flexi_defualt': 1 + } + ) + if salary_component and salary_component != self.name: + frappe.throw(_("{0} is already marked as default flexible component").format(salary_component)) def validate_abbr(self): if not self.salary_component_abbr: @@ -18,4 +33,4 @@ 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]}) diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index 984a78c75f..b7d26f2098 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.doctype.employee_benefit_application.employee_benefit_application import get_employee_benefit_application class SalarySlip(TransactionBase): def autoname(self): @@ -65,6 +66,12 @@ class SalarySlip(TransactionBase): additional_component = frappe._dict(additional_component) self.update_component_row(frappe._dict(additional_component.struct_row), additional_component.amount, "earnings") + employee_benefits = get_employee_benefit_application(self) + if employee_benefits: + for employee_benefit in employee_benefits: + benefit_component = frappe._dict(employee_benefit) + self.update_component_row(frappe._dict(benefit_component.struct_row), benefit_component.amount, "earnings") + def update_component_row(self, struct_row, amount, key): component_row = None for d in self.get(key):