Salary Structure Refactor, Formula on Salary Component Master (#13967)
* Salary structure refactor * Salary Structure Assignment - filters applied * Formula on Salary Component Master * Salary Structure - filter updated, Salary Component - fields re-arranged * Payroll Entry - get_employee_list fix * Salary Structure Assignment - Validate Duplicate Assignment * Salary Structure Assignment - filters for salary structure
This commit is contained in:
parent
c53e35368d
commit
46b23f8e6e
@ -40,15 +40,16 @@ class PayrollEntry(Document):
|
||||
{"company": self.company, "salary_slip_based_on_timesheet":self.salary_slip_based_on_timesheet})
|
||||
|
||||
if sal_struct:
|
||||
cond += "and t2.parent IN %(sal_struct)s "
|
||||
cond += "and t2.salary_structure IN %(sal_struct)s "
|
||||
emp_list = frappe.db.sql("""
|
||||
select
|
||||
t1.name as employee, t1.employee_name, t1.department, t1.designation
|
||||
from
|
||||
`tabEmployee` t1, `tabSalary Structure Employee` t2
|
||||
`tabEmployee` t1, `tabSalary Structure Assignment` t2
|
||||
where
|
||||
t1.docstatus!=2
|
||||
and t1.name = t2.employee
|
||||
and t2.docstatus = 1
|
||||
%s """% cond, {"sal_struct": sal_struct}, as_dict=True)
|
||||
return emp_list
|
||||
|
||||
|
@ -610,6 +610,320 @@
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fieldname": "condition_and_formula",
|
||||
"fieldtype": "Section Break",
|
||||
"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": "Condition and Formula",
|
||||
"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,
|
||||
"fieldname": "condition",
|
||||
"fieldtype": "Code",
|
||||
"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": "Condition",
|
||||
"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,
|
||||
"description": "If selected, the value specified or calculated in this component will not contribute to the earnings or deductions. However, it's value can be referenced by other components that can be added or deducted. ",
|
||||
"fieldname": "statistical_component",
|
||||
"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": "Statistical 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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "depends_on_lwp",
|
||||
"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": "Depends on Leave Without Pay",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"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,
|
||||
"fieldname": "do_not_include_in_total",
|
||||
"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": "Do not include in total",
|
||||
"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": "amount_based_on_formula",
|
||||
"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": "Amount based on formula",
|
||||
"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.amount_based_on_formula!==0",
|
||||
"fieldname": "formula",
|
||||
"fieldtype": "Code",
|
||||
"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": "Formula",
|
||||
"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.amount_based_on_formula!==1",
|
||||
"fieldname": "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": "Amount",
|
||||
"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,
|
||||
"fieldname": "column_break_28",
|
||||
"fieldtype": "Column Break",
|
||||
"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,
|
||||
"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,
|
||||
"fieldname": "help",
|
||||
"fieldtype": "HTML",
|
||||
"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": "Help",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "<h3>Help</h3>\n\n<p>Notes:</p>\n\n<ol>\n<li>Use field <code>base</code> for using base salary of the Employee</li>\n<li>Use Salary Component abbreviations in conditions and formulas. <code>BS = Basic Salary</code></li>\n<li>Use field name for employee details in conditions and formulas. <code>Employment Type = employment_type</code><code>Branch = branch</code></li>\n<li>Use field name from Salary Slip in conditions and formulas. <code>Payment Days = payment_days</code><code>Leave without pay = leave_without_pay</code></li>\n<li>Direct Amount can also be entered based on Condtion. See example 3</li></ol>\n\n<h4>Examples</h4>\n<ol>\n<li>Calculating Basic Salary based on <code>base</code>\n<pre><code>Condition: base < 10000</code></pre>\n<pre><code>Formula: base * .2</code></pre></li>\n<li>Calculating HRA based on Basic Salary<code>BS</code> \n<pre><code>Condition: BS > 2000</code></pre>\n<pre><code>Formula: BS * .1</code></pre></li>\n<li>Calculating TDS based on Employment Type<code>employment_type</code> \n<pre><code>Condition: employment_type==\"Intern\"</code></pre>\n<pre><code>Amount: 1000</code></pre></li>\n</ol>",
|
||||
"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
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
@ -623,7 +937,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-04-27 13:23:34.503504",
|
||||
"modified": "2018-05-09 17:35:11.073733",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Salary Component",
|
||||
|
@ -104,8 +104,8 @@ class SalarySlip(TransactionBase):
|
||||
'''Returns data for evaluating formula'''
|
||||
data = frappe._dict()
|
||||
|
||||
data.update(frappe.get_doc("Salary Structure Employee",
|
||||
{"employee": self.employee, "parent": self.salary_structure}).as_dict())
|
||||
data.update(frappe.get_doc("Salary Structure Assignment",
|
||||
{"employee": self.employee, "salary_structure": self.salary_structure}).as_dict())
|
||||
|
||||
data.update(frappe.get_doc("Employee", self.employee).as_dict())
|
||||
data.update(self.as_dict())
|
||||
@ -166,10 +166,10 @@ class SalarySlip(TransactionBase):
|
||||
if self.payroll_frequency:
|
||||
cond = """and payroll_frequency = '%(payroll_frequency)s'""" % {"payroll_frequency": self.payroll_frequency}
|
||||
|
||||
st_name = frappe.db.sql("""select parent from `tabSalary Structure Employee`
|
||||
st_name = frappe.db.sql("""select salary_structure from `tabSalary Structure Assignment`
|
||||
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 parent in (select name from `tabSalary Structure`
|
||||
and salary_structure in (select name from `tabSalary Structure`
|
||||
where is_active = 'Yes'%s)
|
||||
"""% ('%s', '%s', '%s','%s','%s', cond),(self.employee, self.start_date, joining_date, self.end_date, relieving_date))
|
||||
|
||||
@ -327,7 +327,7 @@ class SalarySlip(TransactionBase):
|
||||
def sum_components(self, component_type, total_field):
|
||||
joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
|
||||
["date_of_joining", "relieving_date"])
|
||||
|
||||
|
||||
if not relieving_date:
|
||||
relieving_date = getdate(self.end_date)
|
||||
|
||||
@ -463,4 +463,4 @@ def unlink_ref_doc_from_salary_slip(ref_no):
|
||||
if linked_ss:
|
||||
for ss in linked_ss:
|
||||
ss_doc = frappe.get_doc("Salary Slip", ss)
|
||||
frappe.db.set_value("Salary Slip", ss_doc.name, "journal_entry", "")
|
||||
frappe.db.set_value("Salary Slip", ss_doc.name, "journal_entry", "")
|
||||
|
@ -7,6 +7,7 @@ import frappe
|
||||
import erpnext
|
||||
import calendar
|
||||
from erpnext.accounts.utils import get_fiscal_year
|
||||
from frappe.utils.make_random import get_random
|
||||
from frappe.utils import getdate, nowdate, add_days, add_months, flt
|
||||
from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
|
||||
from erpnext.hr.doctype.payroll_entry.test_payroll_entry import get_salary_component_account
|
||||
@ -272,33 +273,31 @@ def make_salary_structure(sal_struct, payroll_frequency, employee):
|
||||
frappe.get_doc({
|
||||
"doctype": "Salary Structure",
|
||||
"name": sal_struct,
|
||||
"company": erpnext.get_default_company(),
|
||||
"employees": get_employee_details(employee),
|
||||
"company": "_Test Company",
|
||||
"earnings": get_earnings_component(),
|
||||
"deductions": get_deductions_component(),
|
||||
"payroll_frequency": payroll_frequency,
|
||||
"payment_account": frappe.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name")
|
||||
"payment_account": get_random("Account")
|
||||
}).insert()
|
||||
|
||||
elif not frappe.db.get_value("Salary Structure Employee",{'parent':sal_struct, 'employee':employee},'name'):
|
||||
create_salary_structure_assignment(employee, sal_struct)
|
||||
|
||||
elif not frappe.db.get_value("Salary Structure Assignment",{'salary_structure':sal_struct, 'employee':employee},'name'):
|
||||
sal_struct = frappe.get_doc("Salary Structure", sal_struct)
|
||||
sal_struct.append("employees", {"employee": employee,
|
||||
"employee_name": employee,
|
||||
"base": 32000,
|
||||
"variable": 3200,
|
||||
"from_date": add_months(nowdate(),-1)
|
||||
})
|
||||
sal_struct.save()
|
||||
create_salary_structure_assignment(employee, sal_struct)
|
||||
sal_struct = sal_struct.name
|
||||
return sal_struct
|
||||
|
||||
def get_employee_details(employee):
|
||||
return [{"employee": employee,
|
||||
"base": 50000,
|
||||
"variable": 5000,
|
||||
"from_date": add_months(nowdate(),-1)
|
||||
}
|
||||
]
|
||||
def create_salary_structure_assignment(employee, salary_structure):
|
||||
salary_structure_assignment = frappe.new_doc("Salary Structure Assignment")
|
||||
salary_structure_assignment.employee = employee
|
||||
salary_structure_assignment.base = 50000
|
||||
salary_structure_assignment.variable = 5000
|
||||
salary_structure_assignment.from_date = add_months(nowdate(), -1)
|
||||
salary_structure_assignment.salary_structure = salary_structure
|
||||
salary_structure_assignment.company = erpnext.get_default_company()
|
||||
salary_structure_assignment.save(ignore_permissions=True)
|
||||
return salary_structure_assignment
|
||||
|
||||
def get_earnings_component():
|
||||
return [
|
||||
@ -353,4 +352,4 @@ def get_deductions_component():
|
||||
"formula": 'base*.1',
|
||||
"idx": 3
|
||||
}
|
||||
]
|
||||
]
|
||||
|
@ -165,5 +165,46 @@ frappe.ui.form.on('Salary Detail', {
|
||||
|
||||
deductions_remove: function(frm) {
|
||||
calculate_totals(frm.doc);
|
||||
},
|
||||
|
||||
salary_component: function(frm, cdt, cdn) {
|
||||
var child = locals[cdt][cdn];
|
||||
if(child.salary_component){
|
||||
frappe.call({
|
||||
method: "frappe.client.get",
|
||||
args: {
|
||||
doctype: "Salary Component",
|
||||
name: child.salary_component
|
||||
},
|
||||
callback: function(data) {
|
||||
if(data.message){
|
||||
var result = data.message;
|
||||
frappe.model.set_value(cdt, cdn, 'condition',result.condition);
|
||||
frappe.model.set_value(cdt, cdn, 'amount_based_on_formula',result.amount_based_on_formula);
|
||||
if(result.amount_based_on_formula == 1){
|
||||
frappe.model.set_value(cdt, cdn, 'formula',result.formula);
|
||||
}
|
||||
else{
|
||||
frappe.model.set_value(cdt, cdn, 'amount',result.amount);
|
||||
}
|
||||
frappe.model.set_value(cdt, cdn, 'statistical_component',result.statistical_component);
|
||||
frappe.model.set_value(cdt, cdn, 'depends_on_lwp',result.depends_on_lwp);
|
||||
frappe.model.set_value(cdt, cdn, 'do_not_include_in_total',result.do_not_include_in_total);
|
||||
refresh_field("earnings");
|
||||
refresh_field("deductions");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
amount_based_on_formula: function(frm, cdt, cdn) {
|
||||
var child = locals[cdt][cdn];
|
||||
if(child.amount_based_on_formula == 1){
|
||||
frappe.model.set_value(cdt, cdn, 'amount', null);
|
||||
}
|
||||
else{
|
||||
frappe.model.set_value(cdt, cdn, 'formula', null);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -11,9 +11,36 @@ frappe.ui.form.on('Salary Structure Assignment', {
|
||||
}
|
||||
}
|
||||
});
|
||||
frm.set_query("salary_structure", function() {
|
||||
return {
|
||||
filters: {
|
||||
company: frm.doc.company,
|
||||
is_active: "Yes",
|
||||
docstatus: 1
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
|
||||
employee: function(frm) {
|
||||
if(frm.doc.employee){
|
||||
frappe.call({
|
||||
method: "frappe.client.get_value",
|
||||
args:{
|
||||
doctype: "Employee",
|
||||
fieldname: "company",
|
||||
filters:{
|
||||
name: frm.doc.employee
|
||||
}
|
||||
},
|
||||
callback: function(data) {
|
||||
if(data.message){
|
||||
frm.set_value("company", data.message.company);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else{
|
||||
frm.set_value("company", null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -11,6 +11,7 @@ from frappe.model.document import Document
|
||||
class SalaryStructureAssignment(Document):
|
||||
def validate(self):
|
||||
self.validate_dates()
|
||||
self.validate_duplicate_assignments()
|
||||
|
||||
def validate_dates(self):
|
||||
joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
|
||||
@ -33,10 +34,14 @@ class SalaryStructureAssignment(Document):
|
||||
.format(self.to_date, relieving_date))
|
||||
|
||||
def validate_duplicate_assignments(self):
|
||||
if not self.name:
|
||||
# hack! if name is null, it could cause problems with !=
|
||||
self.name = "New "+self.doctype
|
||||
assignment = frappe.db.sql("""
|
||||
select name from `tabSalary Structure Assignment`
|
||||
where employee=%(employee)s
|
||||
and name != %(salary_struct)s
|
||||
and name != %(name)s
|
||||
and docstatus != 2
|
||||
and (
|
||||
(%(from_date)s between from_date and ifnull(to_date, '2199-12-31'))
|
||||
or (%(to_date)s between from_date and ifnull(to_date, '2199-12-31'))
|
||||
@ -45,8 +50,8 @@ class SalaryStructureAssignment(Document):
|
||||
'employee': self.employee,
|
||||
'from_date': self.from_date,
|
||||
'to_date': (self.to_date or '2199-12-31'),
|
||||
'salary_struct': self.salary_struct
|
||||
'name': self.name
|
||||
})
|
||||
|
||||
if assignment:
|
||||
frappe.throw(_("Active Salary Structure Assignment {0} found for employee {1} for the given dates").format(assignment[0][0], self.employee))
|
||||
frappe.throw(_("Active Salary Structure Assignment {0} found for employee {1} for the given dates").format(assignment[0][0], self.employee))
|
||||
|
@ -118,30 +118,21 @@ class TestTimesheet(unittest.TestCase):
|
||||
|
||||
|
||||
def make_salary_structure(employee):
|
||||
name = frappe.db.get_value('Salary Structure Employee', {'employee': employee}, 'parent')
|
||||
name = frappe.db.get_value('Salary Structure Assignment', {'employee': employee}, 'salary_structure')
|
||||
if name:
|
||||
salary_structure = frappe.get_doc('Salary Structure', name)
|
||||
else:
|
||||
salary_structure = frappe.new_doc("Salary Structure")
|
||||
salary_structure.name = "Timesheet Salary Structure Test"
|
||||
salary_structure.salary_slip_based_on_timesheet = 1
|
||||
salary_structure.from_date = add_days(nowdate(), -30)
|
||||
salary_structure.salary_component = "Basic"
|
||||
salary_structure.hour_rate = 50.0
|
||||
salary_structure.company = "_Test Company"
|
||||
salary_structure.payment_account = get_random("Account")
|
||||
|
||||
salary_structure.set('employees', [])
|
||||
salary_structure.set('earnings', [])
|
||||
salary_structure.set('deductions', [])
|
||||
|
||||
es = salary_structure.append('employees', {
|
||||
"employee": employee,
|
||||
"base": 1200,
|
||||
"from_date": add_months(nowdate(),-1)
|
||||
})
|
||||
|
||||
|
||||
es = salary_structure.append('earnings', {
|
||||
"salary_component": "_Test Allowance",
|
||||
"amount": 100
|
||||
@ -154,6 +145,14 @@ def make_salary_structure(employee):
|
||||
|
||||
salary_structure.save(ignore_permissions=True)
|
||||
|
||||
salary_structure_assignment = frappe.new_doc("Salary Structure Assignment")
|
||||
salary_structure_assignment.employee = employee
|
||||
salary_structure_assignment.base = 1200
|
||||
salary_structure_assignment.from_date = add_months(nowdate(), -1)
|
||||
salary_structure_assignment.salary_structure = salary_structure.name
|
||||
salary_structure_assignment.company = "_Test Company"
|
||||
salary_structure_assignment.save(ignore_permissions=True)
|
||||
|
||||
return salary_structure
|
||||
|
||||
def make_timesheet(employee, simulate=False, billable = 0, activity_type="_Test Activity Type", project=None, task=None, company=None):
|
||||
|
Loading…
Reference in New Issue
Block a user