From ce88bdf00574a3886d97bdbfc2ab7a80a885aea5 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Thu, 17 May 2018 17:08:43 +0530 Subject: [PATCH 01/29] Employee Benefit Claim - Validation Updated - Code refactor --- .../employee_benefit_application.js | 8 +- .../employee_benefit_application.py | 21 +++--- .../employee_benefit_claim.py | 75 ++++++++++++++++--- .../salary_component/salary_component.js | 2 +- erpnext/hr/doctype/salary_slip/salary_slip.py | 67 +++++++++-------- 5 files changed, 115 insertions(+), 58 deletions(-) diff --git a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js index 7859a470cc..7662a94037 100644 --- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js +++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js @@ -32,12 +32,12 @@ frappe.ui.form.on('Employee Benefit Application', { }); frappe.ui.form.on("Employee Benefit Application Detail",{ - amount: function(frm, cdt, cdn) { - calculate_all(frm.doc, cdt, cdn); + amount: function(frm) { + calculate_all(frm.doc); } }); -var calculate_all = function(doc, dt, dn) { +var calculate_all = function(doc) { var tbl = doc.employee_benefits || []; var pro_rata_dispensed_amount = 0; var total_amount = 0; @@ -46,7 +46,7 @@ var calculate_all = function(doc, dt, dn) { total_amount += flt(tbl[i].amount); } if(tbl[i].is_pro_rata_applicable == 1){ - pro_rata_dispensed_amount += flt(tbl[i].amount) + pro_rata_dispensed_amount += flt(tbl[i].amount); } } doc.total_amount = total_amount; 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 8e59bf556b..b5da98ef5f 100644 --- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py +++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py @@ -78,32 +78,32 @@ def get_assigned_salary_sturecture(employee, _date): if salary_structure: return salary_structure -def get_employee_benefit_application(salary_slip): +def get_employee_benefit_application(employee, start_date, end_date): 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 + 'employee': employee, + 'start_date': start_date, + 'end_date': 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) + return get_benefit_components(employee_benefit_obj, employee, start_date, end_date) -def get_components(employee_benefit_application, salary_slip): +def get_benefit_components(employee_benefit_application, employee, start_date, end_date): salary_components_array = [] group_component_amount = {} - payroll_period_days = get_payroll_period_days(salary_slip.start_date, salary_slip.end_date, salary_slip.company) + payroll_period_days = get_payroll_period_days(start_date, end_date, frappe.db.get_value("Employee", employee, "company")) for employee_benefit in employee_benefit_application.employee_benefits: if employee_benefit.is_pro_rata_applicable == 1: struct_row = {} salary_components_dict = {} - amount = get_amount(payroll_period_days, salary_slip.start_date, salary_slip.end_date, employee_benefit.amount) + amount = get_amount(payroll_period_days, start_date, end_date, employee_benefit.amount) sc = frappe.get_doc("Salary Component", employee_benefit.earning_component) salary_component = sc if sc.earning_component_group and not sc.is_group and not sc.flexi_default: @@ -129,7 +129,4 @@ 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 + return total_amount diff --git a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py index 39b3540e06..69797ba40e 100644 --- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py +++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py @@ -7,29 +7,86 @@ import frappe from frappe import _ from frappe.model.document import Document from erpnext.hr.doctype.employee_benefit_application.employee_benefit_application import get_max_benefits +from erpnext.hr.utils import get_payroll_period class EmployeeBenefitClaim(Document): def validate(self): - if not self.is_pro_rata_applicable: - self.validate_max_benefit_for_sal_struct() - # TODO: Validate all cases - - def validate_max_benefit_for_sal_struct(self): max_benefits = get_max_benefits(self.employee, self.claim_date) + self.validate_max_benefit_for_component() + self.validate_max_benefit_for_sal_struct(max_benefits) + payroll_period = get_payroll_period(self.claim_date, self.claim_date, frappe.db.get_value("Employee", self.employee, "company")) + self.validate_benefit_claim_amount(max_benefits, payroll_period) + if not self.is_pro_rata_applicable: + self.validate_non_pro_rata_benefit_claim(max_benefits, payroll_period) + + def validate_benefit_claim_amount(self, max_benefits, payroll_period): + claimed_amount = self.claimed_amount + claimed_amount += self.get_previous_claimed_amount(payroll_period) + if max_benefits < claimed_amount: + frappe.throw(_("Maximum benefit of employee {0} exceeds {1} by the sum {2} of previous claimed\ + amount").format(self.employee, max_benefits, claimed_amount-max_benefits)) + + def validate_max_benefit_for_sal_struct(self, max_benefits): if self.claimed_amount > max_benefits: frappe.throw(_("Maximum benefit amount of employee {0} exceeds {1}").format(self.employee, max_benefits)) + def validate_max_benefit_for_component(self): + if self.claimed_amount > self.max_amount_eligible: + frappe.throw(_("Maximum amount eligible for the component {0} exceeds {1}").format(self.earning_component, self.max_amount_eligible)) -def get_employee_benefit_claim(salary_slip): + def validate_non_pro_rata_benefit_claim(self, max_benefits, payroll_period): + claimed_amount = self.claimed_amount + pro_rata_amount = self.get_pro_rata_amount_in_application(payroll_period.name) + claimed_amount += self.get_previous_claimed_amount(payroll_period, True) + if max_benefits < pro_rata_amount + claimed_amount: + frappe.throw(_("Maximum benefit of employee {0} exceeds {1} by the sum {2} of benefit application pro-rata component\ + amount and previous claimed amount").format(self.employee, max_benefits, pro_rata_amount+claimed_amount-max_benefits)) + + def get_pro_rata_amount_in_application(self, payroll_period): + pro_rata_dispensed_amount = 0 + application = frappe.db.exists( + "Employee Benefit Application", + { + 'employee': self.employee, + 'payroll_period': payroll_period, + 'docstatus': 1 + } + ) + if application: + pro_rata_dispensed_amount = frappe.db.get_value("Employee Benefit Application", application, "pro_rata_dispensed_amount") + return pro_rata_dispensed_amount + + def get_previous_claimed_amount(self, payroll_period, non_pro_rata=False): + total_claimed_amount = 0 + query = """ + select sum(claimed_amount) as 'total_amount' + from `tabEmployee Benefit Claim` + where employee=%(employee)s + and docstatus = 1 + and (claim_date between %(start_date)s and %(end_date)s) + """ + if non_pro_rata: + query += "and is_pro_rata_applicable = 0" + + sum_of_claimed_amount = frappe.db.sql(query, { + 'employee': self.employee, + 'start_date': payroll_period.start_date, + 'end_date': payroll_period.end_date + }, as_dict=True) + if sum_of_claimed_amount: + total_claimed_amount = sum_of_claimed_amount[0].total_amount + return total_claimed_amount + +def get_employee_benefit_claim(employee, start_date, end_date): employee_benefits = frappe.db.sql(""" select name from `tabEmployee Benefit Claim` where employee=%(employee)s and docstatus = 1 and is_pro_rata_applicable = 0 and (claim_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 + 'employee': employee, + 'start_date': start_date, + 'end_date': end_date }) if employee_benefits: diff --git a/erpnext/hr/doctype/salary_component/salary_component.js b/erpnext/hr/doctype/salary_component/salary_component.js index e58a05e754..09d16f1cf7 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.js +++ b/erpnext/hr/doctype/salary_component/salary_component.js @@ -14,7 +14,7 @@ frappe.ui.form.on('Salary Component', { } }; }); - frm.set_query("earning_component_group", function(frm) { + frm.set_query("earning_component_group", function() { return { filters: { "is_group": 1, diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index 87511b6e9d..6651e0561f 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -13,10 +13,10 @@ 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 from erpnext.hr.doctype.employee_benefit_application.employee_benefit_application import get_employee_benefit_application, get_amount from erpnext.hr.doctype.payroll_period.payroll_period import get_payroll_period_days from erpnext.hr.doctype.employee_benefit_claim.employee_benefit_claim import get_employee_benefit_claim -from erpnext.hr.utils import get_payroll_period class SalarySlip(TransactionBase): def autoname(self): @@ -71,46 +71,49 @@ class SalarySlip(TransactionBase): if additional_components: for additional_component in additional_components: additional_component = frappe._dict(additional_component) - amount = self.update_amount_for_other_component(frappe._dict(additional_component.struct_row).salary_component, additional_component.amount) + amount = additional_component.amount + self.get_amount_from_exisiting_component(frappe._dict(additional_component.struct_row).salary_component) self.update_component_row(frappe._dict(additional_component.struct_row), amount, "earnings") max_benefits = self._salary_structure_doc.get("max_benefits") if max_benefits > 0: - employee_benefits = get_employee_benefit_application(self) - if employee_benefits: - for employee_benefit in employee_benefits: - benefit_component = frappe._dict(employee_benefit) - amount = self.update_amount_for_other_component(frappe._dict(benefit_component.struct_row).salary_component, benefit_component.amount) - self.update_component_row(frappe._dict(benefit_component.struct_row), amount, "earnings") + self.add_employee_benefits(max_benefits) + + def add_employee_benefits(self, max_benefits): + employee_benefits = get_employee_benefit_application(self.employee, self.start_date, self.end_date) + if employee_benefits: + for employee_benefit in employee_benefits: + benefit_component = frappe._dict(employee_benefit) + amount = benefit_component.amount + self.get_amount_from_exisiting_component(frappe._dict(benefit_component.struct_row).salary_component) + self.update_component_row(frappe._dict(benefit_component.struct_row), amount, "earnings") + else: + default_flexi_compenent = frappe.db.exists( + 'Salary Component', + { + 'is_flexible_benefit': 1, + 'is_pro_rata_applicable': 1, + 'flexi_default': 1 + } + ) + if default_flexi_compenent: + flexi_struct_row = self.create_flexi_struct_row(default_flexi_compenent) + payroll_period_days = get_payroll_period_days(self.start_date, self.end_date, self.company) + amount = get_amount(payroll_period_days, self.start_date, self.end_date, max_benefits) + amount += self.get_amount_from_exisiting_component(default_flexi_compenent) + self.update_component_row(flexi_struct_row, amount, "earnings") else: - default_flexi_compenent = frappe.db.exists( - 'Salary Component', - { - 'is_flexible_benefit': 1, - 'is_pro_rata_applicable': 1, - 'flexi_default': 1 - } - ) - if default_flexi_compenent: - flexi_struct_row = self.create_flexi_struct_row(default_flexi_compenent) - payroll_period_days = get_payroll_period_days(self.start_date, self.end_date, self.company) - amount = self.update_amount_for_other_component(default_flexi_compenent, get_amount(payroll_period_days, self.start_date, self.end_date, max_benefits)) - self.update_component_row(flexi_struct_row, amount, "earnings") - else: - frappe.throw(_("Configure default flexible benefit salary component for apply pro-rata benefit")) + frappe.throw(_("Configure default flexible benefit salary component to apply pro-rata benefit")) - benefit_claims = get_employee_benefit_claim(self) - if benefit_claims: - for benefit_claim in benefit_claims: - benefit_component = frappe._dict(benefit_claim) - amount = self.update_amount_for_other_component(frappe._dict(benefit_component.struct_row).salary_component, benefit_component.amount) - self.update_component_row(frappe._dict(benefit_component.struct_row), amount, "earnings") + benefit_claims = get_employee_benefit_claim(self.employee, self.start_date, self.end_date) + if benefit_claims: + for benefit_claim in benefit_claims: + benefit_component = frappe._dict(benefit_claim) + amount = benefit_component.amount + self.get_amount_from_exisiting_component(frappe._dict(benefit_component.struct_row).salary_component) + self.update_component_row(frappe._dict(benefit_component.struct_row), amount, "earnings") - def update_amount_for_other_component(self, salary_component, new_amount): - amount = new_amount + def get_amount_from_exisiting_component(self, salary_component): + amount = 0 for d in self.get("earnings"): if d.salary_component == salary_component: - d.amount += new_amount amount = d.amount return amount From da24722beb662014283934f4fcf73e068c7f4455 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Fri, 18 May 2018 12:58:59 +0530 Subject: [PATCH 02/29] Employee Benefit Claim - filter for earning component --- .../employee_benefit_claim.js | 12 ++--- .../employee_benefit_claim.py | 46 +++++++++++++++++++ 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.js b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.js index 64fde03763..cb6da29d03 100644 --- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.js +++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.js @@ -5,12 +5,12 @@ frappe.ui.form.on('Employee Benefit Claim', { setup: function(frm) { frm.set_query("earning_component", function() { return { - filters: { - type: "Earning", - is_flexible_benefit: true, - disabled: false - } - }; + query : "erpnext.hr.doctype.employee_benefit_claim.employee_benefit_claim.get_earning_components_for_claim", + filters: {claim_date: frm.doc.claim_date, employee: frm.doc.employee} + }; }); + }, + employee: function(frm) { + frm.set_value("earning_component", null); } }); diff --git a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py index 69797ba40e..b1dbcaa5ad 100644 --- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py +++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py @@ -8,6 +8,7 @@ from frappe import _ from frappe.model.document import Document from erpnext.hr.doctype.employee_benefit_application.employee_benefit_application import get_max_benefits from erpnext.hr.utils import get_payroll_period +from frappe.desk.reportview import get_match_cond class EmployeeBenefitClaim(Document): def validate(self): @@ -120,3 +121,48 @@ def get_employee_benefit_claim(employee, start_date, end_date): if len(salary_components_array) > 0: return salary_components_array return False + +def get_earning_components_for_claim(doctype, txt, searchfield, start, page_len, filters): + if len(filters) < 2: + return {} + employee = filters['employee'] + claim_date = filters['claim_date'] + + payroll_period = get_payroll_period(claim_date, claim_date, frappe.db.get_value("Employee", employee, "company")) + application = frappe.db.exists( + "Employee Benefit Application", + { + 'employee': employee, + 'payroll_period': payroll_period.name, + 'docstatus': 1 + } + ) + earning_components = get_earning_components_from_application(doctype, application, start, page_len) + + if not earning_components: + earning_components = get_all_pro_rata_earning_components(doctype, start, page_len) + return earning_components + +def get_earning_components_from_application(doctype, parent, start, page_len): + query = """select earning_component from `tabEmployee Benefit Application Detail` where parent = '{parent}' + order by name""" + + return frappe.db.sql(query.format(**{ + "parent": parent, + "mcond": get_match_cond(doctype) + }), { + 'start': start, + 'page_len': page_len + }) + +def get_all_pro_rata_earning_components(doctype, start, page_len): + return frappe.db.sql(""" + select name from `tabSalary Component` + where is_flexible_benefit = 1 and is_pro_rata_applicable = 1 + and type = 'Earning' and disabled = 0 + """.format(**{ + "mcond": get_match_cond(doctype) + }), { + 'start': start, + 'page_len': page_len + }) From 334bd189a735540a965ef91059e6d8d37c8c4bc2 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Fri, 18 May 2018 14:58:52 +0530 Subject: [PATCH 03/29] Employee Benefit Application - filter updated - earning component --- .../employee_benefit_application.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js index 7662a94037..956c1fb402 100644 --- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js +++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js @@ -8,6 +8,8 @@ frappe.ui.form.on('Employee Benefit Application', { filters: { type: "Earning", is_flexible_benefit: true, + is_group: false, + flexi_default: false, disabled: false } }; From f647aa15afeabb899c3a41d96f6ece60ceda4347 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Fri, 18 May 2018 15:18:27 +0530 Subject: [PATCH 04/29] Salary Component - fields - refactor fields behaviour --- .../salary_component/salary_component.js | 27 +++++ .../salary_component/salary_component.json | 104 +++++++++++++++++- 2 files changed, 129 insertions(+), 2 deletions(-) diff --git a/erpnext/hr/doctype/salary_component/salary_component.js b/erpnext/hr/doctype/salary_component/salary_component.js index 09d16f1cf7..3d112aa4aa 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.js +++ b/erpnext/hr/doctype/salary_component/salary_component.js @@ -22,5 +22,32 @@ frappe.ui.form.on('Salary Component', { } }; }); + }, + is_flexible_benefit: function(frm) { + if(frm.doc.is_flexible_benefit){ + set_value_for_condition_and_formula(frm); + } + }, + type: function(frm) { + if(frm.doc.type=="Earning"){ + frm.set_value("variable_based_on_taxable_salary", 0); + } + if(frm.doc.type=="Deduction"){ + frm.set_value("is_flexible_benefit", 0); + } + }, + variable_based_on_taxable_salary: function(frm) { + if(frm.doc.variable_based_on_taxable_salary){ + set_value_for_condition_and_formula(frm); + } } }); + +var set_value_for_condition_and_formula = function(frm) { + frm.set_value("formula", null); + frm.set_value("condition", null); + frm.set_value("amount_based_on_formula", 0); + frm.set_value("statistical_component", 0); + frm.set_value("do_not_include_in_total", 0); + frm.set_value("depends_on_lwp", 0); +} diff --git a/erpnext/hr/doctype/salary_component/salary_component.json b/erpnext/hr/doctype/salary_component/salary_component.json index 6764e0ca92..1751a87af7 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.json +++ b/erpnext/hr/doctype/salary_component/salary_component.json @@ -108,6 +108,102 @@ "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_additional_component", + "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 Additional 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, + "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, @@ -492,6 +588,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "depends_on": "is_flexible_benefit", "fieldname": "create_separate_payment_entry_against_benefit_claim", "fieldtype": "Check", "hidden": 0, @@ -618,6 +715,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "depends_on": "eval:doc.is_payable == 1", "fieldname": "section_break_5", "fieldtype": "Section Break", "hidden": 0, @@ -680,7 +778,9 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 1, + "collapsible_depends_on": "", "columns": 0, + "depends_on": "eval:doc.is_flexible_benefit != 1 && doc.variable_based_on_taxable_salary != 1", "fieldname": "condition_and_formula", "fieldtype": "Section Break", "hidden": 0, @@ -1001,7 +1101,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-05-16 12:27:03.005070", + "modified": "2018-05-18 15:12:38.202265", "modified_by": "Administrator", "module": "HR", "name": "Salary Component", @@ -1036,4 +1136,4 @@ "sort_order": "DESC", "track_changes": 0, "track_seen": 0 -} +} \ No newline at end of file From 0493c22f3c111cafad6d5b5e2f1c2b30d7b39462 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Fri, 18 May 2018 15:19:13 +0530 Subject: [PATCH 05/29] Additional Salary Component - filter updated - salary_component --- .../additional_salary_component/additional_salary_component.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/additional_salary_component/additional_salary_component.js b/erpnext/hr/doctype/additional_salary_component/additional_salary_component.js index 13ed239b36..5596dd0cb4 100644 --- a/erpnext/hr/doctype/additional_salary_component/additional_salary_component.js +++ b/erpnext/hr/doctype/additional_salary_component/additional_salary_component.js @@ -6,7 +6,8 @@ frappe.ui.form.on('Additional Salary Component', { frm.set_query("salary_component", function() { return { filters: { - type: "earning" + type: "earning", + is_additional_component: true } }; }); From 1248f6a752317443cd4775b1a42340736f51e03e Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Fri, 18 May 2018 15:27:48 +0530 Subject: [PATCH 06/29] Codacy fix --- .../doctype/employee_benefit_claim/employee_benefit_claim.js | 4 ++-- erpnext/hr/doctype/salary_component/salary_component.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.js b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.js index cb6da29d03..9870ee4873 100644 --- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.js +++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.js @@ -5,9 +5,9 @@ frappe.ui.form.on('Employee Benefit Claim', { setup: function(frm) { frm.set_query("earning_component", function() { return { - query : "erpnext.hr.doctype.employee_benefit_claim.employee_benefit_claim.get_earning_components_for_claim", + query : "erpnext.hr.doctype.employee_benefit_claim.employee_benefit_claim.get_earning_components_for_claim", filters: {claim_date: frm.doc.claim_date, employee: frm.doc.employee} - }; + }; }); }, employee: function(frm) { diff --git a/erpnext/hr/doctype/salary_component/salary_component.js b/erpnext/hr/doctype/salary_component/salary_component.js index 3d112aa4aa..95242749dd 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.js +++ b/erpnext/hr/doctype/salary_component/salary_component.js @@ -50,4 +50,4 @@ var set_value_for_condition_and_formula = function(frm) { frm.set_value("statistical_component", 0); frm.set_value("do_not_include_in_total", 0); frm.set_value("depends_on_lwp", 0); -} +}; From 77a91f0d01f4a53aff9bca1cbf3c859af7dc73a0 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Fri, 18 May 2018 15:46:55 +0530 Subject: [PATCH 07/29] Salary Component - account mandatory for separate payment entry --- erpnext/hr/doctype/salary_component/salary_component.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/erpnext/hr/doctype/salary_component/salary_component.js b/erpnext/hr/doctype/salary_component/salary_component.js index 95242749dd..0b8bd12b9c 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.js +++ b/erpnext/hr/doctype/salary_component/salary_component.js @@ -40,6 +40,14 @@ frappe.ui.form.on('Salary Component', { if(frm.doc.variable_based_on_taxable_salary){ set_value_for_condition_and_formula(frm); } + }, + create_separate_payment_entry_against_benefit_claim: function(frm) { + if(frm.doc.create_separate_payment_entry_against_benefit_claim){ + frm.set_df_property("accounts", "reqd", 1); + } + else{ + frm.set_df_property("accounts", "reqd", 0); + } } }); From 43e191289cde9d18cb21ed21ad5e6f0515f1d630 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Tue, 22 May 2018 11:39:04 +0530 Subject: [PATCH 08/29] Employee Benefit Application - earning component filter by salary structure flexi component --- .../employee_benefit_application.js | 35 +++++++++---------- .../employee_benefit_application.py | 23 ++++++++++++ 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js index 956c1fb402..d38af3cb57 100644 --- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js +++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js @@ -5,31 +5,28 @@ frappe.ui.form.on('Employee Benefit Application', { setup: function(frm) { frm.set_query("earning_component", "employee_benefits", function() { return { - filters: { - type: "Earning", - is_flexible_benefit: true, - is_group: false, - flexi_default: false, - disabled: false - } + query : "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_earning_components", + filters: {date: frm.doc.date, employee: frm.doc.employee} }; }); }, employee: function(frm) { - frappe.call({ - method: "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_max_benefits", - args:{ - employee: frm.doc.employee, - on_date: frm.doc.date - }, - callback: function (data) { - if(!data.exc){ - if(data.message){ - frm.set_value("max_benefits", data.message); + if(frm.doc.employee && frm.doc.date){ + frappe.call({ + method: "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_max_benefits", + args:{ + employee: frm.doc.employee, + on_date: frm.doc.date + }, + callback: function (data) { + if(!data.exc){ + if(data.message){ + frm.set_value("max_benefits", data.message); + } } } - } - }); + }); + } } }); 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 b5da98ef5f..56b711bccc 100644 --- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py +++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py @@ -8,6 +8,7 @@ from frappe import _ 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 +from frappe.desk.reportview import get_match_cond class EmployeeBenefitApplication(Document): def validate(self): @@ -130,3 +131,25 @@ def get_amount(payroll_period_days, start_date, end_date, amount): amount_per_day = amount / payroll_period_days total_amount = amount_per_day * salary_slip_days return total_amount + +def get_earning_components(doctype, txt, searchfield, start, page_len, filters): + if len(filters) < 2: + return {} + employee = filters['employee'] + date = filters['date'] + salary_structure = get_assigned_salary_sturecture(employee, date) + + if len(salary_structure) > 0: + query = """select salary_component from `tabSalary Detail` where parent = '{salary_structure}' + and is_flexible_benefit = 1 + order by name""" + + return frappe.db.sql(query.format(**{ + "salary_structure": salary_structure[0][0], + "mcond": get_match_cond(doctype) + }), { + 'start': start, + 'page_len': page_len + }) + + return {} From ce7310255e1d4b1f812e6beccb6debf498bb6e0b Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Tue, 22 May 2018 13:41:55 +0530 Subject: [PATCH 09/29] Salary Structure - filter for earnings --- erpnext/hr/doctype/salary_structure/salary_structure.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.js b/erpnext/hr/doctype/salary_structure/salary_structure.js index 9e62b6640e..56f59929fc 100755 --- a/erpnext/hr/doctype/salary_structure/salary_structure.js +++ b/erpnext/hr/doctype/salary_structure/salary_structure.js @@ -19,7 +19,9 @@ frappe.ui.form.on('Salary Structure', { frm.set_query("salary_component", "earnings", function() { return { filters: { - type: "earning" + type: "earning", + is_additional_component: 0, + is_group: 0 } } }); From 2ee211ad2118ed93b20ae5ff22051fc55e9aaeeb Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Tue, 22 May 2018 13:42:53 +0530 Subject: [PATCH 10/29] Salary Structure - validate max benefits with flexi --- .../salary_structure/salary_structure.py | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.py b/erpnext/hr/doctype/salary_structure/salary_structure.py index 23c57de651..affd2bb0da 100644 --- a/erpnext/hr/doctype/salary_structure/salary_structure.py +++ b/erpnext/hr/doctype/salary_structure/salary_structure.py @@ -13,6 +13,7 @@ class SalaryStructure(Document): def validate(self): self.validate_amount() self.strip_condition_and_formula_fields() + self.validate_max_benefits_with_flexi() def validate_amount(self): if flt(self.net_pay) < 0 and self.salary_slip_based_on_timesheet: @@ -28,11 +29,27 @@ class SalaryStructure(Document): row.condition = row.condition.strip() if row.condition else "" row.formula = row.formula.strip() if row.formula else "" + def validate_max_benefits_with_flexi(self): + have_a_flexi = False + if self.max_benefits > 0 and self.earnings: + flexi_amount = 0 + for earning_component in self.earnings: + if earning_component.is_flexible_benefit == 1: + have_a_flexi = True + max_of_component = frappe.db.get_value("Salary Component", earning_component.salary_component, "max_benefit_amount") + flexi_amount += max_of_component + if self.max_benefits > flexi_amount: + frappe.throw(_("Total flexi component amount {0} should not be less \ + than max benefits {1}").format(flexi_amount, self.max_benefits)) + if not have_a_flexi and self.max_benefits > 0: + frappe.throw(_("Flexi component require to add max benefit")) + + @frappe.whitelist() def make_salary_slip(source_name, target_doc = None, employee = None, as_print = False, print_format = None): def postprocess(source, target): if employee: - employee_details = frappe.db.get_value("Employee", employee, + employee_details = frappe.db.get_value("Employee", employee, ["employee_name", "branch", "designation", "department"], as_dict=1) target.employee = employee target.employee_name = employee_details.employee_name @@ -62,4 +79,4 @@ def make_salary_slip(source_name, target_doc = None, employee = None, as_print = def get_employees(salary_structure): employees = frappe.get_list('Salary Structure Assignment', filters={'salary_structure': salary_structure}, fields=['employee']) - return list(set([d.employee for d in employees])) \ No newline at end of file + return list(set([d.employee for d in employees])) From cf414cc4994d517ccf378ab7df6270b0db21b6be Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Tue, 22 May 2018 14:22:42 +0530 Subject: [PATCH 11/29] Payroll Period - fields refactor --- ...test_employee_tax_exemption_declaration.py | 6 +- .../payroll_period/payroll_period.json | 127 +++++++++++++++++- .../doctype/payroll_period/payroll_period.py | 9 +- erpnext/hr/utils.py | 7 +- 4 files changed, 133 insertions(+), 16 deletions(-) diff --git a/erpnext/hr/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py b/erpnext/hr/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py index 84970d85fd..dff02eac14 100644 --- a/erpnext/hr/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py +++ b/erpnext/hr/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py @@ -84,10 +84,8 @@ def create_payroll_period(): doctype = 'Payroll Period', name = "_Test Payroll Period", company = "_Test Company", - periods = [ - dict(start_date = date(date.today().year, 1, 1), - end_date = date(date.today().year, 12, 31)) - ] + start_date = date(date.today().year, 1, 1), + end_date = date(date.today().year, 12, 31) )).insert() def create_exemption_category(): diff --git a/erpnext/hr/doctype/payroll_period/payroll_period.json b/erpnext/hr/doctype/payroll_period/payroll_period.json index 44ead2bc27..61d07631c0 100644 --- a/erpnext/hr/doctype/payroll_period/payroll_period.json +++ b/erpnext/hr/doctype/payroll_period/payroll_period.json @@ -45,6 +45,129 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_2", + "fieldtype": "Column Break", + "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, + "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": "start_date", + "fieldtype": "Date", + "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": "Start Date", + "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": 1, + "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": "end_date", + "fieldtype": "Date", + "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": "End Date", + "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": 1, + "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": "section_break_5", + "fieldtype": "Section Break", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Payroll Periods", + "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, @@ -71,7 +194,7 @@ "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, - "reqd": 1, + "reqd": 0, "search_index": 0, "set_only_once": 0, "translatable": 0, @@ -88,7 +211,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-04-13 19:38:28.013664", + "modified": "2018-05-22 14:15:59.968204", "modified_by": "Administrator", "module": "HR", "name": "Payroll Period", diff --git a/erpnext/hr/doctype/payroll_period/payroll_period.py b/erpnext/hr/doctype/payroll_period/payroll_period.py index a818bc4276..0bf2b7958e 100644 --- a/erpnext/hr/doctype/payroll_period/payroll_period.py +++ b/erpnext/hr/doctype/payroll_period/payroll_period.py @@ -12,13 +12,10 @@ class PayrollPeriod(Document): def get_payroll_period_days(start_date, end_date, company): payroll_period_dates = frappe.db.sql(""" - select ppd.start_date, ppd.end_date from `tabPayroll Period Date` ppd, `tabPayroll Period` pp - where pp.company=%(company)s - and ppd.parent = pp.name + select start_date, end_date from `tabPayroll Period` + where company=%(company)s and ( - (%(start_date)s between ppd.start_date and ppd.end_date) - or (%(end_date)s between ppd.start_date and ppd.end_date) - or (ppd.start_date between %(start_date)s and %(end_date)s) + start_date between %(start_date)s and %(end_date)s )""", { 'company': company, 'start_date': start_date, diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py index 20fe666d2b..bf37c126ea 100644 --- a/erpnext/hr/utils.py +++ b/erpnext/hr/utils.py @@ -236,8 +236,7 @@ def get_leave_period(from_date, to_date, company): 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) + payroll_period = frappe.db.sql("""select name, start_date, end_date from + `tabPayroll Period` + where start_date<=%s and end_date>= %s and company=%s""", (from_date, to_date, company), as_dict=1) return payroll_period[0] if payroll_period else None From 65a5e47e688a336fb4445bfbd9b5c6d23b2baa44 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Tue, 22 May 2018 14:24:33 +0530 Subject: [PATCH 12/29] Payroll Period - validate dates and overlap --- .../doctype/payroll_period/payroll_period.py | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/erpnext/hr/doctype/payroll_period/payroll_period.py b/erpnext/hr/doctype/payroll_period/payroll_period.py index 0bf2b7958e..c7d87e6c70 100644 --- a/erpnext/hr/doctype/payroll_period/payroll_period.py +++ b/erpnext/hr/doctype/payroll_period/payroll_period.py @@ -4,11 +4,45 @@ from __future__ import unicode_literals import frappe -from frappe.utils import date_diff, getdate +from frappe import _ +from frappe.utils import date_diff, getdate, formatdate from frappe.model.document import Document class PayrollPeriod(Document): - pass + def validate(self): + self.validate_dates() + self.validate_overlap() + + def validate_dates(self): + if getdate(self.start_date) > getdate(self.end_date): + frappe.throw(_("End date can not be less than start date")) + + def validate_overlap(self): + query = """ + select name + from `tab{0}` + where name != %(name)s + and company = %(company)s and (start_date between %(start_date)s and %(end_date)s \ + or end_date between %(start_date)s and %(end_date)s \ + or (start_date < %(start_date)s and end_date > %(end_date)s)) + """ + if not self.name: + # hack! if name is null, it could cause problems with != + self.name = "New "+self.doctype + + overlap_doc = frappe.db.sql(query.format(self.doctype),{ + "start_date": self.start_date, + "end_date": self.end_date, + "name": self.name, + "company": self.company + }, as_dict = 1) + + if overlap_doc: + msg = _("A {0} exists between {1} and {2} (").format(self.doctype, + formatdate(self.start_date), formatdate(self.end_date)) \ + + """ {1}""".format(self.doctype, overlap_doc[0].name) \ + + _(") for {0}").format(self.company) + frappe.throw(msg) def get_payroll_period_days(start_date, end_date, company): payroll_period_dates = frappe.db.sql(""" From 9d5d328a4f95898b01f0bb1c04411b34d40b8090 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Tue, 22 May 2018 15:39:34 +0530 Subject: [PATCH 13/29] Salary Structure - validate flexi with max benefit --- erpnext/hr/doctype/salary_detail/salary_detail.json | 5 +++-- erpnext/hr/doctype/salary_structure/salary_structure.py | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/erpnext/hr/doctype/salary_detail/salary_detail.json b/erpnext/hr/doctype/salary_detail/salary_detail.json index 82b0af288a..a0d699a550 100644 --- a/erpnext/hr/doctype/salary_detail/salary_detail.json +++ b/erpnext/hr/doctype/salary_detail/salary_detail.json @@ -238,6 +238,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "depends_on": "eval:doc.is_flexible_benefit != 1", "fieldname": "section_break_2", "fieldtype": "Section Break", "hidden": 0, @@ -566,7 +567,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2018-05-17 12:43:22.606298", + "modified": "2018-05-22 15:11:02.341840", "modified_by": "Administrator", "module": "HR", "name": "Salary Detail", @@ -581,4 +582,4 @@ "sort_order": "DESC", "track_changes": 0, "track_seen": 0 -} \ No newline at end of file +} diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.py b/erpnext/hr/doctype/salary_structure/salary_structure.py index affd2bb0da..12e3445d3a 100644 --- a/erpnext/hr/doctype/salary_structure/salary_structure.py +++ b/erpnext/hr/doctype/salary_structure/salary_structure.py @@ -31,13 +31,15 @@ class SalaryStructure(Document): def validate_max_benefits_with_flexi(self): have_a_flexi = False - if self.max_benefits > 0 and self.earnings: + if self.earnings: flexi_amount = 0 for earning_component in self.earnings: if earning_component.is_flexible_benefit == 1: have_a_flexi = True max_of_component = frappe.db.get_value("Salary Component", earning_component.salary_component, "max_benefit_amount") flexi_amount += max_of_component + if have_a_flexi and self.max_benefits == 0: + frappe.throw(_("Max benefits should be greater than zero to despense flexi")) if self.max_benefits > flexi_amount: frappe.throw(_("Total flexi component amount {0} should not be less \ than max benefits {1}").format(flexi_amount, self.max_benefits)) From c5629efe0e499b1185fb3d2cbd265a4136d23d89 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Tue, 22 May 2018 16:18:43 +0530 Subject: [PATCH 14/29] Employee Benefit Application - refactor validation --- .../employee_benefit_application.py | 4 +--- 1 file changed, 1 insertion(+), 3 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 56b711bccc..05725d6d7d 100644 --- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py +++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py @@ -12,13 +12,11 @@ from frappe.desk.reportview import get_match_cond class EmployeeBenefitApplication(Document): def validate(self): + self.validate_duplicate_on_payroll_period() if self.max_benefits <= 0: frappe.throw(_("Employee {0} has no maximum benefit amount").format(self.employee)) self.validate_max_benefit_for_component() - def before_submit(self): - self.validate_duplicate_on_payroll_period() - def validate_max_benefit_for_component(self): if self.employee_benefits: max_benefit_amount = 0 From c1ae88ba025d2f4f0f3ed008edf3d7762366327d Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Tue, 22 May 2018 16:19:35 +0530 Subject: [PATCH 15/29] Employee Benefit Calim - earning component filter updated --- .../employee_benefit_claim.js | 4 +- .../employee_benefit_claim.py | 45 ------------------- 2 files changed, 2 insertions(+), 47 deletions(-) diff --git a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.js b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.js index 9870ee4873..5e12828ba4 100644 --- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.js +++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.js @@ -5,8 +5,8 @@ frappe.ui.form.on('Employee Benefit Claim', { setup: function(frm) { frm.set_query("earning_component", function() { return { - query : "erpnext.hr.doctype.employee_benefit_claim.employee_benefit_claim.get_earning_components_for_claim", - filters: {claim_date: frm.doc.claim_date, employee: frm.doc.employee} + query : "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_earning_components", + filters: {date: frm.doc.claim_date, employee: frm.doc.employee} }; }); }, diff --git a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py index b1dbcaa5ad..cd9c07c64b 100644 --- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py +++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py @@ -121,48 +121,3 @@ def get_employee_benefit_claim(employee, start_date, end_date): if len(salary_components_array) > 0: return salary_components_array return False - -def get_earning_components_for_claim(doctype, txt, searchfield, start, page_len, filters): - if len(filters) < 2: - return {} - employee = filters['employee'] - claim_date = filters['claim_date'] - - payroll_period = get_payroll_period(claim_date, claim_date, frappe.db.get_value("Employee", employee, "company")) - application = frappe.db.exists( - "Employee Benefit Application", - { - 'employee': employee, - 'payroll_period': payroll_period.name, - 'docstatus': 1 - } - ) - earning_components = get_earning_components_from_application(doctype, application, start, page_len) - - if not earning_components: - earning_components = get_all_pro_rata_earning_components(doctype, start, page_len) - return earning_components - -def get_earning_components_from_application(doctype, parent, start, page_len): - query = """select earning_component from `tabEmployee Benefit Application Detail` where parent = '{parent}' - order by name""" - - return frappe.db.sql(query.format(**{ - "parent": parent, - "mcond": get_match_cond(doctype) - }), { - 'start': start, - 'page_len': page_len - }) - -def get_all_pro_rata_earning_components(doctype, start, page_len): - return frappe.db.sql(""" - select name from `tabSalary Component` - where is_flexible_benefit = 1 and is_pro_rata_applicable = 1 - and type = 'Earning' and disabled = 0 - """.format(**{ - "mcond": get_match_cond(doctype) - }), { - 'start': start, - 'page_len': page_len - }) From eacaad3aec2d45a3fec58c5e900322297d52a080 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Wed, 23 May 2018 13:24:52 +0530 Subject: [PATCH 16/29] Max benefit amount in Employee Benefit Application Detail --- .../employee_benefit_application_detail.json | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/employee_benefit_application_detail/employee_benefit_application_detail.json b/erpnext/hr/doctype/employee_benefit_application_detail/employee_benefit_application_detail.json index 37f32429e0..32c14b59e8 100644 --- a/erpnext/hr/doctype/employee_benefit_application_detail/employee_benefit_application_detail.json +++ b/erpnext/hr/doctype/employee_benefit_application_detail/employee_benefit_application_detail.json @@ -77,6 +77,38 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "max_benefit_amount", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Max Benefit Amount", + "length": 0, + "no_copy": 0, + "options": "earning_component.max_benefit_amount", + "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, @@ -119,7 +151,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2018-05-15 12:03:25.545041", + "modified": "2018-05-23 13:05:20.004362", "modified_by": "Administrator", "module": "HR", "name": "Employee Benefit Application Detail", @@ -129,6 +161,7 @@ "quick_entry": 1, "read_only": 0, "read_only_onload": 0, + "search_fields": "", "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "DESC", From 772f257ff3b7b0e5d240950a09d6b6db71087da0 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Wed, 23 May 2018 13:25:30 +0530 Subject: [PATCH 17/29] Employee Benefit Claim - date default to Today --- .../employee_benefit_claim/employee_benefit_claim.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.json b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.json index 33fc942255..5fdc1471f5 100644 --- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.json +++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.json @@ -116,7 +116,8 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, - "columns": 0, + "columns": 0, + "default": "Today", "fieldname": "claim_date", "fieldtype": "Date", "hidden": 0, @@ -434,7 +435,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-05-17 12:43:21.082282", + "modified": "2018-05-23 13:12:33.596989", "modified_by": "Administrator", "module": "HR", "name": "Employee Benefit Claim", @@ -527,4 +528,4 @@ "title_field": "employee_name", "track_changes": 1, "track_seen": 0 -} \ No newline at end of file +} From 8a953ba51623b67445f7fde44bdad551629ab02d Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Wed, 23 May 2018 13:28:08 +0530 Subject: [PATCH 18/29] Validate remaining benefit amount in Employee Benefit Application --- .../employee_benefit_application.py | 41 ++++++++++++++++--- 1 file changed, 35 insertions(+), 6 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 05725d6d7d..e1af43090e 100644 --- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py +++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py @@ -16,6 +16,39 @@ class EmployeeBenefitApplication(Document): if self.max_benefits <= 0: frappe.throw(_("Employee {0} has no maximum benefit amount").format(self.employee)) self.validate_max_benefit_for_component() + if self.remainig_benefits > 0: + self.validate_remaining_benefit_amount() + + def validate_remaining_benefit_amount(self): + # check salary structure earnings have flexi component (sum of max_benefit_amount) + # without pro-rata which satisfy the remainig_benefits + # else pro-rata component for the amount + # again comes the same validation and satisfy or throw + benefit_components = [] + if self.employee_benefits: + for employee_benefit in self.employee_benefits: + benefit_components.append(employee_benefit.earning_component) + salary_struct_name = get_assigned_salary_sturecture(self.employee, self.date) + if len(salary_struct_name) > 0: + non_pro_rata_amount = 0 + pro_rata_amount = 0 + salary_structure = frappe.get_doc("Salary Structure", salary_struct_name[0][0]) + if salary_structure.earnings: + for earnings in salary_structure.earnings: + if earnings.is_flexible_benefit == 1 and earnings.salary_component not in benefit_components: + is_pro_rata_applicable, max_benefit_amount = frappe.db.get_value("Salary Component", earnings.salary_component, ["is_pro_rata_applicable", "max_benefit_amount"]) + if is_pro_rata_applicable == 1: + pro_rata_amount += max_benefit_amount + else: + non_pro_rata_amount += max_benefit_amount + if pro_rata_amount == 0 and non_pro_rata_amount == 0: + frappe.throw(_("Please add the remainig benefits {0} to any of the existing component").format(self.remainig_benefits)) + elif non_pro_rata_amount > 0 and non_pro_rata_amount < self.remainig_benefits: + frappe.throw(_("You can claim only an amount of {0}, the rest amount {1} should be in the application \ + as pro-rata component").format(non_pro_rata_amount, self.remainig_benefits - non_pro_rata_amount)) + elif non_pro_rata_amount == 0: + frappe.throw(_("Please add the remainig benefits {0} to the application as \ + pro-rata component").format(self.remainig_benefits)) def validate_max_benefit_for_component(self): if self.employee_benefits: @@ -143,11 +176,7 @@ def get_earning_components(doctype, txt, searchfield, start, page_len, filters): order by name""" return frappe.db.sql(query.format(**{ - "salary_structure": salary_structure[0][0], - "mcond": get_match_cond(doctype) - }), { - 'start': start, - 'page_len': page_len - }) + "salary_structure": salary_structure[0][0] + })) return {} From 47d865baa037f91100bbdcf30f2ee04eeaba48cc Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Wed, 23 May 2018 13:45:12 +0530 Subject: [PATCH 19/29] Calculate remaining benefit amount in Employee Benefit Application --- .../employee_benefit_application.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js index d38af3cb57..f96f2629c3 100644 --- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js +++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js @@ -33,6 +33,9 @@ frappe.ui.form.on('Employee Benefit Application', { frappe.ui.form.on("Employee Benefit Application Detail",{ amount: function(frm) { calculate_all(frm.doc); + }, + employee_benefits_remove: function(frm) { + calculate_all(frm.doc); } }); From 16e924333ea886c5fab476362a3dcb9353f5a33a Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Fri, 25 May 2018 11:04:21 +0530 Subject: [PATCH 20/29] get payroll period days - fix --- erpnext/hr/doctype/payroll_period/payroll_period.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/payroll_period/payroll_period.py b/erpnext/hr/doctype/payroll_period/payroll_period.py index c7d87e6c70..66d6a457d6 100644 --- a/erpnext/hr/doctype/payroll_period/payroll_period.py +++ b/erpnext/hr/doctype/payroll_period/payroll_period.py @@ -49,7 +49,9 @@ def get_payroll_period_days(start_date, end_date, company): select start_date, end_date from `tabPayroll Period` where company=%(company)s and ( - start_date between %(start_date)s and %(end_date)s + (%(start_date)s between start_date and end_date) + or (%(end_date)s between start_date and end_date) + or (start_date between %(start_date)s and %(end_date)s) )""", { 'company': company, 'start_date': start_date, From 8eec40cb8a6aa0c736c00e6ca2754fdab366b4ed Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Fri, 25 May 2018 11:06:42 +0530 Subject: [PATCH 21/29] Employee Benefits in Salary Slip - Application and Claim --- .../employee_benefit_application.py | 67 ++++++++-------- .../employee_benefit_claim.py | 77 ++++++++----------- erpnext/hr/doctype/salary_slip/salary_slip.py | 60 ++++----------- 3 files changed, 80 insertions(+), 124 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 e1af43090e..1902b5d6ea 100644 --- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py +++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py @@ -110,8 +110,9 @@ def get_assigned_salary_sturecture(employee, _date): if salary_structure: return salary_structure -def get_employee_benefit_application(employee, start_date, end_date): - employee_benefits = frappe.db.sql(""" +def get_benefit_component_amount(employee, start_date, end_date, struct_row, sal_struct): + # Considering there is only one application for an year + benefit_application_name = frappe.db.sql(""" select name from `tabEmployee Benefit Application` where employee=%(employee)s and docstatus = 1 @@ -122,41 +123,41 @@ def get_employee_benefit_application(employee, start_date, end_date): 'end_date': 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_benefit_components(employee_benefit_obj, employee, start_date, end_date) - -def get_benefit_components(employee_benefit_application, employee, start_date, end_date): - salary_components_array = [] - group_component_amount = {} payroll_period_days = get_payroll_period_days(start_date, end_date, frappe.db.get_value("Employee", employee, "company")) - for employee_benefit in employee_benefit_application.employee_benefits: - if employee_benefit.is_pro_rata_applicable == 1: - struct_row = {} - salary_components_dict = {} - amount = get_amount(payroll_period_days, start_date, end_date, employee_benefit.amount) - sc = frappe.get_doc("Salary Component", employee_benefit.earning_component) - salary_component = sc - if sc.earning_component_group and not sc.is_group and not sc.flexi_default: - salary_component = frappe.get_doc("Salary Component", sc.earning_component_group) - if group_component_amount and group_component_amount.has_key(sc.earning_component_group): - group_component_amount[sc.earning_component_group] += amount - else: - group_component_amount[sc.earning_component_group] = amount - amount = group_component_amount[sc.earning_component_group] - 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 payroll_period_days: + # If there is application for benefit claim then fetch the amount from it. + if benefit_application_name: + benefit_application = frappe.get_doc("Employee Benefit Application", benefit_application_name[0][0]) + return get_benefit_amount(benefit_application, start_date, end_date, struct_row, payroll_period_days) - if len(salary_components_array) > 0: - return salary_components_array + # TODO: Check if there is benefit claim for employee then pro-rata devid the rest of amount + # else Split the max benefits to the pro-rata components with the ratio of thier max_benefit_amount + else: + component_max = frappe.db.get_value("Salary Component", struct_row.salary_component, "max_benefit_amount") + if component_max > 0: + return get_benefit_pro_rata_ratio_amount(sal_struct, component_max, payroll_period_days, start_date, end_date) return False +def get_benefit_pro_rata_ratio_amount(sal_struct, component_max, payroll_period_days, start_date, end_date): + total_pro_rata_max = 0 + for sal_struct_row in sal_struct.get("earnings"): + is_pro_rata_applicable, max_benefit_amount = frappe.db.get_value("Salary Component", sal_struct_row.salary_component, ["is_pro_rata_applicable", "max_benefit_amount"]) + if sal_struct_row.is_flexible_benefit == 1 and is_pro_rata_applicable == 1: + total_pro_rata_max += max_benefit_amount + if total_pro_rata_max > 0: + benefit_amount = component_max * sal_struct.max_benefits / total_pro_rata_max + if benefit_amount > component_max: + benefit_amount = component_max + return get_amount(payroll_period_days, start_date, end_date, benefit_amount) + return False + +def get_benefit_amount(application, start_date, end_date, struct_row, payroll_period_days): + amount = 0 + for employee_benefit in application.employee_benefits: + if employee_benefit.earning_component == struct_row.salary_component: + amount += get_amount(payroll_period_days, start_date, end_date, employee_benefit.amount) + return amount if amount > 0 else 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 diff --git a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py index cd9c07c64b..b8aef0cf9d 100644 --- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py +++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py @@ -13,9 +13,9 @@ from frappe.desk.reportview import get_match_cond class EmployeeBenefitClaim(Document): def validate(self): max_benefits = get_max_benefits(self.employee, self.claim_date) - self.validate_max_benefit_for_component() - self.validate_max_benefit_for_sal_struct(max_benefits) payroll_period = get_payroll_period(self.claim_date, self.claim_date, frappe.db.get_value("Employee", self.employee, "company")) + self.validate_max_benefit_for_component(payroll_period) + self.validate_max_benefit_for_sal_struct(max_benefits) self.validate_benefit_claim_amount(max_benefits, payroll_period) if not self.is_pro_rata_applicable: self.validate_non_pro_rata_benefit_claim(max_benefits, payroll_period) @@ -31,20 +31,27 @@ class EmployeeBenefitClaim(Document): if self.claimed_amount > max_benefits: frappe.throw(_("Maximum benefit amount of employee {0} exceeds {1}").format(self.employee, max_benefits)) - def validate_max_benefit_for_component(self): - if self.claimed_amount > self.max_amount_eligible: + def validate_max_benefit_for_component(self, payroll_period): + claimed_amount = self.claimed_amount + claimed_amount += self.get_previous_claimed_amount(payroll_period, self.earning_component) + if claimed_amount > self.max_amount_eligible: frappe.throw(_("Maximum amount eligible for the component {0} exceeds {1}").format(self.earning_component, self.max_amount_eligible)) def validate_non_pro_rata_benefit_claim(self, max_benefits, payroll_period): claimed_amount = self.claimed_amount pro_rata_amount = self.get_pro_rata_amount_in_application(payroll_period.name) + if not pro_rata_amount: + pro_rata_amount = 0 + # TODO: + # Get pro_rata_amount if there is no application, + # get salary slip for the period and calculate pro-rata amount per day and mulitply with payroll_period_days + claimed_amount += self.get_previous_claimed_amount(payroll_period, True) if max_benefits < pro_rata_amount + claimed_amount: frappe.throw(_("Maximum benefit of employee {0} exceeds {1} by the sum {2} of benefit application pro-rata component\ amount and previous claimed amount").format(self.employee, max_benefits, pro_rata_amount+claimed_amount-max_benefits)) def get_pro_rata_amount_in_application(self, payroll_period): - pro_rata_dispensed_amount = 0 application = frappe.db.exists( "Employee Benefit Application", { @@ -54,10 +61,10 @@ class EmployeeBenefitClaim(Document): } ) if application: - pro_rata_dispensed_amount = frappe.db.get_value("Employee Benefit Application", application, "pro_rata_dispensed_amount") - return pro_rata_dispensed_amount + return frappe.db.get_value("Employee Benefit Application", application, "pro_rata_dispensed_amount") + return False - def get_previous_claimed_amount(self, payroll_period, non_pro_rata=False): + def get_previous_claimed_amount(self, payroll_period, non_pro_rata=False, component=False): total_claimed_amount = 0 query = """ select sum(claimed_amount) as 'total_amount' @@ -68,56 +75,36 @@ class EmployeeBenefitClaim(Document): """ if non_pro_rata: query += "and is_pro_rata_applicable = 0" + if component: + query += "and earning_component = %(component)s" sum_of_claimed_amount = frappe.db.sql(query, { 'employee': self.employee, 'start_date': payroll_period.start_date, - 'end_date': payroll_period.end_date + 'end_date': payroll_period.end_date, + 'component': component }, as_dict=True) - if sum_of_claimed_amount: + if sum_of_claimed_amount and sum_of_claimed_amount[0].total_amount > 0: total_claimed_amount = sum_of_claimed_amount[0].total_amount return total_claimed_amount -def get_employee_benefit_claim(employee, start_date, end_date): - employee_benefits = frappe.db.sql(""" - select name from `tabEmployee Benefit Claim` +def get_benefit_claim_amount(employee, start_date, end_date, struct_row): + benefit_claim_details = frappe.db.sql(""" + select claimed_amount from `tabEmployee Benefit Claim` where employee=%(employee)s and docstatus = 1 and is_pro_rata_applicable = 0 + and earning_component = %(earning_component)s and (claim_date between %(start_date)s and %(end_date)s) """, { 'employee': employee, 'start_date': start_date, - 'end_date': end_date - }) + 'end_date': end_date, + 'earning_component': struct_row.salary_component + }, as_dict = True) - if employee_benefits: - salary_components_array = [] - for employee_benefit in employee_benefits: - struct_row = {} - salary_components_dict = {} - group_component_amount = {} - - employee_benefit_claim = frappe.get_doc("Employee Benefit Claim", employee_benefit[0]) - amount = employee_benefit_claim.claimed_amount - sc = frappe.get_doc("Salary Component", employee_benefit_claim.earning_component) - - salary_component = sc - if sc.earning_component_group and not sc.is_group and not sc.flexi_default: - salary_component = frappe.get_doc("Salary Component", sc.earning_component_group) - if group_component_amount and group_component_amount.has_key(sc.earning_component_group): - group_component_amount[sc.earning_component_group] += amount - else: - group_component_amount[sc.earning_component_group] = amount - amount = group_component_amount[sc.earning_component_group] - - 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 + if benefit_claim_details: + claimed_amount = 0 + for claim_detail in benefit_claim_details: + claimed_amount += claim_detail.claimed_amount + return claimed_amount return False diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index 6651e0561f..32fc4b90aa 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -14,9 +14,8 @@ 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 -from erpnext.hr.doctype.employee_benefit_application.employee_benefit_application import get_employee_benefit_application, get_amount -from erpnext.hr.doctype.payroll_period.payroll_period import get_payroll_period_days -from erpnext.hr.doctype.employee_benefit_claim.employee_benefit_claim import get_employee_benefit_claim +from erpnext.hr.doctype.employee_benefit_application.employee_benefit_application import get_benefit_component_amount +from erpnext.hr.doctype.employee_benefit_claim.employee_benefit_claim import get_benefit_claim_amount class SalarySlip(TransactionBase): def autoname(self): @@ -62,6 +61,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=="earnings" and struct_row.is_flexible_benefit == 1: + self.add_employee_flexi_benefits(struct_row) + 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: @@ -74,41 +77,15 @@ class SalarySlip(TransactionBase): amount = additional_component.amount + self.get_amount_from_exisiting_component(frappe._dict(additional_component.struct_row).salary_component) self.update_component_row(frappe._dict(additional_component.struct_row), amount, "earnings") - max_benefits = self._salary_structure_doc.get("max_benefits") - if max_benefits > 0: - self.add_employee_benefits(max_benefits) - - def add_employee_benefits(self, max_benefits): - employee_benefits = get_employee_benefit_application(self.employee, self.start_date, self.end_date) - if employee_benefits: - for employee_benefit in employee_benefits: - benefit_component = frappe._dict(employee_benefit) - amount = benefit_component.amount + self.get_amount_from_exisiting_component(frappe._dict(benefit_component.struct_row).salary_component) - self.update_component_row(frappe._dict(benefit_component.struct_row), amount, "earnings") + def add_employee_flexi_benefits(self, struct_row): + if frappe.db.get_value("Salary Component", struct_row.salary_component, "is_pro_rata_applicable") == 1: + benefit_component_amount = get_benefit_component_amount(self.employee, self.start_date, self.end_date, struct_row, self._salary_structure_doc) + if benefit_component_amount: + self.update_component_row(struct_row, benefit_component_amount, "earnings") else: - default_flexi_compenent = frappe.db.exists( - 'Salary Component', - { - 'is_flexible_benefit': 1, - 'is_pro_rata_applicable': 1, - 'flexi_default': 1 - } - ) - if default_flexi_compenent: - flexi_struct_row = self.create_flexi_struct_row(default_flexi_compenent) - payroll_period_days = get_payroll_period_days(self.start_date, self.end_date, self.company) - amount = get_amount(payroll_period_days, self.start_date, self.end_date, max_benefits) - amount += self.get_amount_from_exisiting_component(default_flexi_compenent) - self.update_component_row(flexi_struct_row, amount, "earnings") - else: - frappe.throw(_("Configure default flexible benefit salary component to apply pro-rata benefit")) - - benefit_claims = get_employee_benefit_claim(self.employee, self.start_date, self.end_date) - if benefit_claims: - for benefit_claim in benefit_claims: - benefit_component = frappe._dict(benefit_claim) - amount = benefit_component.amount + self.get_amount_from_exisiting_component(frappe._dict(benefit_component.struct_row).salary_component) - self.update_component_row(frappe._dict(benefit_component.struct_row), amount, "earnings") + benefit_claim_amount = get_benefit_claim_amount(self.employee, self.start_date, self.end_date, struct_row) + if benefit_claim_amount: + self.update_component_row(struct_row, benefit_claim_amount, "earnings") def get_amount_from_exisiting_component(self, salary_component): amount = 0 @@ -117,15 +94,6 @@ class SalarySlip(TransactionBase): amount = d.amount return amount - def create_flexi_struct_row(self, default_flexi_compenent): - salary_component = frappe.get_doc("Salary Component", default_flexi_compenent) - flexi_struct_row = {} - flexi_struct_row['depends_on_lwp'] = salary_component.depends_on_lwp - flexi_struct_row['salary_component'] = salary_component.name - flexi_struct_row['abbr'] = salary_component.salary_component_abbr - flexi_struct_row['do_not_include_in_total'] = salary_component.do_not_include_in_total - return frappe._dict(flexi_struct_row) - def update_component_row(self, struct_row, amount, key): component_row = None for d in self.get(key): From dc698a891de726c294c59461ef00cb660f20b64f Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Fri, 25 May 2018 12:06:40 +0530 Subject: [PATCH 22/29] options to fetch from migration --- .../additional_salary_component.json | 16 +++++++++++--- .../attendance_request.json | 17 +++++++++++--- .../compensatory_leave_request.json | 15 ++++++++++--- .../employee_benefit_application.json | 18 ++++++++++++--- .../employee_benefit_application_detail.json | 12 +++++++--- .../employee_benefit_claim.json | 22 +++++++++++++++---- 6 files changed, 81 insertions(+), 19 deletions(-) diff --git a/erpnext/hr/doctype/additional_salary_component/additional_salary_component.json b/erpnext/hr/doctype/additional_salary_component/additional_salary_component.json index ea73917e07..2071ddae55 100644 --- a/erpnext/hr/doctype/additional_salary_component/additional_salary_component.json +++ b/erpnext/hr/doctype/additional_salary_component/additional_salary_component.json @@ -15,6 +15,7 @@ "fields": [ { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -47,6 +48,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -79,6 +81,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -111,11 +114,12 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fetch_from": "employee.employee_name", + "fetch_from": "employee.employee_name", "fieldname": "employee_name", "fieldtype": "Data", "hidden": 0, @@ -144,6 +148,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -176,6 +181,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -206,6 +212,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -237,6 +244,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -268,6 +276,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -299,6 +308,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -372,7 +382,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-05-17 10:22:03.004640", + "modified": "2018-05-25 12:03:07.399413", "modified_by": "Administrator", "module": "HR", "name": "Additional Salary Component", @@ -427,4 +437,4 @@ "title_field": "employee", "track_changes": 1, "track_seen": 0 -} \ No newline at end of file +} diff --git a/erpnext/hr/doctype/attendance_request/attendance_request.json b/erpnext/hr/doctype/attendance_request/attendance_request.json index d152a70353..c626941e6d 100644 --- a/erpnext/hr/doctype/attendance_request/attendance_request.json +++ b/erpnext/hr/doctype/attendance_request/attendance_request.json @@ -15,6 +15,7 @@ "fields": [ { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -47,11 +48,12 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fetch_from": "employee.employee_name", + "fetch_from": "employee.employee_name", "fieldname": "employee_name", "fieldtype": "Data", "hidden": 0, @@ -80,6 +82,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -144,6 +147,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -175,6 +179,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -206,6 +211,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -238,6 +244,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -268,6 +275,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -299,6 +307,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -331,6 +340,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -363,6 +373,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -403,7 +414,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-05-17 12:04:20.334541", + "modified": "2018-05-25 12:02:39.993839", "modified_by": "Administrator", "module": "HR", "name": "Attendance Request", @@ -496,4 +507,4 @@ "title_field": "employee_name", "track_changes": 1, "track_seen": 0 -} \ No newline at end of file +} diff --git a/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.json b/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.json index 44c76c58fd..9d2a966165 100644 --- a/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.json +++ b/erpnext/hr/doctype/compensatory_leave_request/compensatory_leave_request.json @@ -15,6 +15,7 @@ "fields": [ { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -47,11 +48,12 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fetch_from": "employee.employee_name", + "fetch_from": "employee.employee_name", "fieldname": "employee_name", "fieldtype": "Data", "hidden": 0, @@ -80,6 +82,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -144,6 +147,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -175,6 +179,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -205,6 +210,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -237,6 +243,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -268,6 +275,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -300,6 +308,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -340,7 +349,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-05-17 10:09:21.089982", + "modified": "2018-05-25 12:02:05.585184", "modified_by": "Administrator", "module": "HR", "name": "Compensatory Leave Request", @@ -433,4 +442,4 @@ "title_field": "employee_name", "track_changes": 1, "track_seen": 0 -} \ No newline at end of file +} diff --git a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.json b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.json index cf178547d6..7a8803ad00 100644 --- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.json +++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.json @@ -15,6 +15,7 @@ "fields": [ { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -47,11 +48,12 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fetch_from": "employee.employee_name", + "fetch_from": "employee.employee_name", "fieldname": "employee_name", "fieldtype": "Data", "hidden": 0, @@ -80,6 +82,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -111,6 +114,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -142,6 +146,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -172,6 +177,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -204,6 +210,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -236,6 +243,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -267,6 +275,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -298,6 +307,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -362,6 +372,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -392,6 +403,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -433,7 +445,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-05-17 12:43:32.220595", + "modified": "2018-05-25 12:01:01.490375", "modified_by": "Administrator", "module": "HR", "name": "Employee Benefit Application", @@ -526,4 +538,4 @@ "title_field": "employee_name", "track_changes": 1, "track_seen": 0 -} \ No newline at end of file +} diff --git a/erpnext/hr/doctype/employee_benefit_application_detail/employee_benefit_application_detail.json b/erpnext/hr/doctype/employee_benefit_application_detail/employee_benefit_application_detail.json index 32c14b59e8..a6e51fbf7c 100644 --- a/erpnext/hr/doctype/employee_benefit_application_detail/employee_benefit_application_detail.json +++ b/erpnext/hr/doctype/employee_benefit_application_detail/employee_benefit_application_detail.json @@ -15,6 +15,7 @@ "fields": [ { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -47,10 +48,12 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, + "fetch_from": "earning_component.is_pro_rata_applicable", "fieldname": "is_pro_rata_applicable", "fieldtype": "Check", "hidden": 0, @@ -63,7 +66,7 @@ "label": "Is Pro-rata Applicable", "length": 0, "no_copy": 0, - "options": "earning_component.is_pro_rata_applicable", + "options": "", "permlevel": 0, "precision": "", "print_hide": 0, @@ -79,10 +82,12 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, + "fetch_from": "earning_component.max_benefit_amount", "fieldname": "max_benefit_amount", "fieldtype": "Currency", "hidden": 0, @@ -95,7 +100,7 @@ "label": "Max Benefit Amount", "length": 0, "no_copy": 0, - "options": "earning_component.max_benefit_amount", + "options": "", "permlevel": 0, "precision": "", "print_hide": 0, @@ -111,6 +116,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -151,7 +157,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2018-05-23 13:05:20.004362", + "modified": "2018-05-25 12:00:37.588822", "modified_by": "Administrator", "module": "HR", "name": "Employee Benefit Application Detail", diff --git a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.json b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.json index 5fdc1471f5..a9dd573f00 100644 --- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.json +++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.json @@ -15,6 +15,7 @@ "fields": [ { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -47,11 +48,12 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fetch_from": "employee.employee_name", + "fetch_from": "employee.employee_name", "fieldname": "employee_name", "fieldtype": "Data", "hidden": 0, @@ -80,6 +82,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -145,6 +148,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -175,6 +179,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -207,10 +212,12 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, + "fetch_from": "earning_component.max_benefit_amount", "fieldname": "max_amount_eligible", "fieldtype": "Currency", "hidden": 0, @@ -223,7 +230,7 @@ "label": "Max Amount Eligible", "length": 0, "no_copy": 0, - "options": "earning_component.max_benefit_amount", + "options": "", "permlevel": 0, "precision": "", "print_hide": 0, @@ -239,10 +246,12 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, + "fetch_from": "earning_component.is_pro_rata_applicable", "fieldname": "is_pro_rata_applicable", "fieldtype": "Check", "hidden": 1, @@ -255,7 +264,7 @@ "label": "Is Pro-Rata Applicable", "length": 0, "no_copy": 0, - "options": "earning_component.is_pro_rata_applicable", + "options": "", "permlevel": 0, "precision": "", "print_hide": 0, @@ -271,6 +280,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -302,6 +312,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -334,6 +345,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -365,6 +377,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -395,6 +408,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -435,7 +449,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-05-23 13:12:33.596989", + "modified": "2018-05-25 11:58:07.140055", "modified_by": "Administrator", "module": "HR", "name": "Employee Benefit Claim", From 620c3a872cc31d45075cf6f0f782adbd47ad3f49 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Fri, 25 May 2018 12:07:44 +0530 Subject: [PATCH 23/29] Employee Benefit Claim - non pro-rata claim validation updated --- .../employee_benefit_claim.py | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py index b8aef0cf9d..809bf4061b 100644 --- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py +++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py @@ -6,7 +6,7 @@ from __future__ import unicode_literals import frappe from frappe import _ from frappe.model.document import Document -from erpnext.hr.doctype.employee_benefit_application.employee_benefit_application import get_max_benefits +from erpnext.hr.doctype.employee_benefit_application.employee_benefit_application import get_max_benefits, get_assigned_salary_sturecture from erpnext.hr.utils import get_payroll_period from frappe.desk.reportview import get_match_cond @@ -41,16 +41,39 @@ class EmployeeBenefitClaim(Document): claimed_amount = self.claimed_amount pro_rata_amount = self.get_pro_rata_amount_in_application(payroll_period.name) if not pro_rata_amount: - pro_rata_amount = 0 - # TODO: # Get pro_rata_amount if there is no application, - # get salary slip for the period and calculate pro-rata amount per day and mulitply with payroll_period_days + # get salary structure for the date and calculate pro-rata amount + pro_rata_amount = self.get_benefit_pro_rata_ratio_amount() + if not pro_rata_amount: + pro_rata_amount = 0 claimed_amount += self.get_previous_claimed_amount(payroll_period, True) if max_benefits < pro_rata_amount + claimed_amount: frappe.throw(_("Maximum benefit of employee {0} exceeds {1} by the sum {2} of benefit application pro-rata component\ amount and previous claimed amount").format(self.employee, max_benefits, pro_rata_amount+claimed_amount-max_benefits)) + def get_benefit_pro_rata_ratio_amount(self): + sal_struct_name = get_assigned_salary_sturecture(self.employee, self.claim_date) + if len(sal_struct_name) > 0: + sal_struct = frappe.get_doc("Salary Structure", sal_struct_name[0][0]) + total_pro_rata_max = 0 + benefit_amount_total = 0 + for sal_struct_row in sal_struct.get("earnings"): + is_pro_rata_applicable, max_benefit_amount = frappe.db.get_value("Salary Component", sal_struct_row.salary_component, ["is_pro_rata_applicable", "max_benefit_amount"]) + if sal_struct_row.is_flexible_benefit == 1 and is_pro_rata_applicable == 1: + total_pro_rata_max += max_benefit_amount + if total_pro_rata_max > 0: + for sal_struct_row in sal_struct.get("earnings"): + is_pro_rata_applicable, max_benefit_amount = frappe.db.get_value("Salary Component", sal_struct_row.salary_component, ["is_pro_rata_applicable", "max_benefit_amount"]) + if sal_struct_row.is_flexible_benefit == 1 and is_pro_rata_applicable == 1: + component_max = max_benefit_amount + benefit_amount = component_max * sal_struct.max_benefits / total_pro_rata_max + if benefit_amount > component_max: + benefit_amount = component_max + benefit_amount_total += benefit_amount + return benefit_amount_total + return False + def get_pro_rata_amount_in_application(self, payroll_period): application = frappe.db.exists( "Employee Benefit Application", From f1d10bf2863c336a340533e18f3d5cc5bec05d2b Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Fri, 25 May 2018 12:26:18 +0530 Subject: [PATCH 24/29] Salary Component - remove flexi_default --- .../salary_component/salary_component.json | 69 ++++++++++--------- .../salary_component/salary_component.py | 14 ---- 2 files changed, 35 insertions(+), 48 deletions(-) diff --git a/erpnext/hr/doctype/salary_component/salary_component.json b/erpnext/hr/doctype/salary_component/salary_component.json index 1751a87af7..7281c7b90d 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.json +++ b/erpnext/hr/doctype/salary_component/salary_component.json @@ -14,6 +14,7 @@ "fields": [ { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -45,6 +46,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -78,6 +80,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -110,6 +113,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -142,6 +146,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -174,6 +179,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -206,6 +212,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -236,6 +243,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -267,6 +275,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -298,6 +307,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -330,6 +340,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -361,6 +372,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -393,6 +405,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -425,11 +438,12 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "depends_on": "eval:doc.is_flexible_benefit && !doc.is_group && !doc.flexi_default", + "depends_on": "eval:doc.is_flexible_benefit && !doc.is_group", "fieldname": "earning_component_group", "fieldtype": "Link", "hidden": 0, @@ -458,6 +472,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -488,6 +503,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -520,38 +536,7 @@ }, { "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_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -584,6 +569,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -616,6 +602,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -647,6 +634,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -678,6 +666,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -711,6 +700,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -743,6 +733,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -775,6 +766,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 1, @@ -808,6 +800,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -839,6 +832,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -871,6 +865,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -902,6 +897,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -933,6 +929,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -965,6 +962,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -997,6 +995,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1029,6 +1028,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1059,6 +1059,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1101,7 +1102,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-05-18 15:12:38.202265", + "modified": "2018-05-25 12:23:38.764311", "modified_by": "Administrator", "module": "HR", "name": "Salary Component", diff --git a/erpnext/hr/doctype/salary_component/salary_component.py b/erpnext/hr/doctype/salary_component/salary_component.py index 132930f563..f82d00aa09 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.py +++ b/erpnext/hr/doctype/salary_component/salary_component.py @@ -11,20 +11,6 @@ from frappe.model.naming import append_number_if_name_exists class SalaryComponent(Document): def validate(self): self.validate_abbr() - self.validate_flexi_default() - - def validate_flexi_default(self): - if self.is_flexible_benefit and self.is_pro_rata_applicable and self.flexi_default: - salary_component = frappe.db.exists( - 'Salary Component', - { - 'is_flexible_benefit': 1, - 'is_pro_rata_applicable': 1, - 'flexi_default': 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: From ce89199abb9e9458dfd48bbab834bb0507a9bacf Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Fri, 25 May 2018 12:31:55 +0530 Subject: [PATCH 25/29] taxable salary slabs remove from Salary Component and add to Payroll Period --- .../payroll_period/payroll_period.json | 73 ++++++++++++++++++- .../salary_component/salary_component.json | 36 +-------- .../salary_component/salary_component.py | 9 --- 3 files changed, 73 insertions(+), 45 deletions(-) diff --git a/erpnext/hr/doctype/payroll_period/payroll_period.json b/erpnext/hr/doctype/payroll_period/payroll_period.json index 61d07631c0..d3a9612d78 100644 --- a/erpnext/hr/doctype/payroll_period/payroll_period.json +++ b/erpnext/hr/doctype/payroll_period/payroll_period.json @@ -15,6 +15,7 @@ "fields": [ { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -47,6 +48,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -77,6 +79,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -108,6 +111,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -139,6 +143,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -170,6 +175,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -199,6 +205,71 @@ "set_only_once": 0, "translatable": 0, "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "section_break_7", + "fieldtype": "Section Break", + "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": "Taxable Salary Slabs", + "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_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "taxable_salary_slabs", + "fieldtype": "Table", + "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": "Taxable Salary Slabs", + "length": 0, + "no_copy": 0, + "options": "Taxable Salary Slab", + "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 } ], "has_web_view": 0, @@ -211,7 +282,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-05-22 14:15:59.968204", + "modified": "2018-05-25 12:29:07.207927", "modified_by": "Administrator", "module": "HR", "name": "Payroll Period", diff --git a/erpnext/hr/doctype/salary_component/salary_component.json b/erpnext/hr/doctype/salary_component/salary_component.json index 7281c7b90d..f22bfc3fe2 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.json +++ b/erpnext/hr/doctype/salary_component/salary_component.json @@ -664,40 +664,6 @@ "translatable": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "variable_based_on_taxable_salary", - "fieldname": "taxable_salary_slabs", - "fieldtype": "Table", - "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": "Taxable Salary Slabs", - "length": 0, - "no_copy": 0, - "options": "Taxable Salary Slab", - "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_in_quick_entry": 0, @@ -1102,7 +1068,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-05-25 12:23:38.764311", + "modified": "2018-05-25 12:28:03.454487", "modified_by": "Administrator", "module": "HR", "name": "Salary Component", diff --git a/erpnext/hr/doctype/salary_component/salary_component.py b/erpnext/hr/doctype/salary_component/salary_component.py index f82d00aa09..22b5376683 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.py +++ b/erpnext/hr/doctype/salary_component/salary_component.py @@ -20,12 +20,3 @@ 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]}) - - 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 From 79a6b42353ace05cf01351336364020fcc2eab99 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Fri, 25 May 2018 12:35:26 +0530 Subject: [PATCH 26/29] Salary Slip - options to fetch from migration --- .../hr/doctype/salary_slip/salary_slip.json | 70 +++++++++++++++++-- 1 file changed, 63 insertions(+), 7 deletions(-) diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.json b/erpnext/hr/doctype/salary_slip/salary_slip.json index e19f722080..15a465349d 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.json +++ b/erpnext/hr/doctype/salary_slip/salary_slip.json @@ -14,6 +14,7 @@ "fields": [ { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -46,6 +47,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -79,11 +81,12 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fetch_from": "employee.employee_name", + "fetch_from": "employee.employee_name", "fieldname": "employee_name", "fieldtype": "Read Only", "hidden": 0, @@ -113,11 +116,12 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fetch_from": "employee.department", + "fetch_from": "employee.department", "fieldname": "department", "fieldtype": "Link", "hidden": 0, @@ -132,7 +136,7 @@ "no_copy": 0, "oldfieldname": "department", "oldfieldtype": "Link", - "options": "Department", + "options": "Department", "permlevel": 0, "print_hide": 0, "print_hide_if_no_value": 0, @@ -147,12 +151,13 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, "depends_on": "eval:doc.designation", - "fetch_from": "employee.designation", + "fetch_from": "employee.designation", "fieldname": "designation", "fieldtype": "Read Only", "hidden": 0, @@ -182,11 +187,12 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fetch_from": "employee.branch", + "fetch_from": "employee.branch", "fieldname": "branch", "fieldtype": "Read Only", "hidden": 0, @@ -216,6 +222,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -247,6 +254,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -279,6 +287,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -311,6 +320,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -342,6 +352,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 1, "bold": 0, "collapsible": 0, @@ -373,6 +384,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -403,6 +415,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -436,6 +449,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -468,6 +482,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -501,6 +516,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -531,6 +547,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -564,6 +581,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -598,6 +616,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -631,6 +650,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -664,6 +684,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -697,6 +718,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -729,6 +751,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -762,6 +785,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -792,6 +816,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -823,6 +848,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -855,6 +881,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -887,6 +914,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -919,6 +947,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -951,6 +980,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -981,6 +1011,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1014,6 +1045,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1044,6 +1076,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1075,6 +1108,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1106,6 +1140,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1137,6 +1172,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1169,6 +1205,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1203,6 +1240,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1235,6 +1273,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1268,6 +1307,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1299,6 +1339,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1332,6 +1373,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1361,6 +1403,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1394,6 +1437,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1426,6 +1470,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1458,6 +1503,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1488,6 +1534,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1521,6 +1568,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1554,6 +1602,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1584,6 +1633,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1617,6 +1667,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1648,6 +1699,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1682,6 +1734,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1712,6 +1765,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 1, "collapsible": 0, @@ -1743,6 +1797,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1773,6 +1828,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1816,7 +1872,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-05-17 10:30:09.007581", + "modified": "2018-05-25 12:33:27.147636", "modified_by": "Administrator", "module": "HR", "name": "Salary Slip", @@ -1890,4 +1946,4 @@ "title_field": "employee_name", "track_changes": 0, "track_seen": 0 -} \ No newline at end of file +} From fca88a6b229ae05d59a59d097e7ea83dc7dedbd7 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Fri, 25 May 2018 14:35:02 +0530 Subject: [PATCH 27/29] Employee benefits - get_assigned_salary_structure --- .../employee_benefit_application.py | 38 +++++-------------- .../employee_benefit_claim.py | 10 ++--- 2 files changed, 15 insertions(+), 33 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 1902b5d6ea..0c39b33d2c 100644 --- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py +++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py @@ -8,7 +8,7 @@ from frappe import _ 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 -from frappe.desk.reportview import get_match_cond +from erpnext.hr.doctype.salary_structure_assignment.salary_structure_assignment import get_assigned_salary_structure class EmployeeBenefitApplication(Document): def validate(self): @@ -28,11 +28,11 @@ class EmployeeBenefitApplication(Document): if self.employee_benefits: for employee_benefit in self.employee_benefits: benefit_components.append(employee_benefit.earning_component) - salary_struct_name = get_assigned_salary_sturecture(self.employee, self.date) - if len(salary_struct_name) > 0: + salary_struct_name = get_assigned_salary_structure(self.employee, self.date) + if salary_struct_name: non_pro_rata_amount = 0 pro_rata_amount = 0 - salary_structure = frappe.get_doc("Salary Structure", salary_struct_name[0][0]) + salary_structure = frappe.get_doc("Salary Structure", salary_struct_name) if salary_structure.earnings: for earnings in salary_structure.earnings: if earnings.is_flexible_benefit == 1 and earnings.salary_component not in benefit_components: @@ -82,9 +82,9 @@ class EmployeeBenefitApplication(Document): @frappe.whitelist() def get_max_benefits(employee, on_date): - sal_struct = get_assigned_salary_sturecture(employee, on_date) + sal_struct = get_assigned_salary_structure(employee, on_date) if sal_struct: - max_benefits = frappe.db.get_value("Salary Structure", sal_struct[0][0], "max_benefits") + max_benefits = frappe.db.get_value("Salary Structure", sal_struct, "max_benefits") if max_benefits > 0: return max_benefits else: @@ -92,24 +92,6 @@ def get_max_benefits(employee, on_date): else: frappe.throw(_("Employee {0} has no salary structure assigned").format(employee)) - -@frappe.whitelist() -def get_assigned_salary_sturecture(employee, _date): - if not _date: - _date = nowdate() - salary_structure = frappe.db.sql(""" - select salary_structure from `tabSalary Structure Assignment` - where employee=%(employee)s - and docstatus = 1 - and ( - (%(_date)s between from_date and ifnull(to_date, '2199-12-31')) - )""", { - 'employee': employee, - '_date': _date, - }) - if salary_structure: - return salary_structure - def get_benefit_component_amount(employee, start_date, end_date, struct_row, sal_struct): # Considering there is only one application for an year benefit_application_name = frappe.db.sql(""" @@ -130,7 +112,7 @@ def get_benefit_component_amount(employee, start_date, end_date, struct_row, sal benefit_application = frappe.get_doc("Employee Benefit Application", benefit_application_name[0][0]) return get_benefit_amount(benefit_application, start_date, end_date, struct_row, payroll_period_days) - # TODO: Check if there is benefit claim for employee then pro-rata devid the rest of amount + # TODO: Check if there is benefit claim for employee then pro-rata devid the rest of amount (Late Benefit Application) # else Split the max benefits to the pro-rata components with the ratio of thier max_benefit_amount else: component_max = frappe.db.get_value("Salary Component", struct_row.salary_component, "max_benefit_amount") @@ -169,15 +151,15 @@ def get_earning_components(doctype, txt, searchfield, start, page_len, filters): return {} employee = filters['employee'] date = filters['date'] - salary_structure = get_assigned_salary_sturecture(employee, date) + salary_structure = get_assigned_salary_structure(employee, date) - if len(salary_structure) > 0: + if salary_structure: query = """select salary_component from `tabSalary Detail` where parent = '{salary_structure}' and is_flexible_benefit = 1 order by name""" return frappe.db.sql(query.format(**{ - "salary_structure": salary_structure[0][0] + "salary_structure": salary_structure })) return {} diff --git a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py index 809bf4061b..1aed7ce1f8 100644 --- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py +++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py @@ -6,9 +6,9 @@ from __future__ import unicode_literals import frappe from frappe import _ from frappe.model.document import Document -from erpnext.hr.doctype.employee_benefit_application.employee_benefit_application import get_max_benefits, get_assigned_salary_sturecture +from erpnext.hr.doctype.employee_benefit_application.employee_benefit_application import get_max_benefits from erpnext.hr.utils import get_payroll_period -from frappe.desk.reportview import get_match_cond +from erpnext.hr.doctype.salary_structure_assignment.salary_structure_assignment import get_assigned_salary_structure class EmployeeBenefitClaim(Document): def validate(self): @@ -53,9 +53,9 @@ class EmployeeBenefitClaim(Document): amount and previous claimed amount").format(self.employee, max_benefits, pro_rata_amount+claimed_amount-max_benefits)) def get_benefit_pro_rata_ratio_amount(self): - sal_struct_name = get_assigned_salary_sturecture(self.employee, self.claim_date) - if len(sal_struct_name) > 0: - sal_struct = frappe.get_doc("Salary Structure", sal_struct_name[0][0]) + sal_struct_name = get_assigned_salary_structure(self.employee, self.claim_date) + if sal_struct_name: + sal_struct = frappe.get_doc("Salary Structure", sal_struct_name) total_pro_rata_max = 0 benefit_amount_total = 0 for sal_struct_row in sal_struct.get("earnings"): From 9416ac4ad4499ab00c56df440bb2baa3a7cffe24 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Fri, 25 May 2018 14:46:31 +0530 Subject: [PATCH 28/29] Leave Priod - fix - grant leave allocation filter by grade --- .../hr/doctype/leave_period/leave_period.json | 37 ++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/erpnext/hr/doctype/leave_period/leave_period.json b/erpnext/hr/doctype/leave_period/leave_period.json index 0f3cad4970..91f97e73fe 100644 --- a/erpnext/hr/doctype/leave_period/leave_period.json +++ b/erpnext/hr/doctype/leave_period/leave_period.json @@ -15,6 +15,7 @@ "fields": [ { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -41,10 +42,12 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -71,10 +74,12 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -100,10 +105,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -131,10 +138,12 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -161,10 +170,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -192,10 +203,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 1, @@ -222,10 +235,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -252,15 +267,17 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "employee_grade", + "fieldname": "grade", "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, @@ -283,10 +300,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -314,10 +333,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -345,10 +366,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -376,10 +399,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -406,10 +431,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -435,10 +462,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -465,6 +494,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, + "translatable": 0, "unique": 0 } ], @@ -478,7 +508,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-05-07 18:25:06.719932", + "modified": "2018-05-25 14:43:02.871669", "modified_by": "Administrator", "module": "HR", "name": "Leave Period", @@ -487,7 +517,6 @@ "permissions": [ { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 1, @@ -507,7 +536,6 @@ }, { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 1, @@ -527,7 +555,6 @@ }, { "amend": 0, - "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 1, From e6eef3085c5708c5165fcbd0af59221bf686831a Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Fri, 25 May 2018 15:20:50 +0530 Subject: [PATCH 29/29] Remove unused imports --- .../employee_benefit_application.py | 2 +- erpnext/hr/doctype/salary_component/salary_component.py | 2 -- 2 files changed, 1 insertion(+), 3 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 0c39b33d2c..2d33ce843a 100644 --- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py +++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe from frappe import _ -from frappe.utils import nowdate, date_diff, getdate +from frappe.utils import date_diff, getdate from frappe.model.document import Document from erpnext.hr.doctype.payroll_period.payroll_period import get_payroll_period_days from erpnext.hr.doctype.salary_structure_assignment.salary_structure_assignment import get_assigned_salary_structure diff --git a/erpnext/hr/doctype/salary_component/salary_component.py b/erpnext/hr/doctype/salary_component/salary_component.py index 22b5376683..7c926314a2 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.py +++ b/erpnext/hr/doctype/salary_component/salary_component.py @@ -3,8 +3,6 @@ # For license information, please see license.txt 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