Employee benefit - Last payroll period benefit (#14634)
* Employee benefit - Last payroll period benefit * Method name refactor
This commit is contained in:
parent
00f0f0f5fc
commit
b64161a389
@ -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
|
||||
|
@ -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")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user