mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-30 02:14:48 +00:00
Merge pull request #14096 from ESS-LLP/jam_enterprise_emp_benefit
Employee Benefit
This commit is contained in:
@@ -2,7 +2,55 @@
|
|||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on('Employee Benefit Application', {
|
frappe.ui.form.on('Employee Benefit Application', {
|
||||||
refresh: function(frm) {
|
setup: function(frm) {
|
||||||
|
frm.set_query("earning_component", "employee_benefits", function() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
type: "Earning",
|
||||||
|
is_flexible_benefit: true,
|
||||||
|
disabled: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
frappe.ui.form.on("Employee Benefit Application Detail",{
|
||||||
|
amount: function(frm, cdt, cdn) {
|
||||||
|
calculate_all(frm.doc, cdt, cdn);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var calculate_all = function(doc, dt, dn) {
|
||||||
|
var tbl = doc.employee_benefits || [];
|
||||||
|
var pro_rata_dispensed_amount = 0;
|
||||||
|
var total_amount = 0;
|
||||||
|
for(var i = 0; i < tbl.length; i++){
|
||||||
|
if(cint(tbl[i].amount) > 0) {
|
||||||
|
total_amount += flt(tbl[i].amount);
|
||||||
|
}
|
||||||
|
if(tbl[i].is_pro_rata_applicable == 1){
|
||||||
|
pro_rata_dispensed_amount += flt(tbl[i].amount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
doc.total_amount = total_amount;
|
||||||
|
doc.remainig_benefits = doc.max_benefits - total_amount;
|
||||||
|
doc.pro_rata_dispensed_amount = pro_rata_dispensed_amount;
|
||||||
|
refresh_many(['pro_rata_dispensed_amount', 'total_amount','remainig_benefits']);
|
||||||
|
};
|
||||||
|
|||||||
@@ -77,6 +77,68 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "max_benefits",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"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": "Max Benefits (Yearly)",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"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,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "remainig_benefits",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"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": "Remainig Benefits (Yearly)",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"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_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@@ -107,6 +169,38 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"default": "Today",
|
||||||
|
"fieldname": "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": "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_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@@ -139,6 +233,68 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "pro_rata_dispensed_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"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": "Pro Rata Dispensed Amount",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"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,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "total_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"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": "Total Amount",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"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_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@@ -243,7 +399,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-04-14 15:35:20.748301",
|
"modified": "2018-05-11 16:58:31.662866",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Employee Benefit Application",
|
"name": "Employee Benefit Application",
|
||||||
|
|||||||
@@ -4,7 +4,132 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from frappe.utils import nowdate, date_diff, getdate
|
||||||
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
|
||||||
|
|
||||||
class EmployeeBenefitApplication(Document):
|
class EmployeeBenefitApplication(Document):
|
||||||
pass
|
def validate(self):
|
||||||
|
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
|
||||||
|
for employee_benefit in self.employee_benefits:
|
||||||
|
self.validate_max_benefit(employee_benefit.earning_component)
|
||||||
|
max_benefit_amount += employee_benefit.amount
|
||||||
|
if max_benefit_amount > self.max_benefits:
|
||||||
|
frappe.throw(_("Maximum benefit amount of employee {0} exceeds {1}").format(self.employee, self.max_benefits))
|
||||||
|
|
||||||
|
def validate_max_benefit(self, earning_component_name):
|
||||||
|
max_benefit_amount = frappe.db.get_value("Salary Component", earning_component_name, "max_benefit_amount")
|
||||||
|
benefit_amount = 0
|
||||||
|
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:
|
||||||
|
frappe.throw(_("Maximum benefit amount of component {0} exceeds {1}").format(earning_component_name, max_benefit_amount))
|
||||||
|
|
||||||
|
def validate_duplicate_on_payroll_period(self):
|
||||||
|
application = frappe.db.exists(
|
||||||
|
"Employee Benefit Application",
|
||||||
|
{
|
||||||
|
'employee': self.employee,
|
||||||
|
'payroll_period': self.payroll_period,
|
||||||
|
'docstatus': 1
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if application:
|
||||||
|
frappe.throw(_("Employee {0} already submited an apllication {1} for the payroll period {2}").format(self.employee, application, self.payroll_period))
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_max_benefits(employee, on_date):
|
||||||
|
sal_struct = get_assigned_salary_sturecture(employee, on_date)
|
||||||
|
if sal_struct:
|
||||||
|
max_benefits = frappe.db.get_value("Salary Structure", sal_struct[0][0], "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))
|
||||||
|
|
||||||
|
|
||||||
|
@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_employee_benefit_application(salary_slip):
|
||||||
|
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
|
||||||
|
})
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
def get_components(employee_benefit_application, salary_slip):
|
||||||
|
salary_components_array = []
|
||||||
|
group_component_amount = {}
|
||||||
|
payroll_period_days = get_payroll_period_days(salary_slip.start_date, salary_slip.end_date, salary_slip.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)
|
||||||
|
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 len(salary_components_array) > 0:
|
||||||
|
return salary_components_array
|
||||||
|
return 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
|
||||||
|
total_amount = amount_per_day * salary_slip_days
|
||||||
|
if total_amount > amount:
|
||||||
|
return amount
|
||||||
|
else:
|
||||||
|
return total_amount
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
# See license.txt
|
# See license.txt
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import frappe
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
class TestEmployeeBenefitApplication(unittest.TestCase):
|
class TestEmployeeBenefitApplication(unittest.TestCase):
|
||||||
|
|||||||
@@ -45,6 +45,38 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "is_pro_rata_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 Pro-rata Applicable",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "earning_component.is_pro_rata_applicable",
|
||||||
|
"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_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@@ -87,7 +119,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-04-13 19:32:35.064272",
|
"modified": "2018-05-15 12:03:25.545041",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Employee Benefit Application Detail",
|
"name": "Employee Benefit Application Detail",
|
||||||
|
|||||||
@@ -2,7 +2,15 @@
|
|||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on('Employee Benefit Claim', {
|
frappe.ui.form.on('Employee Benefit Claim', {
|
||||||
refresh: function(frm) {
|
setup: function(frm) {
|
||||||
|
frm.set_query("earning_component", function() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
type: "Earning",
|
||||||
|
is_flexible_benefit: true,
|
||||||
|
disabled: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -188,6 +188,7 @@
|
|||||||
"label": "Max Amount Eligible",
|
"label": "Max Amount Eligible",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
|
"options": "earning_component.max_benefit_amount",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
@@ -201,6 +202,38 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "is_pro_rata_applicable",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"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": "Is Pro-Rata Applicable",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "earning_component.is_pro_rata_applicable",
|
||||||
|
"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_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@@ -367,7 +400,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-04-14 15:38:41.538646",
|
"modified": "2018-05-16 17:21:25.598531",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Employee Benefit Claim",
|
"name": "Employee Benefit Claim",
|
||||||
@@ -460,4 +493,4 @@
|
|||||||
"title_field": "employee_name",
|
"title_field": "employee_name",
|
||||||
"track_changes": 1,
|
"track_changes": 1,
|
||||||
"track_seen": 0
|
"track_seen": 0
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,62 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
|
from frappe import _
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
from erpnext.hr.doctype.employee_benefit_application.employee_benefit_application import get_max_benefits
|
||||||
|
|
||||||
class EmployeeBenefitClaim(Document):
|
class EmployeeBenefitClaim(Document):
|
||||||
pass
|
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)
|
||||||
|
if self.claimed_amount > max_benefits:
|
||||||
|
frappe.throw(_("Maximum benefit amount of employee {0} exceeds {1}").format(self.employee, max_benefits))
|
||||||
|
|
||||||
|
|
||||||
|
def get_employee_benefit_claim(salary_slip):
|
||||||
|
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
|
||||||
|
})
|
||||||
|
|
||||||
|
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
|
||||||
|
return False
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
# See license.txt
|
# See license.txt
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import frappe
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
class TestEmployeeBenefitClaim(unittest.TestCase):
|
class TestEmployeeBenefitClaim(unittest.TestCase):
|
||||||
|
|||||||
@@ -4,7 +4,26 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
|
from frappe.utils import date_diff, getdate
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class PayrollPeriod(Document):
|
class PayrollPeriod(Document):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
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
|
||||||
|
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)
|
||||||
|
)""", {
|
||||||
|
'company': company,
|
||||||
|
'start_date': start_date,
|
||||||
|
'end_date': end_date
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(payroll_period_dates) > 0:
|
||||||
|
return date_diff(getdate(payroll_period_dates[0][1]), getdate(payroll_period_dates[0][0])) + 1
|
||||||
|
|||||||
@@ -12,7 +12,15 @@ frappe.ui.form.on('Salary Component', {
|
|||||||
"is_group": 0,
|
"is_group": 0,
|
||||||
"company": d.company
|
"company": d.company
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
})
|
});
|
||||||
|
frm.set_query("earning_component_group", function(frm) {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
"is_group": 1,
|
||||||
|
"is_flexible_benefit": 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -108,70 +108,6 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 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_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@@ -366,6 +302,38 @@
|
|||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"depends_on": "is_flexible_benefit",
|
"depends_on": "is_flexible_benefit",
|
||||||
|
"fieldname": "is_group",
|
||||||
|
"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 Group",
|
||||||
|
"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.is_flexible_benefit && !doc.is_group && !doc.flexi_default",
|
||||||
"fieldname": "earning_component_group",
|
"fieldname": "earning_component_group",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -454,6 +422,38 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"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_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@@ -618,7 +618,6 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"depends_on": "is_payable",
|
|
||||||
"fieldname": "section_break_5",
|
"fieldname": "section_break_5",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -1002,7 +1001,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-05-16 12:15:43.117948",
|
"modified": "2018-05-16 12:27:03.005070",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Salary Component",
|
"name": "Salary Component",
|
||||||
@@ -1037,4 +1036,4 @@
|
|||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 0,
|
"track_changes": 0,
|
||||||
"track_seen": 0
|
"track_seen": 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,27 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
|
from frappe import _
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.model.naming import append_number_if_name_exists
|
from frappe.model.naming import append_number_if_name_exists
|
||||||
|
|
||||||
class SalaryComponent(Document):
|
class SalaryComponent(Document):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_abbr()
|
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):
|
def validate_abbr(self):
|
||||||
if not self.salary_component_abbr:
|
if not self.salary_component_abbr:
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
|
|||||||
from erpnext.utilities.transaction_base import TransactionBase
|
from erpnext.utilities.transaction_base import TransactionBase
|
||||||
from frappe.utils.background_jobs import enqueue
|
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.doctype.additional_salary_component.additional_salary_component import get_additional_salary_component
|
||||||
|
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
|
from erpnext.hr.utils import get_payroll_period
|
||||||
|
|
||||||
class SalarySlip(TransactionBase):
|
class SalarySlip(TransactionBase):
|
||||||
@@ -68,7 +71,57 @@ class SalarySlip(TransactionBase):
|
|||||||
if additional_components:
|
if additional_components:
|
||||||
for additional_component in additional_components:
|
for additional_component in additional_components:
|
||||||
additional_component = frappe._dict(additional_component)
|
additional_component = frappe._dict(additional_component)
|
||||||
self.update_component_row(frappe._dict(additional_component.struct_row), additional_component.amount, "earnings")
|
amount = self.update_amount_for_other_component(frappe._dict(additional_component.struct_row).salary_component, additional_component.amount)
|
||||||
|
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")
|
||||||
|
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"))
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
def update_amount_for_other_component(self, salary_component, new_amount):
|
||||||
|
amount = new_amount
|
||||||
|
for d in self.get("earnings"):
|
||||||
|
if d.salary_component == salary_component:
|
||||||
|
d.amount += new_amount
|
||||||
|
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):
|
def update_component_row(self, struct_row, amount, key):
|
||||||
component_row = None
|
component_row = None
|
||||||
@@ -181,6 +234,7 @@ class SalarySlip(TransactionBase):
|
|||||||
st_name = frappe.db.sql("""select salary_structure from `tabSalary Structure Assignment`
|
st_name = frappe.db.sql("""select salary_structure from `tabSalary Structure Assignment`
|
||||||
where employee=%s and (from_date <= %s or from_date <= %s)
|
where employee=%s and (from_date <= %s or from_date <= %s)
|
||||||
and (to_date is null or to_date >= %s or to_date >= %s)
|
and (to_date is null or to_date >= %s or to_date >= %s)
|
||||||
|
and docstatus = 1
|
||||||
and salary_structure in (select name from `tabSalary Structure`
|
and salary_structure in (select name from `tabSalary Structure`
|
||||||
where is_active = 'Yes'%s)
|
where is_active = 'Yes'%s)
|
||||||
"""% ('%s', '%s', '%s','%s','%s', cond),(self.employee, self.start_date, joining_date, self.end_date, relieving_date))
|
"""% ('%s', '%s', '%s','%s','%s', cond),(self.employee, self.start_date, joining_date, self.end_date, relieving_date))
|
||||||
|
|||||||
@@ -123,15 +123,6 @@ frappe.ui.form.on('Salary Structure', {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
frappe.ui.form.on('Salary Structure Employee', {
|
|
||||||
from_date: function(frm, cdt, cdn) {
|
|
||||||
validate_date(frm, cdt, cdn);
|
|
||||||
},
|
|
||||||
to_date: function(frm, cdt, cdn) {
|
|
||||||
validate_date(frm, cdt, cdn);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var validate_date = function(frm, cdt, cdn) {
|
var validate_date = function(frm, cdt, cdn) {
|
||||||
var doc = locals[cdt][cdn];
|
var doc = locals[cdt][cdn];
|
||||||
if(doc.to_date && doc.from_date) {
|
if(doc.to_date && doc.from_date) {
|
||||||
|
|||||||
Reference in New Issue
Block a user