Employee benefit - Last payroll period benefit (#14634)

* Employee benefit - Last payroll period benefit

* Method name refactor
This commit is contained in:
Jamsheer 2018-06-22 17:27:54 +05:30 committed by Nabin Hait
parent 00f0f0f5fc
commit b64161a389
2 changed files with 122 additions and 35 deletions

View File

@ -45,39 +45,19 @@ 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
# Get pro_rata_amount if there is no application,
# 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
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)
pro_rata_amount = get_benefit_pro_rata_ratio_amount(self.employee, self.claim_date, sal_struct)
claimed_amount += get_previous_claimed_amount(self.employee, payroll_period, non_pro_rata = 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_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"):
pay_against_benefit_claim, max_benefit_amount = frappe.db.get_value("Salary Component", sal_struct_row.salary_component, ["pay_against_benefit_claim", "max_benefit_amount"])
if sal_struct_row.is_flexible_benefit == 1 and pay_against_benefit_claim != 1:
total_pro_rata_max += max_benefit_amount
if total_pro_rata_max > 0:
for sal_struct_row in sal_struct.get("earnings"):
pay_against_benefit_claim, max_benefit_amount = frappe.db.get_value("Salary Component", sal_struct_row.salary_component, ["pay_against_benefit_claim", "max_benefit_amount"])
if sal_struct_row.is_flexible_benefit == 1 and pay_against_benefit_claim != 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",
@ -91,23 +71,111 @@ class EmployeeBenefitClaim(Document):
return frappe.db.get_value("Employee Benefit Application", application, "pro_rata_dispensed_amount")
return False
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`
def get_benefit_pro_rata_ratio_amount(employee, on_date, sal_struct):
total_pro_rata_max = 0
benefit_amount_total = 0
for sal_struct_row in sal_struct.get("earnings"):
pay_against_benefit_claim, max_benefit_amount = frappe.db.get_value("Salary Component", sal_struct_row.salary_component, ["pay_against_benefit_claim", "max_benefit_amount"])
if sal_struct_row.is_flexible_benefit == 1 and pay_against_benefit_claim != 1:
total_pro_rata_max += max_benefit_amount
if total_pro_rata_max > 0:
for sal_struct_row in sal_struct.get("earnings"):
pay_against_benefit_claim, max_benefit_amount = frappe.db.get_value("Salary Component", sal_struct_row.salary_component, ["pay_against_benefit_claim", "max_benefit_amount"])
if sal_struct_row.is_flexible_benefit == 1 and pay_against_benefit_claim != 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
def get_benefit_claim_amount(employee, start_date, end_date, salary_component):
query = """select claimed_amount from `tabEmployee Benefit Claim`
where employee=%(employee)s
and docstatus = 1 and pay_against_benefit_claim = 1
and earning_component = %(earning_component)s
and (claim_date between %(start_date)s and %(end_date)s)
""", {
"""
if not start_date:
query += "and claim_date <= %(end_date)s"
else:
query += "and (claim_date between %(start_date)s and %(end_date)s)"
if salary_component:
query += "and earning_component = %(earning_component)s"
benefit_claim_details = frappe.db.sql(query, {
'employee': employee,
'start_date': start_date,
'end_date': end_date,
'earning_component': struct_row.salary_component
'earning_component': salary_component
}, as_dict = True)
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
def get_total_benefit_dispensed(employee, sal_struct, sal_slip_start_date, payroll_period):
pro_rata_amount = 0
claimed_amount = 0
application = frappe.db.exists(
"Employee Benefit Application",
{
'employee': employee,
'payroll_period': payroll_period.name,
'docstatus': 1
}
)
if application:
application_obj = frappe.get_doc("Employee Benefit Application", application)
pro_rata_amount = application_obj.pro_rata_dispensed_amount + application_obj.max_benefits - application_obj.remainig_benefits
else:
pro_rata_amount = get_benefit_pro_rata_ratio_amount(employee, sal_slip_start_date, sal_struct)
claimed_amount += get_benefit_claim_amount(employee, payroll_period.start_date, payroll_period.end_date, False)
return claimed_amount + pro_rata_amount
def get_last_payroll_period_benefits(employee, sal_slip_start_date, sal_slip_end_date, current_flexi_amount, payroll_period, sal_struct):
max_benefits = get_max_benefits(employee, payroll_period.end_date)
if not max_benefits:
max_benefits = 0
remainig_benefits = max_benefits - get_total_benefit_dispensed(employee, sal_struct, sal_slip_start_date, payroll_period)
if remainig_benefits > 0:
have_remaining = True
# Set the remainig benefits to flexi non pro-rata component in the salary structure
salary_components_array = []
for d in sal_struct.get("earnings"):
if d.is_flexible_benefit == 1:
salary_component = frappe.get_doc("Salary Component", d.salary_component)
if salary_component.is_pro_rata_applicable != 1:
claimed_amount = get_benefit_claim_amount(employee, payroll_period.start_date, sal_slip_end_date, d.salary_component)
amount_fit_to_component = salary_component.max_benefit_amount - claimed_amount
if amount_fit_to_component > 0:
if remainig_benefits > amount_fit_to_component:
amount = amount_fit_to_component
remainig_benefits -= amount_fit_to_component
else:
amount = remainig_benefits
have_remaining = False
current_claimed_amount = get_benefit_claim_amount(employee, sal_slip_start_date, sal_slip_end_date, d.salary_component)
amount += current_claimed_amount
struct_row = {}
salary_components_dict = {}
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
struct_row['is_tax_applicable'] = salary_component.is_tax_applicable,
struct_row['is_flexible_benefit'] = salary_component.is_flexible_benefit,
struct_row['variable_based_on_taxable_salary'] = salary_component.variable_based_on_taxable_salary
salary_components_dict['amount'] = amount
salary_components_dict['struct_row'] = struct_row
salary_components_array.append(salary_components_dict)
if not have_remaining:
break
if len(salary_components_array) > 0:
return salary_components_array
return False

View File

@ -16,7 +16,7 @@ from frappe.utils.background_jobs import enqueue
from erpnext.hr.doctype.additional_salary.additional_salary 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_benefit_component_amount
from erpnext.hr.doctype.employee_benefit_claim.employee_benefit_claim import get_benefit_claim_amount
from erpnext.hr.doctype.employee_benefit_claim.employee_benefit_claim import get_benefit_claim_amount, get_last_payroll_period_benefits
class SalarySlip(TransactionBase):
def __init__(self, *args, **kwargs):
@ -80,6 +80,8 @@ class SalarySlip(TransactionBase):
key = "deductions"
self.update_component_row(frappe._dict(additional_component.struct_row), amount, key)
self.get_last_payroll_period_benefit()
# Calculate variable_based_on_taxable_salary after all components updated in salary slip
for struct_row in self._salary_structure_doc.get("deductions"):
if struct_row.variable_based_on_taxable_salary == 1:
@ -87,6 +89,23 @@ class SalarySlip(TransactionBase):
if tax_row and amount:
self.update_component_row(frappe._dict(tax_row), amount, "deductions")
def get_last_payroll_period_benefit(self):
payroll_period = get_payroll_period(self.start_date, self.end_date, self.company)
if payroll_period:
# Check for last payroll period
if (getdate(payroll_period.end_date) <= getdate(self.end_date)):
current_flexi_amount = 0
for d in self.get("earnings"):
if d.is_flexible_benefit == 1:
current_flexi_amount += d.amount
last_benefits = get_last_payroll_period_benefits(self.employee, self.start_date, self.end_date,\
current_flexi_amount, payroll_period, self._salary_structure_doc)
if last_benefits:
for last_benefit in last_benefits:
last_benefit = frappe._dict(last_benefit)
amount = last_benefit.amount
self.update_component_row(frappe._dict(last_benefit.struct_row), amount, "earnings")
def add_employee_flexi_benefits(self, struct_row):
if frappe.db.get_value("Salary Component", struct_row.salary_component, "pay_against_benefit_claim") != 1:
benefit_component_amount = get_benefit_component_amount(self.employee, self.start_date, self.end_date, \
@ -94,7 +113,7 @@ class SalarySlip(TransactionBase):
if benefit_component_amount:
self.update_component_row(struct_row, benefit_component_amount, "earnings")
else:
benefit_claim_amount = get_benefit_claim_amount(self.employee, self.start_date, self.end_date, struct_row)
benefit_claim_amount = get_benefit_claim_amount(self.employee, self.start_date, self.end_date, struct_row.salary_component)
if benefit_claim_amount:
self.update_component_row(struct_row, benefit_claim_amount, "earnings")