Employee benefit - Late employee benefit application (#14465)
* HR Utils - get salary slip total benefit given for a payroll period * Late employee benefit application * Additional Salary - code refactor - get_amount * new line in salary detail json * Employee benefit late application - validation refactor * Codacy fix
This commit is contained in:
parent
2354c1eba3
commit
8d66f1e45d
@ -25,11 +25,6 @@ class AdditionalSalary(Document):
|
||||
frappe.throw(_("To date can not greater than employee's relieving date"))
|
||||
|
||||
def get_amount(self, sal_start_date, sal_end_date):
|
||||
# If additional salary dates in between the salary slip dates
|
||||
# then return complete additional salary amount
|
||||
if getdate(sal_start_date) <= getdate(self.from_date) <= getdate(sal_end_date)\
|
||||
and getdate(sal_end_date) >= getdate(self.to_date) >= getdate(sal_start_date):
|
||||
return self.amount
|
||||
start_date = getdate(sal_start_date)
|
||||
end_date = getdate(sal_end_date)
|
||||
total_days = date_diff(getdate(self.to_date), getdate(self.from_date)) + 1
|
||||
@ -38,12 +33,9 @@ class AdditionalSalary(Document):
|
||||
start_date = getdate(self.from_date)
|
||||
if getdate(sal_end_date) > getdate(self.to_date):
|
||||
end_date = getdate(self.to_date)
|
||||
no_of_days = date_diff(getdate(end_date), getdate(start_date))
|
||||
no_of_days = date_diff(getdate(end_date), getdate(start_date)) + 1
|
||||
return amount_per_day * no_of_days
|
||||
|
||||
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_additional_salary_component(employee, start_date, end_date):
|
||||
additional_components = frappe.db.sql("""
|
||||
|
@ -11,25 +11,53 @@ frappe.ui.form.on('Employee Benefit Application', {
|
||||
});
|
||||
},
|
||||
employee: function(frm) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
var method, args;
|
||||
if(frm.doc.employee && frm.doc.date && frm.doc.payroll_period){
|
||||
method = "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_max_benefits_remaining";
|
||||
args = {
|
||||
employee: frm.doc.employee,
|
||||
on_date: frm.doc.date,
|
||||
payroll_period: frm.doc.payroll_period
|
||||
};
|
||||
get_max_benefits(frm, method, args);
|
||||
}
|
||||
else if(frm.doc.employee && frm.doc.date){
|
||||
method = "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_max_benefits";
|
||||
args = {
|
||||
employee: frm.doc.employee,
|
||||
on_date: frm.doc.date
|
||||
};
|
||||
get_max_benefits(frm, method, args);
|
||||
}
|
||||
},
|
||||
payroll_period: function(frm) {
|
||||
var method, args;
|
||||
if(frm.doc.employee && frm.doc.date && frm.doc.payroll_period){
|
||||
method = "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_max_benefits_remaining";
|
||||
args = {
|
||||
employee: frm.doc.employee,
|
||||
on_date: frm.doc.date,
|
||||
payroll_period: frm.doc.payroll_period
|
||||
};
|
||||
get_max_benefits(frm, method, args);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var get_max_benefits=function(frm, method, args) {
|
||||
frappe.call({
|
||||
method: method,
|
||||
args: args,
|
||||
callback: function (data) {
|
||||
if(!data.exc){
|
||||
if(data.message){
|
||||
frm.set_value("max_benefits", data.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
frappe.ui.form.on("Employee Benefit Application Detail",{
|
||||
amount: function(frm) {
|
||||
calculate_all(frm.doc);
|
||||
|
@ -5,10 +5,11 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import date_diff, getdate
|
||||
from frappe.utils import date_diff, getdate, rounded
|
||||
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
|
||||
from erpnext.hr.utils import get_sal_slip_total_benefit_given
|
||||
|
||||
class EmployeeBenefitApplication(Document):
|
||||
def validate(self):
|
||||
@ -41,9 +42,10 @@ class EmployeeBenefitApplication(Document):
|
||||
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:
|
||||
elif non_pro_rata_amount > 0 and non_pro_rata_amount < rounded(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:
|
||||
@ -65,7 +67,9 @@ class EmployeeBenefitApplication(Document):
|
||||
for employee_benefit in self.employee_benefits:
|
||||
if employee_benefit.earning_component == earning_component_name:
|
||||
benefit_amount += employee_benefit.amount
|
||||
if benefit_amount > max_benefit_amount:
|
||||
prev_sal_slip_flexi_amount = get_sal_slip_total_benefit_given(self.employee, frappe.get_doc("Payroll Period", self.payroll_period), earning_component_name)
|
||||
benefit_amount += prev_sal_slip_flexi_amount
|
||||
if rounded(benefit_amount, 2) > max_benefit_amount:
|
||||
frappe.throw(_("Maximum benefit amount of component {0} exceeds {1}").format(earning_component_name, max_benefit_amount))
|
||||
|
||||
def validate_duplicate_on_payroll_period(self):
|
||||
@ -87,10 +91,17 @@ def get_max_benefits(employee, on_date):
|
||||
max_benefits = frappe.db.get_value("Salary Structure", sal_struct, "max_benefits")
|
||||
if max_benefits > 0:
|
||||
return max_benefits
|
||||
else:
|
||||
frappe.throw(_("Employee {0} has no max benefits in salary structure {1}").format(employee, sal_struct[0][0]))
|
||||
else:
|
||||
frappe.throw(_("Employee {0} has no salary structure assigned").format(employee))
|
||||
return False
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_max_benefits_remaining(employee, on_date, payroll_period):
|
||||
max_benefits = get_max_benefits(employee, on_date)
|
||||
if max_benefits and max_benefits > 0:
|
||||
payroll_period_obj = frappe.get_doc("Payroll Period", payroll_period)
|
||||
# Get all salary slip flexi amount in the payroll period
|
||||
prev_sal_slip_flexi_total = get_sal_slip_total_benefit_given(employee, payroll_period_obj)
|
||||
return max_benefits - prev_sal_slip_flexi_total
|
||||
return max_benefits
|
||||
|
||||
def get_benefit_component_amount(employee, start_date, end_date, struct_row, sal_struct):
|
||||
# Considering there is only one application for an year
|
||||
|
@ -13,6 +13,8 @@ from erpnext.hr.doctype.salary_structure_assignment.salary_structure_assignment
|
||||
class EmployeeBenefitClaim(Document):
|
||||
def validate(self):
|
||||
max_benefits = get_max_benefits(self.employee, self.claim_date)
|
||||
if not max_benefits or max_benefits <= 0:
|
||||
frappe.throw(_("Employee {0} has no maximum benefit amount").format(self.employee))
|
||||
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)
|
||||
|
@ -606,4 +606,4 @@
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +107,8 @@ class SalarySlip(TransactionBase):
|
||||
'depends_on_lwp' : struct_row.depends_on_lwp,
|
||||
'salary_component' : struct_row.salary_component,
|
||||
'abbr' : struct_row.abbr,
|
||||
'do_not_include_in_total' : struct_row.do_not_include_in_total
|
||||
'do_not_include_in_total' : struct_row.do_not_include_in_total,
|
||||
'is_flexible_benefit': struct_row.is_flexible_benefit
|
||||
})
|
||||
else:
|
||||
component_row.amount = amount
|
||||
|
@ -350,3 +350,31 @@ def get_annual_component_pay(frequency, amount):
|
||||
return amount * 12
|
||||
elif frequency == "Bimonthly":
|
||||
return amount * 6
|
||||
|
||||
def get_sal_slip_total_benefit_given(employee, payroll_period, component=False):
|
||||
total_given_benefit_amount = 0
|
||||
query = """
|
||||
select sum(sd.amount) as 'total_amount'
|
||||
from `tabSalary Slip` ss, `tabSalary Detail` sd
|
||||
where ss.employee=%(employee)s
|
||||
and ss.docstatus = 1 and ss.name = sd.parent
|
||||
and sd.is_flexible_benefit = 1 and sd.parentfield = "earnings"
|
||||
and sd.parenttype = "Salary Slip"
|
||||
and (ss.start_date between %(start_date)s and %(end_date)s
|
||||
or ss.end_date between %(start_date)s and %(end_date)s
|
||||
or (ss.start_date < %(start_date)s and ss.end_date > %(end_date)s))
|
||||
"""
|
||||
|
||||
if component:
|
||||
query += "and sd.salary_component = %(component)s"
|
||||
|
||||
sum_of_given_benefit = frappe.db.sql(query, {
|
||||
'employee': employee,
|
||||
'start_date': payroll_period.start_date,
|
||||
'end_date': payroll_period.end_date,
|
||||
'component': component
|
||||
}, as_dict=True)
|
||||
|
||||
if sum_of_given_benefit and sum_of_given_benefit[0].total_amount > 0:
|
||||
total_given_benefit_amount = sum_of_given_benefit[0].total_amount
|
||||
return total_given_benefit_amount
|
||||
|
Loading…
x
Reference in New Issue
Block a user