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"))
|
frappe.throw(_("To date can not greater than employee's relieving date"))
|
||||||
|
|
||||||
def get_amount(self, sal_start_date, sal_end_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)
|
start_date = getdate(sal_start_date)
|
||||||
end_date = getdate(sal_end_date)
|
end_date = getdate(sal_end_date)
|
||||||
total_days = date_diff(getdate(self.to_date), getdate(self.from_date)) + 1
|
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)
|
start_date = getdate(self.from_date)
|
||||||
if getdate(sal_end_date) > getdate(self.to_date):
|
if getdate(sal_end_date) > getdate(self.to_date):
|
||||||
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
|
return amount_per_day * no_of_days
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_additional_salary_component(employee, start_date, end_date):
|
def get_additional_salary_component(employee, start_date, end_date):
|
||||||
additional_components = frappe.db.sql("""
|
additional_components = frappe.db.sql("""
|
||||||
|
|||||||
@ -11,25 +11,53 @@ frappe.ui.form.on('Employee Benefit Application', {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
employee: function(frm) {
|
employee: function(frm) {
|
||||||
if(frm.doc.employee && frm.doc.date){
|
var method, args;
|
||||||
frappe.call({
|
if(frm.doc.employee && frm.doc.date && frm.doc.payroll_period){
|
||||||
method: "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_max_benefits",
|
method = "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_max_benefits_remaining";
|
||||||
args:{
|
args = {
|
||||||
employee: frm.doc.employee,
|
employee: frm.doc.employee,
|
||||||
on_date: frm.doc.date
|
on_date: frm.doc.date,
|
||||||
},
|
payroll_period: frm.doc.payroll_period
|
||||||
callback: function (data) {
|
};
|
||||||
if(!data.exc){
|
get_max_benefits(frm, method, args);
|
||||||
if(data.message){
|
}
|
||||||
frm.set_value("max_benefits", data.message);
|
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",{
|
frappe.ui.form.on("Employee Benefit Application Detail",{
|
||||||
amount: function(frm) {
|
amount: function(frm) {
|
||||||
calculate_all(frm.doc);
|
calculate_all(frm.doc);
|
||||||
|
|||||||
@ -5,10 +5,11 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
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 frappe.model.document import Document
|
||||||
from erpnext.hr.doctype.payroll_period.payroll_period import get_payroll_period_days
|
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.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):
|
class EmployeeBenefitApplication(Document):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
@ -41,9 +42,10 @@ class EmployeeBenefitApplication(Document):
|
|||||||
pro_rata_amount += max_benefit_amount
|
pro_rata_amount += max_benefit_amount
|
||||||
else:
|
else:
|
||||||
non_pro_rata_amount += max_benefit_amount
|
non_pro_rata_amount += max_benefit_amount
|
||||||
|
|
||||||
if pro_rata_amount == 0 and non_pro_rata_amount == 0:
|
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))
|
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 \
|
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))
|
as pro-rata component").format(non_pro_rata_amount, self.remainig_benefits - non_pro_rata_amount))
|
||||||
elif non_pro_rata_amount == 0:
|
elif non_pro_rata_amount == 0:
|
||||||
@ -65,7 +67,9 @@ class EmployeeBenefitApplication(Document):
|
|||||||
for employee_benefit in self.employee_benefits:
|
for employee_benefit in self.employee_benefits:
|
||||||
if employee_benefit.earning_component == earning_component_name:
|
if employee_benefit.earning_component == earning_component_name:
|
||||||
benefit_amount += employee_benefit.amount
|
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))
|
frappe.throw(_("Maximum benefit amount of component {0} exceeds {1}").format(earning_component_name, max_benefit_amount))
|
||||||
|
|
||||||
def validate_duplicate_on_payroll_period(self):
|
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")
|
max_benefits = frappe.db.get_value("Salary Structure", sal_struct, "max_benefits")
|
||||||
if max_benefits > 0:
|
if max_benefits > 0:
|
||||||
return max_benefits
|
return max_benefits
|
||||||
else:
|
return False
|
||||||
frappe.throw(_("Employee {0} has no max benefits in salary structure {1}").format(employee, sal_struct[0][0]))
|
|
||||||
else:
|
@frappe.whitelist()
|
||||||
frappe.throw(_("Employee {0} has no salary structure assigned").format(employee))
|
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):
|
def get_benefit_component_amount(employee, start_date, end_date, struct_row, sal_struct):
|
||||||
# Considering there is only one application for an year
|
# 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):
|
class EmployeeBenefitClaim(Document):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
max_benefits = get_max_benefits(self.employee, self.claim_date)
|
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"))
|
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_component(payroll_period)
|
||||||
self.validate_max_benefit_for_sal_struct(max_benefits)
|
self.validate_max_benefit_for_sal_struct(max_benefits)
|
||||||
|
|||||||
@ -107,7 +107,8 @@ class SalarySlip(TransactionBase):
|
|||||||
'depends_on_lwp' : struct_row.depends_on_lwp,
|
'depends_on_lwp' : struct_row.depends_on_lwp,
|
||||||
'salary_component' : struct_row.salary_component,
|
'salary_component' : struct_row.salary_component,
|
||||||
'abbr' : struct_row.abbr,
|
'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:
|
else:
|
||||||
component_row.amount = amount
|
component_row.amount = amount
|
||||||
|
|||||||
@ -350,3 +350,31 @@ def get_annual_component_pay(frequency, amount):
|
|||||||
return amount * 12
|
return amount * 12
|
||||||
elif frequency == "Bimonthly":
|
elif frequency == "Bimonthly":
|
||||||
return amount * 6
|
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