mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-31 10:49:09 +00:00
Payroll entry ux improvements and processing via background jobs
This commit is contained in:
@@ -46,39 +46,6 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "company",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"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": "Company",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Company",
|
|
||||||
"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_in_quick_entry": 0,
|
"allow_in_quick_entry": 0,
|
||||||
@@ -153,28 +120,29 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "salary_component",
|
"fetch_from": "employee.department",
|
||||||
|
"fieldname": "department",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 0,
|
||||||
"label": "Salary Component",
|
"label": "Department",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Salary Component",
|
"options": "Department",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 1,
|
||||||
"remember_last_selected_value": 0,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 1,
|
"reqd": 0,
|
||||||
"search_index": 1,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
@@ -186,29 +154,27 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fetch_from": "salary_component.type",
|
"fieldname": "payroll_date",
|
||||||
"fieldname": "type",
|
"fieldtype": "Date",
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Type",
|
"label": "Payroll Date",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "",
|
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 1,
|
"read_only": 0,
|
||||||
"remember_last_selected_value": 0,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 1,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
@@ -251,18 +217,19 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "payroll_date",
|
"fieldname": "salary_component",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 1,
|
||||||
"label": "Payroll Date",
|
"label": "Salary Component",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
|
"options": "Salary Component",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
@@ -315,8 +282,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fetch_from": "employee.department",
|
"fieldname": "company",
|
||||||
"fieldname": "department",
|
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
@@ -325,18 +291,18 @@
|
|||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Department",
|
"label": "Company",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Department",
|
"options": "Company",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 1,
|
"read_only": 0,
|
||||||
"remember_last_selected_value": 0,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
@@ -375,6 +341,72 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fetch_from": "salary_component.type",
|
||||||
|
"fieldname": "type",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"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": "Salary Component Type",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "",
|
||||||
|
"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_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "overwrite_salary_structure_amount",
|
||||||
|
"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": "Overwrite Salary Structure 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_bulk_edit": 0,
|
||||||
"allow_in_quick_entry": 0,
|
"allow_in_quick_entry": 0,
|
||||||
@@ -418,7 +450,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-07-28 17:50:25.725444",
|
"modified": "2018-07-30 16:02:01.538750",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Additional Salary",
|
"name": "Additional Salary",
|
||||||
@@ -474,4 +506,4 @@
|
|||||||
"track_changes": 1,
|
"track_changes": 1,
|
||||||
"track_seen": 0,
|
"track_seen": 0,
|
||||||
"track_views": 0
|
"track_views": 0
|
||||||
}
|
}
|
||||||
@@ -37,11 +37,12 @@ class AdditionalSalary(Document):
|
|||||||
@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("""
|
||||||
select salary_component, sum(amount) as amount from `tabAdditional Salary`
|
select salary_component, sum(amount) as amount, overwrite_salary_structure_amount from `tabAdditional Salary`
|
||||||
where employee=%(employee)s
|
where employee=%(employee)s
|
||||||
and docstatus = 1
|
and docstatus = 1
|
||||||
and payroll_date between %(from_date)s and %(to_date)s
|
and payroll_date between %(from_date)s and %(to_date)s
|
||||||
group by salary_component
|
group by salary_component, overwrite_salary_structure_amount
|
||||||
|
order by salary_component, overwrite_salary_structure_amount
|
||||||
""", {
|
""", {
|
||||||
'employee': employee,
|
'employee': employee,
|
||||||
'from_date': start_date,
|
'from_date': start_date,
|
||||||
@@ -58,6 +59,7 @@ def get_additional_salary_component(employee, start_date, end_date):
|
|||||||
additional_components_list.append({
|
additional_components_list.append({
|
||||||
'amount': d.amount,
|
'amount': d.amount,
|
||||||
'type': component.type,
|
'type': component.type,
|
||||||
'struct_row': struct_row
|
'struct_row': struct_row,
|
||||||
|
'overwrite': d.overwrite_salary_structure_amount
|
||||||
})
|
})
|
||||||
return additional_components_list
|
return additional_components_list
|
||||||
@@ -20,48 +20,61 @@ frappe.ui.form.on('Payroll Entry', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
|
if (frm.doc.docstatus == 0) {
|
||||||
|
if(!frm.is_new()) {
|
||||||
|
frm.page.clear_primary_action();
|
||||||
|
frm.add_custom_button(__("Get Employees"),
|
||||||
|
function() {
|
||||||
|
frm.events.get_employee_details(frm);
|
||||||
|
}
|
||||||
|
).toggleClass('btn-primary', !(frm.doc.employees || []).length);
|
||||||
|
}
|
||||||
|
if ((frm.doc.employees || []).length) {
|
||||||
|
frm.page.set_primary_action(__('Create Salary Slips'), () => {
|
||||||
|
frm.save('Submit');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
if (frm.doc.docstatus == 1) {
|
if (frm.doc.docstatus == 1) {
|
||||||
if (frm.custom_buttons) frm.clear_custom_buttons();
|
if (frm.custom_buttons) frm.clear_custom_buttons();
|
||||||
frm.events.add_context_buttons(frm);
|
frm.events.add_context_buttons(frm);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
add_context_buttons: function(frm) {
|
get_employee_details: function (frm) {
|
||||||
frappe.call({
|
return frappe.call({
|
||||||
method: 'erpnext.hr.doctype.payroll_entry.payroll_entry.payroll_entry_has_created_slips',
|
doc: frm.doc,
|
||||||
args: {
|
method: 'fill_employee_details',
|
||||||
'name': frm.doc.name
|
|
||||||
},
|
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if(r.message) {
|
if (r.docs[0].employees){
|
||||||
frm.events.add_salary_slip_buttons(frm, r.message);
|
frm.save();
|
||||||
if(r.message.submitted){
|
frm.refresh();
|
||||||
frm.events.add_bank_entry_button(frm);
|
if(r.docs[0].validate_attendance){
|
||||||
|
render_employee_attendance(frm, r.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
add_salary_slip_buttons: function(frm, slip_status) {
|
create_salary_slips: function(frm) {
|
||||||
if (!slip_status.draft && !slip_status.submitted) {
|
frm.call({
|
||||||
return;
|
doc: frm.doc,
|
||||||
} else {
|
method: "create_salary_slips",
|
||||||
frm.add_custom_button(__("View Salary Slips"),
|
callback: function(r) {
|
||||||
function() {
|
frm.refresh();
|
||||||
frappe.set_route(
|
frm.toolbar.refresh();
|
||||||
'List', 'Salary Slip', {posting_date: frm.doc.posting_date}
|
}
|
||||||
);
|
})
|
||||||
}
|
},
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (slip_status.draft) {
|
add_context_buttons: function(frm) {
|
||||||
frm.add_custom_button(__("Submit Salary Slip"),
|
if(frm.doc.salary_slips_submitted) {
|
||||||
function() {
|
frm.events.add_bank_entry_button(frm);
|
||||||
submit_salary_slip(frm);
|
} else if(frm.doc.salary_slips_created) {
|
||||||
}
|
frm.add_custom_button(__("Submit Salary Slip"), function() {
|
||||||
).addClass("btn-primary");
|
submit_salary_slip(frm);
|
||||||
|
}).addClass("btn-primary");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -73,13 +86,9 @@ frappe.ui.form.on('Payroll Entry', {
|
|||||||
},
|
},
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if (r.message && !r.message.submitted) {
|
if (r.message && !r.message.submitted) {
|
||||||
frm.add_custom_button("Bank Entry",
|
frm.add_custom_button("Make Bank Entry", function() {
|
||||||
function() {
|
make_bank_entry(frm);
|
||||||
make_bank_entry(frm);
|
}).addClass("btn-primary");
|
||||||
},
|
|
||||||
__('Make')
|
|
||||||
);
|
|
||||||
frm.page.set_inner_btn_group_as_primary(__('Make'));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -115,23 +124,23 @@ frappe.ui.form.on('Payroll Entry', {
|
|||||||
|
|
||||||
payroll_frequency: function (frm) {
|
payroll_frequency: function (frm) {
|
||||||
frm.trigger("set_start_end_dates");
|
frm.trigger("set_start_end_dates");
|
||||||
frm.set_value('employees', []);
|
frm.events.clear_employee_table(frm);
|
||||||
},
|
},
|
||||||
|
|
||||||
company: function (frm) {
|
company: function (frm) {
|
||||||
frm.set_value('employees', []);
|
frm.events.clear_employee_table(frm);
|
||||||
},
|
},
|
||||||
|
|
||||||
department: function (frm) {
|
department: function (frm) {
|
||||||
frm.set_value('employees', []);
|
frm.events.clear_employee_table(frm);
|
||||||
},
|
},
|
||||||
|
|
||||||
designation: function (frm) {
|
designation: function (frm) {
|
||||||
frm.set_value('employees', []);
|
frm.events.clear_employee_table(frm);
|
||||||
},
|
},
|
||||||
|
|
||||||
branch: function (frm) {
|
branch: function (frm) {
|
||||||
frm.set_value('employees', []);
|
frm.events.clear_employee_table(frm);
|
||||||
},
|
},
|
||||||
|
|
||||||
start_date: function (frm) {
|
start_date: function (frm) {
|
||||||
@@ -141,11 +150,11 @@ frappe.ui.form.on('Payroll Entry', {
|
|||||||
// reset flag
|
// reset flag
|
||||||
in_progress = false;
|
in_progress = false;
|
||||||
}
|
}
|
||||||
frm.set_value('employees', []);
|
frm.events.clear_employee_table(frm);
|
||||||
},
|
},
|
||||||
|
|
||||||
project: function (frm) {
|
project: function (frm) {
|
||||||
frm.set_value('employees', []);
|
frm.events.clear_employee_table(frm);
|
||||||
},
|
},
|
||||||
|
|
||||||
salary_slip_based_on_timesheet: function (frm) {
|
salary_slip_based_on_timesheet: function (frm) {
|
||||||
@@ -201,7 +210,12 @@ frappe.ui.form.on('Payroll Entry', {
|
|||||||
}else{
|
}else{
|
||||||
frm.fields_dict.attendance_detail_html.html("");
|
frm.fields_dict.attendance_detail_html.html("");
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
|
clear_employee_table: function (frm) {
|
||||||
|
frm.clear_table('employees');
|
||||||
|
frm.refresh();
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Submit salary slips
|
// Submit salary slips
|
||||||
@@ -227,18 +241,6 @@ const submit_salary_slip = function (frm) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
cur_frm.cscript.get_employee_details = function (doc) {
|
|
||||||
var callback = function (r) {
|
|
||||||
if (r.docs[0].employees){
|
|
||||||
cur_frm.refresh_field('employees');
|
|
||||||
if(r.docs[0].validate_attendance){
|
|
||||||
render_employee_attendance(cur_frm, r.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return $c('runserverobj', { 'method': 'fill_employee_details', 'docs': doc }, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
let make_bank_entry = function (frm) {
|
let make_bank_entry = function (frm) {
|
||||||
var doc = frm.doc;
|
var doc = frm.doc;
|
||||||
if (doc.company && doc.start_date && doc.end_date && doc.payment_account) {
|
if (doc.company && doc.start_date && doc.end_date && doc.payment_account) {
|
||||||
@@ -247,7 +249,7 @@ let make_bank_entry = function (frm) {
|
|||||||
method: "make_payment_entry",
|
method: "make_payment_entry",
|
||||||
callback: function() {
|
callback: function() {
|
||||||
frappe.set_route(
|
frappe.set_route(
|
||||||
'List', 'Journal Entry', {posting_date: frm.doc.posting_date}
|
'List', 'Journal Entry', {"Journal Entry Account.reference_name": frm.doc.name}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
freeze: true,
|
freeze: true,
|
||||||
|
|||||||
@@ -77,40 +77,6 @@
|
|||||||
"unique": 0,
|
"unique": 0,
|
||||||
"width": "50%"
|
"width": "50%"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"default": "",
|
|
||||||
"fieldname": "company",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Company",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Company",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 1,
|
|
||||||
"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_in_quick_entry": 0,
|
"allow_in_quick_entry": 0,
|
||||||
@@ -211,6 +177,73 @@
|
|||||||
"unique": 0,
|
"unique": 0,
|
||||||
"width": "50%"
|
"width": "50%"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"default": "",
|
||||||
|
"fieldname": "company",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Company",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Company",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 1,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 1,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"collapsible_depends_on": "",
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "section_break_8",
|
||||||
|
"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": "Employees",
|
||||||
|
"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_in_quick_entry": 0,
|
"allow_in_quick_entry": 0,
|
||||||
@@ -277,6 +310,37 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "column_break_10",
|
||||||
|
"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_bulk_edit": 0,
|
||||||
"allow_in_quick_entry": 0,
|
"allow_in_quick_entry": 0,
|
||||||
@@ -317,8 +381,8 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "section_break_8",
|
"fieldname": "number_of_employees",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Int",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
@@ -326,13 +390,14 @@
|
|||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
|
"label": "Number Of Employees",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 0,
|
"read_only": 1,
|
||||||
"remember_last_selected_value": 0,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
@@ -348,8 +413,8 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "get_employee_details",
|
"fieldname": "sec_break20",
|
||||||
"fieldtype": "Button",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
@@ -357,7 +422,6 @@
|
|||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Get Employee Details",
|
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@@ -389,7 +453,7 @@
|
|||||||
"in_global_search": 0,
|
"in_global_search": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 0,
|
"in_standard_filter": 0,
|
||||||
"label": "Employees",
|
"label": "Employee Details",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Payroll Employee Detail",
|
"options": "Payroll Employee Detail",
|
||||||
@@ -797,6 +861,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_from": "company.cost_center",
|
||||||
"fieldname": "cost_center",
|
"fieldname": "cost_center",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -1016,38 +1081,6 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "activity_log",
|
|
||||||
"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": "Activity Log",
|
|
||||||
"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_in_quick_entry": 0,
|
"allow_in_quick_entry": 0,
|
||||||
@@ -1079,6 +1112,70 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "salary_slips_created",
|
||||||
|
"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": "Salary Slips Created",
|
||||||
|
"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_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "salary_slips_submitted",
|
||||||
|
"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": "Salary Slips Submitted",
|
||||||
|
"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
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"has_web_view": 0,
|
||||||
@@ -1092,7 +1189,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-06-28 13:55:48.295327",
|
"modified": "2018-07-30 14:57:37.601430",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Payroll Entry",
|
"name": "Payroll Entry",
|
||||||
@@ -1126,5 +1223,6 @@
|
|||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 0,
|
"track_changes": 0,
|
||||||
"track_seen": 0
|
"track_seen": 0,
|
||||||
|
"track_views": 0
|
||||||
}
|
}
|
||||||
@@ -66,6 +66,7 @@ class PayrollEntry(Document):
|
|||||||
for d in employees:
|
for d in employees:
|
||||||
self.append('employees', d)
|
self.append('employees', d)
|
||||||
|
|
||||||
|
self.number_of_employees = len(employees)
|
||||||
if self.validate_attendance:
|
if self.validate_attendance:
|
||||||
return self.validate_employee_attendance()
|
return self.validate_employee_attendance()
|
||||||
|
|
||||||
@@ -108,9 +109,9 @@ class PayrollEntry(Document):
|
|||||||
"posting_date": self.posting_date,
|
"posting_date": self.posting_date,
|
||||||
"deduct_tax_for_unclaimed_employee_benefits": self.deduct_tax_for_unclaimed_employee_benefits,
|
"deduct_tax_for_unclaimed_employee_benefits": self.deduct_tax_for_unclaimed_employee_benefits,
|
||||||
"deduct_tax_for_unsubmitted_tax_exemption_proof": self.deduct_tax_for_unsubmitted_tax_exemption_proof,
|
"deduct_tax_for_unsubmitted_tax_exemption_proof": self.deduct_tax_for_unsubmitted_tax_exemption_proof,
|
||||||
"payroll_entry": self.payroll_entry
|
"payroll_entry": self.name
|
||||||
})
|
})
|
||||||
if len(emp_list) > 50:
|
if len(emp_list) > 30:
|
||||||
frappe.enqueue(create_salary_slips_for_employees, timeout=600, employees=emp_list, args=args)
|
frappe.enqueue(create_salary_slips_for_employees, timeout=600, employees=emp_list, args=args)
|
||||||
else:
|
else:
|
||||||
create_salary_slips_for_employees(emp_list, args, publish_progress=False)
|
create_salary_slips_for_employees(emp_list, args, publish_progress=False)
|
||||||
@@ -129,41 +130,12 @@ class PayrollEntry(Document):
|
|||||||
return ss_list
|
return ss_list
|
||||||
|
|
||||||
def submit_salary_slips(self):
|
def submit_salary_slips(self):
|
||||||
"""
|
|
||||||
Submit all salary slips based on selected criteria
|
|
||||||
"""
|
|
||||||
self.check_permission('write')
|
self.check_permission('write')
|
||||||
|
|
||||||
ss_list = self.get_sal_slip_list(ss_status=0)
|
ss_list = self.get_sal_slip_list(ss_status=0)
|
||||||
submitted_ss = []
|
if len(ss_list) > 30:
|
||||||
not_submitted_ss = []
|
frappe.enqueue(submit_salary_slips_for_employees, timeout=600, payroll_entry=self, salary_slips=ss_list)
|
||||||
frappe.flags.via_payroll_entry = True
|
else:
|
||||||
for ss in ss_list:
|
submit_salary_slips_for_employees(self, ss_list, publish_progress=False)
|
||||||
ss_obj = frappe.get_doc("Salary Slip",ss[0])
|
|
||||||
ss_dict = {}
|
|
||||||
ss_dict["Employee Name"] = ss_obj.employee_name
|
|
||||||
ss_dict["Total Pay"] = fmt_money(ss_obj.net_pay,
|
|
||||||
currency = frappe.defaults.get_global_default("currency"))
|
|
||||||
ss_dict["Salary Slip"] = format_as_links(ss_obj.name)[0]
|
|
||||||
|
|
||||||
if ss_obj.net_pay<0:
|
|
||||||
not_submitted_ss.append(ss_dict)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
ss_obj.submit()
|
|
||||||
submitted_ss.append(ss_obj)
|
|
||||||
|
|
||||||
except frappe.ValidationError:
|
|
||||||
not_submitted_ss.append(ss_dict)
|
|
||||||
|
|
||||||
if submitted_ss:
|
|
||||||
self.make_accrual_jv_entry()
|
|
||||||
frappe.msgprint(_("Salary Slip submitted for period from {0} to {1}")
|
|
||||||
.format(ss_obj.start_date, ss_obj.end_date))
|
|
||||||
|
|
||||||
self.email_salary_slip(submitted_ss)
|
|
||||||
|
|
||||||
return create_submit_log(submitted_ss, not_submitted_ss)
|
|
||||||
|
|
||||||
def email_salary_slip(self, submitted_ss):
|
def email_salary_slip(self, submitted_ss):
|
||||||
if frappe.db.get_single_value("HR Settings", "email_salary_slip_to_employee"):
|
if frappe.db.get_single_value("HR Settings", "email_salary_slip_to_employee"):
|
||||||
@@ -490,49 +462,6 @@ def get_month_details(year, month):
|
|||||||
else:
|
else:
|
||||||
frappe.throw(_("Fiscal Year {0} not found").format(year))
|
frappe.throw(_("Fiscal Year {0} not found").format(year))
|
||||||
|
|
||||||
def format_as_links(salary_slip):
|
|
||||||
return ['<a href="#Form/Salary Slip/{0}">{0}</a>'.format(salary_slip)]
|
|
||||||
|
|
||||||
|
|
||||||
def create_submit_log(submitted_ss, not_submitted_ss):
|
|
||||||
if not submitted_ss and not not_submitted_ss:
|
|
||||||
frappe.msgprint(_("No salary slip found to submit for the above selected criteria OR salary slip already submitted"))
|
|
||||||
|
|
||||||
if not_submitted_ss:
|
|
||||||
frappe.msgprint(_("Could not submit some Salary Slips <br>\
|
|
||||||
Possible reasons: <br>\
|
|
||||||
1. Net pay is less than 0. <br>\
|
|
||||||
2. Company Email Address specified in employee master is not valid. <br>"))
|
|
||||||
|
|
||||||
|
|
||||||
def get_salary_slip_list(name, docstatus, as_dict=0):
|
|
||||||
payroll_entry = frappe.get_doc('Payroll Entry', name)
|
|
||||||
|
|
||||||
salary_slip_list = frappe.db.sql(
|
|
||||||
"select t1.name, t1.salary_structure from `tabSalary Slip` t1 "
|
|
||||||
"where t1.docstatus = %s "
|
|
||||||
"and t1.start_date >= %s "
|
|
||||||
"and t1.end_date <= %s",
|
|
||||||
(docstatus, payroll_entry.start_date, payroll_entry.end_date),
|
|
||||||
as_dict=as_dict
|
|
||||||
)
|
|
||||||
|
|
||||||
return salary_slip_list
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def payroll_entry_has_created_slips(name):
|
|
||||||
response = {}
|
|
||||||
|
|
||||||
draft_salary_slips = get_salary_slip_list(name, docstatus=0)
|
|
||||||
submitted_salary_slips = get_salary_slip_list(name, docstatus=1)
|
|
||||||
|
|
||||||
response['draft'] = 1 if draft_salary_slips else 0
|
|
||||||
response['submitted'] = 1 if submitted_salary_slips else 0
|
|
||||||
|
|
||||||
return response
|
|
||||||
|
|
||||||
|
|
||||||
def get_payroll_entry_bank_entries(payroll_entry_name):
|
def get_payroll_entry_bank_entries(payroll_entry_name):
|
||||||
journal_entries = frappe.db.sql(
|
journal_entries = frappe.db.sql(
|
||||||
'select name from `tabJournal Entry Account` '
|
'select name from `tabJournal Entry Account` '
|
||||||
@@ -548,7 +477,6 @@ def get_payroll_entry_bank_entries(payroll_entry_name):
|
|||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def payroll_entry_has_bank_entries(name):
|
def payroll_entry_has_bank_entries(name):
|
||||||
response = {}
|
response = {}
|
||||||
|
|
||||||
bank_entries = get_payroll_entry_bank_entries(name)
|
bank_entries = get_payroll_entry_bank_entries(name)
|
||||||
response['submitted'] = 1 if bank_entries else 0
|
response['submitted'] = 1 if bank_entries else 0
|
||||||
|
|
||||||
@@ -568,6 +496,10 @@ def create_salary_slips_for_employees(employees, args, publish_progress=True):
|
|||||||
frappe.publish_progress(count*100/len(set(employees) - set(salary_slips_exists_for)),
|
frappe.publish_progress(count*100/len(set(employees) - set(salary_slips_exists_for)),
|
||||||
title = _("Creating Salary Slips..."))
|
title = _("Creating Salary Slips..."))
|
||||||
|
|
||||||
|
payroll_entry = frappe.get_doc("Payroll Entry", args.payroll_entry)
|
||||||
|
payroll_entry.db_set("salary_slips_created", 1)
|
||||||
|
payroll_entry.notify_update()
|
||||||
|
|
||||||
def get_existing_salary_slips(employees, args):
|
def get_existing_salary_slips(employees, args):
|
||||||
return frappe.db.sql_list("""
|
return frappe.db.sql_list("""
|
||||||
select distinct employee from `tabSalary Slip`
|
select distinct employee from `tabSalary Slip`
|
||||||
@@ -575,4 +507,41 @@ def get_existing_salary_slips(employees, args):
|
|||||||
and start_date >= %s and end_date <= %s
|
and start_date >= %s and end_date <= %s
|
||||||
and employee in (%s)
|
and employee in (%s)
|
||||||
""" % ('%s', '%s', '%s', ', '.join(['%s']*len(employees))),
|
""" % ('%s', '%s', '%s', ', '.join(['%s']*len(employees))),
|
||||||
[args.company, args.start_date, args.end_date] + employees)
|
[args.company, args.start_date, args.end_date] + employees)
|
||||||
|
|
||||||
|
def submit_salary_slips_for_employees(payroll_entry, salary_slips, publish_progress=True):
|
||||||
|
submitted_ss = []
|
||||||
|
not_submitted_ss = []
|
||||||
|
frappe.flags.via_payroll_entry = True
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
for ss in salary_slips:
|
||||||
|
ss_obj = frappe.get_doc("Salary Slip",ss[0])
|
||||||
|
if ss_obj.net_pay<0:
|
||||||
|
not_submitted_ss.append(ss[0])
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
ss_obj.submit()
|
||||||
|
submitted_ss.append(ss_obj)
|
||||||
|
except frappe.ValidationError:
|
||||||
|
not_submitted_ss.append(ss[0])
|
||||||
|
|
||||||
|
count += 1
|
||||||
|
if publish_progress:
|
||||||
|
frappe.publish_progress(count*100/len(salary_slips), title = _("Submitting Salary Slips..."))
|
||||||
|
|
||||||
|
if submitted_ss:
|
||||||
|
payroll_entry.make_accrual_jv_entry()
|
||||||
|
frappe.msgprint(_("Salary Slip submitted for period from {0} to {1}")
|
||||||
|
.format(ss_obj.start_date, ss_obj.end_date))
|
||||||
|
|
||||||
|
payroll_entry.email_salary_slip(submitted_ss)
|
||||||
|
|
||||||
|
payroll_entry.db_set("salary_slips_submitted", 1)
|
||||||
|
payroll_entry.notify_update()
|
||||||
|
|
||||||
|
if not submitted_ss and not not_submitted_ss:
|
||||||
|
frappe.msgprint(_("No salary slip found to submit for the above selected criteria OR salary slip already submitted"))
|
||||||
|
|
||||||
|
if not_submitted_ss:
|
||||||
|
frappe.msgprint(_("Could not submit some Salary Slips"))
|
||||||
20
erpnext/hr/doctype/payroll_entry/payroll_entry_dashboard.py
Normal file
20
erpnext/hr/doctype/payroll_entry/payroll_entry_dashboard.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
return {
|
||||||
|
'fieldname': 'payroll_entry',
|
||||||
|
'non_standard_fieldnames': {
|
||||||
|
'Journal Entry': 'reference_name',
|
||||||
|
'Payment Entry': 'reference_name',
|
||||||
|
},
|
||||||
|
'transactions': [
|
||||||
|
{
|
||||||
|
'items': ['Salary Slip', 'Journal Entry']
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'form_links': [
|
||||||
|
{
|
||||||
|
'items': ['Error Log']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -83,10 +83,11 @@ class SalarySlip(TransactionBase):
|
|||||||
for additional_component in additional_components:
|
for additional_component in additional_components:
|
||||||
additional_component = frappe._dict(additional_component)
|
additional_component = frappe._dict(additional_component)
|
||||||
amount = additional_component.amount
|
amount = additional_component.amount
|
||||||
|
overwrite = additional_component.overwrite
|
||||||
key = "earnings"
|
key = "earnings"
|
||||||
if additional_component.type == "Deduction":
|
if additional_component.type == "Deduction":
|
||||||
key = "deductions"
|
key = "deductions"
|
||||||
self.update_component_row(frappe._dict(additional_component.struct_row), amount, key)
|
self.update_component_row(frappe._dict(additional_component.struct_row), amount, key, overwrite=overwrite)
|
||||||
|
|
||||||
self.get_last_payroll_period_benefit()
|
self.get_last_payroll_period_benefit()
|
||||||
|
|
||||||
@@ -125,7 +126,7 @@ class SalarySlip(TransactionBase):
|
|||||||
if benefit_claim_amount:
|
if benefit_claim_amount:
|
||||||
self.update_component_row(struct_row, benefit_claim_amount, "earnings")
|
self.update_component_row(struct_row, benefit_claim_amount, "earnings")
|
||||||
|
|
||||||
def update_component_row(self, struct_row, amount, key, benefit_tax=None, additional_tax=None):
|
def update_component_row(self, struct_row, amount, key, benefit_tax=None, additional_tax=None, overwrite=1):
|
||||||
component_row = None
|
component_row = None
|
||||||
for d in self.get(key):
|
for d in self.get(key):
|
||||||
if d.salary_component == struct_row.salary_component:
|
if d.salary_component == struct_row.salary_component:
|
||||||
@@ -146,8 +147,13 @@ class SalarySlip(TransactionBase):
|
|||||||
'tax_on_additional_salary': additional_tax
|
'tax_on_additional_salary': additional_tax
|
||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
component_row.default_amount = amount
|
if overwrite:
|
||||||
component_row.amount = amount
|
component_row.default_amount = amount
|
||||||
|
component_row.amount = amount
|
||||||
|
else:
|
||||||
|
component_row.default_amount += amount
|
||||||
|
component_row.amount = component_row.default_amount
|
||||||
|
|
||||||
component_row.tax_on_flexible_benefit = benefit_tax
|
component_row.tax_on_flexible_benefit = benefit_tax
|
||||||
component_row.tax_on_additional_salary = additional_tax
|
component_row.tax_on_additional_salary = additional_tax
|
||||||
|
|
||||||
@@ -447,6 +453,9 @@ class SalarySlip(TransactionBase):
|
|||||||
self.net_pay = flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.total_loan_repayment))
|
self.net_pay = flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.total_loan_repayment))
|
||||||
self.rounded_total = rounded(self.net_pay,
|
self.rounded_total = rounded(self.net_pay,
|
||||||
self.precision("net_pay") if disable_rounded_total else 0)
|
self.precision("net_pay") if disable_rounded_total else 0)
|
||||||
|
|
||||||
|
if self.net_pay < 0:
|
||||||
|
frappe.throw(_("Net Pay cannnot be negative"))
|
||||||
|
|
||||||
def set_loan_repayment(self):
|
def set_loan_repayment(self):
|
||||||
self.set('loans', [])
|
self.set('loans', [])
|
||||||
|
|||||||
Reference in New Issue
Block a user