Payroll entry ux improvements and processing via background jobs
This commit is contained in:
parent
04d5412754
commit
4f135c9805
@ -46,39 +46,6 @@
|
||||
"translatable": 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_in_quick_entry": 0,
|
||||
@ -153,28 +120,29 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "salary_component",
|
||||
"fetch_from": "employee.department",
|
||||
"fieldname": "department",
|
||||
"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": 1,
|
||||
"label": "Salary Component",
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Department",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Salary Component",
|
||||
"options": "Department",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
@ -186,29 +154,27 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "salary_component.type",
|
||||
"fieldname": "type",
|
||||
"fieldtype": "Data",
|
||||
"fieldname": "payroll_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_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Type",
|
||||
"label": "Payroll Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
@ -251,18 +217,19 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "payroll_date",
|
||||
"fieldtype": "Date",
|
||||
"fieldname": "salary_component",
|
||||
"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": "Payroll Date",
|
||||
"in_standard_filter": 1,
|
||||
"label": "Salary Component",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Salary Component",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -315,8 +282,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "employee.department",
|
||||
"fieldname": "department",
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
@ -325,18 +291,18 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Department",
|
||||
"label": "Company",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Department",
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
@ -375,6 +341,72 @@
|
||||
"translatable": 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_in_quick_entry": 0,
|
||||
@ -418,7 +450,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-07-28 17:50:25.725444",
|
||||
"modified": "2018-07-30 16:02:01.538750",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Additional Salary",
|
||||
@ -474,4 +506,4 @@
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
}
|
@ -37,11 +37,12 @@ class AdditionalSalary(Document):
|
||||
@frappe.whitelist()
|
||||
def get_additional_salary_component(employee, start_date, end_date):
|
||||
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
|
||||
and docstatus = 1
|
||||
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,
|
||||
'from_date': start_date,
|
||||
@ -58,6 +59,7 @@ def get_additional_salary_component(employee, start_date, end_date):
|
||||
additional_components_list.append({
|
||||
'amount': d.amount,
|
||||
'type': component.type,
|
||||
'struct_row': struct_row
|
||||
'struct_row': struct_row,
|
||||
'overwrite': d.overwrite_salary_structure_amount
|
||||
})
|
||||
return additional_components_list
|
@ -20,48 +20,61 @@ frappe.ui.form.on('Payroll Entry', {
|
||||
},
|
||||
|
||||
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.custom_buttons) frm.clear_custom_buttons();
|
||||
frm.events.add_context_buttons(frm);
|
||||
}
|
||||
},
|
||||
|
||||
add_context_buttons: function(frm) {
|
||||
frappe.call({
|
||||
method: 'erpnext.hr.doctype.payroll_entry.payroll_entry.payroll_entry_has_created_slips',
|
||||
args: {
|
||||
'name': frm.doc.name
|
||||
},
|
||||
get_employee_details: function (frm) {
|
||||
return frappe.call({
|
||||
doc: frm.doc,
|
||||
method: 'fill_employee_details',
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
frm.events.add_salary_slip_buttons(frm, r.message);
|
||||
if(r.message.submitted){
|
||||
frm.events.add_bank_entry_button(frm);
|
||||
if (r.docs[0].employees){
|
||||
frm.save();
|
||||
frm.refresh();
|
||||
if(r.docs[0].validate_attendance){
|
||||
render_employee_attendance(frm, r.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
add_salary_slip_buttons: function(frm, slip_status) {
|
||||
if (!slip_status.draft && !slip_status.submitted) {
|
||||
return;
|
||||
} else {
|
||||
frm.add_custom_button(__("View Salary Slips"),
|
||||
function() {
|
||||
frappe.set_route(
|
||||
'List', 'Salary Slip', {posting_date: frm.doc.posting_date}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
create_salary_slips: function(frm) {
|
||||
frm.call({
|
||||
doc: frm.doc,
|
||||
method: "create_salary_slips",
|
||||
callback: function(r) {
|
||||
frm.refresh();
|
||||
frm.toolbar.refresh();
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
if (slip_status.draft) {
|
||||
frm.add_custom_button(__("Submit Salary Slip"),
|
||||
function() {
|
||||
submit_salary_slip(frm);
|
||||
}
|
||||
).addClass("btn-primary");
|
||||
add_context_buttons: function(frm) {
|
||||
if(frm.doc.salary_slips_submitted) {
|
||||
frm.events.add_bank_entry_button(frm);
|
||||
} else if(frm.doc.salary_slips_created) {
|
||||
frm.add_custom_button(__("Submit Salary Slip"), function() {
|
||||
submit_salary_slip(frm);
|
||||
}).addClass("btn-primary");
|
||||
}
|
||||
},
|
||||
|
||||
@ -73,13 +86,9 @@ frappe.ui.form.on('Payroll Entry', {
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message && !r.message.submitted) {
|
||||
frm.add_custom_button("Bank Entry",
|
||||
function() {
|
||||
make_bank_entry(frm);
|
||||
},
|
||||
__('Make')
|
||||
);
|
||||
frm.page.set_inner_btn_group_as_primary(__('Make'));
|
||||
frm.add_custom_button("Make Bank Entry", function() {
|
||||
make_bank_entry(frm);
|
||||
}).addClass("btn-primary");
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -115,23 +124,23 @@ frappe.ui.form.on('Payroll Entry', {
|
||||
|
||||
payroll_frequency: function (frm) {
|
||||
frm.trigger("set_start_end_dates");
|
||||
frm.set_value('employees', []);
|
||||
frm.events.clear_employee_table(frm);
|
||||
},
|
||||
|
||||
company: function (frm) {
|
||||
frm.set_value('employees', []);
|
||||
frm.events.clear_employee_table(frm);
|
||||
},
|
||||
|
||||
department: function (frm) {
|
||||
frm.set_value('employees', []);
|
||||
frm.events.clear_employee_table(frm);
|
||||
},
|
||||
|
||||
designation: function (frm) {
|
||||
frm.set_value('employees', []);
|
||||
frm.events.clear_employee_table(frm);
|
||||
},
|
||||
|
||||
branch: function (frm) {
|
||||
frm.set_value('employees', []);
|
||||
frm.events.clear_employee_table(frm);
|
||||
},
|
||||
|
||||
start_date: function (frm) {
|
||||
@ -141,11 +150,11 @@ frappe.ui.form.on('Payroll Entry', {
|
||||
// reset flag
|
||||
in_progress = false;
|
||||
}
|
||||
frm.set_value('employees', []);
|
||||
frm.events.clear_employee_table(frm);
|
||||
},
|
||||
|
||||
project: function (frm) {
|
||||
frm.set_value('employees', []);
|
||||
frm.events.clear_employee_table(frm);
|
||||
},
|
||||
|
||||
salary_slip_based_on_timesheet: function (frm) {
|
||||
@ -201,7 +210,12 @@ frappe.ui.form.on('Payroll Entry', {
|
||||
}else{
|
||||
frm.fields_dict.attendance_detail_html.html("");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
clear_employee_table: function (frm) {
|
||||
frm.clear_table('employees');
|
||||
frm.refresh();
|
||||
},
|
||||
});
|
||||
|
||||
// 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) {
|
||||
var doc = frm.doc;
|
||||
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",
|
||||
callback: function() {
|
||||
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,
|
||||
|
@ -77,40 +77,6 @@
|
||||
"unique": 0,
|
||||
"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,
|
||||
@ -211,6 +177,73 @@
|
||||
"unique": 0,
|
||||
"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_in_quick_entry": 0,
|
||||
@ -277,6 +310,37 @@
|
||||
"translatable": 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_in_quick_entry": 0,
|
||||
@ -317,8 +381,8 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_8",
|
||||
"fieldtype": "Section Break",
|
||||
"fieldname": "number_of_employees",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@ -326,13 +390,14 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Number Of Employees",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@ -348,8 +413,8 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "get_employee_details",
|
||||
"fieldtype": "Button",
|
||||
"fieldname": "sec_break20",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@ -357,7 +422,6 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Get Employee Details",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
@ -389,7 +453,7 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Employees",
|
||||
"label": "Employee Details",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Payroll Employee Detail",
|
||||
@ -797,6 +861,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "company.cost_center",
|
||||
"fieldname": "cost_center",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -1016,38 +1081,6 @@
|
||||
"translatable": 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_in_quick_entry": 0,
|
||||
@ -1079,6 +1112,70 @@
|
||||
"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_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,
|
||||
@ -1092,7 +1189,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-06-28 13:55:48.295327",
|
||||
"modified": "2018-07-30 14:57:37.601430",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Payroll Entry",
|
||||
@ -1126,5 +1223,6 @@
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
@ -66,6 +66,7 @@ class PayrollEntry(Document):
|
||||
for d in employees:
|
||||
self.append('employees', d)
|
||||
|
||||
self.number_of_employees = len(employees)
|
||||
if self.validate_attendance:
|
||||
return self.validate_employee_attendance()
|
||||
|
||||
@ -108,9 +109,9 @@ class PayrollEntry(Document):
|
||||
"posting_date": self.posting_date,
|
||||
"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,
|
||||
"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)
|
||||
else:
|
||||
create_salary_slips_for_employees(emp_list, args, publish_progress=False)
|
||||
@ -129,41 +130,12 @@ class PayrollEntry(Document):
|
||||
return ss_list
|
||||
|
||||
def submit_salary_slips(self):
|
||||
"""
|
||||
Submit all salary slips based on selected criteria
|
||||
"""
|
||||
self.check_permission('write')
|
||||
|
||||
ss_list = self.get_sal_slip_list(ss_status=0)
|
||||
submitted_ss = []
|
||||
not_submitted_ss = []
|
||||
frappe.flags.via_payroll_entry = True
|
||||
for ss in ss_list:
|
||||
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)
|
||||
if len(ss_list) > 30:
|
||||
frappe.enqueue(submit_salary_slips_for_employees, timeout=600, payroll_entry=self, salary_slips=ss_list)
|
||||
else:
|
||||
submit_salary_slips_for_employees(self, ss_list, publish_progress=False)
|
||||
|
||||
def email_salary_slip(self, submitted_ss):
|
||||
if frappe.db.get_single_value("HR Settings", "email_salary_slip_to_employee"):
|
||||
@ -490,49 +462,6 @@ def get_month_details(year, month):
|
||||
else:
|
||||
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):
|
||||
journal_entries = frappe.db.sql(
|
||||
'select name from `tabJournal Entry Account` '
|
||||
@ -548,7 +477,6 @@ def get_payroll_entry_bank_entries(payroll_entry_name):
|
||||
@frappe.whitelist()
|
||||
def payroll_entry_has_bank_entries(name):
|
||||
response = {}
|
||||
|
||||
bank_entries = get_payroll_entry_bank_entries(name)
|
||||
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)),
|
||||
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):
|
||||
return frappe.db.sql_list("""
|
||||
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 employee in (%s)
|
||||
""" % ('%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:
|
||||
additional_component = frappe._dict(additional_component)
|
||||
amount = additional_component.amount
|
||||
overwrite = additional_component.overwrite
|
||||
key = "earnings"
|
||||
if additional_component.type == "Deduction":
|
||||
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()
|
||||
|
||||
@ -125,7 +126,7 @@ class SalarySlip(TransactionBase):
|
||||
if benefit_claim_amount:
|
||||
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
|
||||
for d in self.get(key):
|
||||
if d.salary_component == struct_row.salary_component:
|
||||
@ -146,8 +147,13 @@ class SalarySlip(TransactionBase):
|
||||
'tax_on_additional_salary': additional_tax
|
||||
})
|
||||
else:
|
||||
component_row.default_amount = amount
|
||||
component_row.amount = amount
|
||||
if overwrite:
|
||||
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_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.rounded_total = rounded(self.net_pay,
|
||||
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):
|
||||
self.set('loans', [])
|
||||
|
Loading…
x
Reference in New Issue
Block a user