[WIP] Payroll Updates
This commit is contained in:
parent
e4b9473f83
commit
f7b25cbb6b
BIN
erpnext/docs/assets/img/human-resources/payroll-frequency.png
Normal file
BIN
erpnext/docs/assets/img/human-resources/payroll-frequency.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 40 KiB |
Binary file not shown.
Before Width: | Height: | Size: 216 KiB After Width: | Height: | Size: 209 KiB |
Binary file not shown.
Before Width: | Height: | Size: 413 KiB After Width: | Height: | Size: 425 KiB |
@ -2,43 +2,43 @@
|
|||||||
// License: GNU General Public License v3. See license.txt
|
// License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
frappe.ui.form.on("Process Payroll", {
|
frappe.ui.form.on("Process Payroll", {
|
||||||
refresh: function(frm) {
|
onload: function(frm) {
|
||||||
frm.disable_save();
|
frm.doc.posting_date = frm.doc.start_date = frm.doc.end_date = frappe.datetime.nowdate()
|
||||||
frm.trigger("toggle_fields");
|
|
||||||
frm.trigger("set_month_dates");
|
|
||||||
},
|
|
||||||
|
|
||||||
month: function(frm) {
|
|
||||||
frm.trigger("set_month_dates");
|
|
||||||
},
|
|
||||||
|
|
||||||
fiscal_year: function(frm) {
|
|
||||||
frm.trigger("set_month_dates");
|
|
||||||
},
|
|
||||||
|
|
||||||
salary_slip_based_on_timesheet: function(frm) {
|
|
||||||
frm.trigger("toggle_fields")
|
|
||||||
},
|
},
|
||||||
|
|
||||||
toggle_fields: function(frm) {
|
refresh: function(frm) {
|
||||||
frm.toggle_display(['from_date','to_date'],
|
frm.disable_save();
|
||||||
cint(frm.doc.salary_slip_based_on_timesheet)==1);
|
|
||||||
frm.toggle_display(['fiscal_year', 'month'],
|
|
||||||
cint(frm.doc.salary_slip_based_on_timesheet)==0);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
set_month_dates: function(frm) {
|
payroll_frequency: function(frm) {
|
||||||
|
frm.trigger("set_start_end_dates");
|
||||||
|
},
|
||||||
|
|
||||||
|
start_date: function(frm) {
|
||||||
|
frm.trigger("set_start_end_dates");
|
||||||
|
},
|
||||||
|
|
||||||
|
end_date: function(frm) {
|
||||||
|
frm.trigger("set_start_end_dates");
|
||||||
|
},
|
||||||
|
|
||||||
|
payment_account: function(frm) {
|
||||||
|
frm.toggle_display(['make_bank_entry'], (frm.doc.payment_account!="" && frm.doc.payment_account!="undefined"));
|
||||||
|
},
|
||||||
|
|
||||||
|
set_start_end_dates: function(frm) {
|
||||||
if (!frm.doc.salary_slip_based_on_timesheet){
|
if (!frm.doc.salary_slip_based_on_timesheet){
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method:'erpnext.hr.doctype.process_payroll.process_payroll.get_month_details',
|
method:'erpnext.hr.doctype.process_payroll.process_payroll.get_start_end_dates',
|
||||||
args:{
|
args:{
|
||||||
year: frm.doc.fiscal_year,
|
payroll_frequency: frm.doc.payroll_frequency,
|
||||||
month: frm.doc.month
|
start_date: frm.doc.start_date,
|
||||||
|
end_date: frm.doc.end_date
|
||||||
},
|
},
|
||||||
callback: function(r){
|
callback: function(r){
|
||||||
if (r.message){
|
if (r.message){
|
||||||
frm.set_value('from_date', r.message.month_start_date);
|
frm.set_value('start_date', r.message.start_date);
|
||||||
frm.set_value('to_date', r.message.month_end_date);
|
frm.set_value('end_date', r.message.end_date);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -56,17 +56,6 @@ frappe.ui.form.on("Process Payroll", {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
cur_frm.cscript.onload = function(doc,cdt,cdn){
|
|
||||||
if(!doc.month) {
|
|
||||||
var today=new Date();
|
|
||||||
month = (today.getMonth()+01).toString();
|
|
||||||
if(month.length>1) doc.month = month;
|
|
||||||
else doc.month = '0'+month;
|
|
||||||
}
|
|
||||||
if(!doc.fiscal_year) doc.fiscal_year = sys_defaults['fiscal_year'];
|
|
||||||
refresh_many(['month', 'fiscal_year']);
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_frm.cscript.display_activity_log = function(msg) {
|
cur_frm.cscript.display_activity_log = function(msg) {
|
||||||
if(!cur_frm.ss_html)
|
if(!cur_frm.ss_html)
|
||||||
cur_frm.ss_html = $a(cur_frm.fields_dict['activity_log'].wrapper,'div');
|
cur_frm.ss_html = $a(cur_frm.fields_dict['activity_log'].wrapper,'div');
|
||||||
@ -92,7 +81,7 @@ cur_frm.cscript.create_salary_slip = function(doc, cdt, cdn) {
|
|||||||
cur_frm.cscript.submit_salary_slip = function(doc, cdt, cdn) {
|
cur_frm.cscript.submit_salary_slip = function(doc, cdt, cdn) {
|
||||||
cur_frm.cscript.display_activity_log("");
|
cur_frm.cscript.display_activity_log("");
|
||||||
|
|
||||||
frappe.confirm(__("Do you really want to Submit all Salary Slip from {0} to {1}", [doc.from_date, doc.to_date]), function() {
|
frappe.confirm(__("Do you really want to Submit all Salary Slip from {0} to {1}", [doc.start_date, doc.end_date]), function() {
|
||||||
// clear all in locals
|
// clear all in locals
|
||||||
if(locals["Salary Slip"]) {
|
if(locals["Salary Slip"]) {
|
||||||
$.each(locals["Salary Slip"], function(name, d) {
|
$.each(locals["Salary Slip"], function(name, d) {
|
||||||
@ -110,7 +99,7 @@ cur_frm.cscript.submit_salary_slip = function(doc, cdt, cdn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.cscript.make_bank_entry = function(doc,cdt,cdn){
|
cur_frm.cscript.make_bank_entry = function(doc,cdt,cdn){
|
||||||
if(doc.company && doc.from_date && doc.to_date){
|
if(doc.company && doc.start_date && doc.end_date){
|
||||||
return cur_frm.cscript.reference_entry(doc,cdt,cdn);
|
return cur_frm.cscript.reference_entry(doc,cdt,cdn);
|
||||||
} else {
|
} else {
|
||||||
msgprint(__("Company, From Date and To Date is mandatory"));
|
msgprint(__("Company, From Date and To Date is mandatory"));
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Select Employees",
|
"label": "Select Employees",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -48,6 +49,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -67,6 +69,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"default": "",
|
||||||
"fieldname": "company",
|
"fieldname": "company",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -74,6 +77,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Company",
|
"label": "Company",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -102,6 +106,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Posting Date",
|
"label": "Posting Date",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -117,6 +122,37 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"default": "Monthly",
|
||||||
|
"depends_on": "eval:doc.salary_slip_based_on_timesheet == 0",
|
||||||
|
"fieldname": "payroll_frequency",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Payroll Frequency",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "\nMonthly\nFortnightly\nBimonthly\nWeekly\nDaily",
|
||||||
|
"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,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
@ -129,6 +165,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -155,6 +192,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Branch",
|
"label": "Branch",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -182,6 +220,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Department",
|
"label": "Department",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -209,6 +248,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Designation",
|
"label": "Designation",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -236,6 +276,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -262,6 +303,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Salary Slip Based on Timesheet",
|
"label": "Salary Slip Based on Timesheet",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -289,6 +331,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Select Payroll Period",
|
"label": "Select Payroll Period",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -309,14 +352,16 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "from_date",
|
"default": "Today",
|
||||||
"fieldtype": "Data",
|
"fieldname": "start_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
"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_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "From",
|
"in_standard_filter": 0,
|
||||||
|
"label": "Start Date",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -331,33 +376,6 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "fiscal_year",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Fiscal Year",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Fiscal Year",
|
|
||||||
"permlevel": 0,
|
|
||||||
"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,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
@ -370,6 +388,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -389,14 +408,16 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"fieldname": "to_date",
|
"default": "Today",
|
||||||
"fieldtype": "Data",
|
"fieldname": "end_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
"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_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "To",
|
"in_standard_filter": 0,
|
||||||
|
"label": "End Date",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -411,33 +432,6 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "month",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "Month",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12",
|
|
||||||
"permlevel": 0,
|
|
||||||
"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,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
@ -450,6 +444,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Process Payroll",
|
"label": "Process Payroll",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -477,6 +472,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -504,6 +500,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Create Salary Slip",
|
"label": "Create Salary Slip",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -530,6 +527,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -557,6 +555,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Submit Salary Slip",
|
"label": "Submit Salary Slip",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -583,6 +582,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Account",
|
"label": "Account",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -611,6 +611,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Payment Account",
|
"label": "Payment Account",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -632,15 +633,16 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"depends_on": "eval:doc.payment_account",
|
"depends_on": "",
|
||||||
"description": "Create Bank Entry for the total salary paid for the above selected criteria",
|
"description": "Create Bank Entry for the total salary paid for the above selected criteria",
|
||||||
"fieldname": "make_bank_entry",
|
"fieldname": "make_bank_entry",
|
||||||
"fieldtype": "Button",
|
"fieldtype": "Button",
|
||||||
"hidden": 0,
|
"hidden": 1,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Make Bank Entry",
|
"label": "Make Bank Entry",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -667,6 +669,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
@ -692,6 +695,7 @@
|
|||||||
"ignore_xss_filter": 0,
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Activity Log",
|
"label": "Activity Log",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
@ -718,7 +722,7 @@
|
|||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-11-03 16:02:34.040851",
|
"modified": "2016-11-26 01:14:51.691057",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Process Payroll",
|
"name": "Process Payroll",
|
||||||
|
@ -3,10 +3,12 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.utils import cint, flt, nowdate
|
from frappe.utils import cint, flt, nowdate, add_days, getdate
|
||||||
from frappe import _
|
from frappe import _
|
||||||
import collections
|
import collections
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
from calendar import monthrange
|
||||||
|
from erpnext.accounts.utils import get_fiscal_year
|
||||||
|
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
@ -19,7 +21,12 @@ class ProcessPayroll(Document):
|
|||||||
"""
|
"""
|
||||||
cond = self.get_filter_condition()
|
cond = self.get_filter_condition()
|
||||||
cond += self.get_joining_releiving_condition()
|
cond += self.get_joining_releiving_condition()
|
||||||
|
|
||||||
|
|
||||||
|
struct_cond = ''
|
||||||
|
if self.payroll_frequency:
|
||||||
|
struct_cond = """and payroll_frequency = '%(payroll_frequency)s'""" % {"payroll_frequency": self.payroll_frequency}
|
||||||
|
|
||||||
sal_struct = frappe.db.sql("""
|
sal_struct = frappe.db.sql("""
|
||||||
select name from `tabSalary Structure`
|
select name from `tabSalary Structure`
|
||||||
where docstatus != 2 and is_active = 'Yes' and company = %(company)s and
|
where docstatus != 2 and is_active = 'Yes' and company = %(company)s and
|
||||||
@ -28,13 +35,11 @@ class ProcessPayroll(Document):
|
|||||||
|
|
||||||
if sal_struct:
|
if sal_struct:
|
||||||
cond += "and t2.parent IN %(sal_struct)s "
|
cond += "and t2.parent IN %(sal_struct)s "
|
||||||
|
|
||||||
emp_list = frappe.db.sql("""
|
emp_list = frappe.db.sql("""
|
||||||
select t1.name
|
select t1.name
|
||||||
from `tabEmployee` t1, `tabSalary Structure Employee` t2
|
from `tabEmployee` t1, `tabSalary Structure Employee` t2
|
||||||
where t1.docstatus!=2 and t1.name = t2.employee
|
where t1.docstatus!=2 and t1.name = t2.employee
|
||||||
%s """% cond, {"sal_struct": sal_struct})
|
%s """% cond, {"sal_struct": sal_struct})
|
||||||
|
|
||||||
return emp_list
|
return emp_list
|
||||||
|
|
||||||
|
|
||||||
@ -51,16 +56,16 @@ class ProcessPayroll(Document):
|
|||||||
|
|
||||||
def get_joining_releiving_condition(self):
|
def get_joining_releiving_condition(self):
|
||||||
cond = """
|
cond = """
|
||||||
and ifnull(t1.date_of_joining, '0000-00-00') <= '%(to_date)s'
|
and ifnull(t1.date_of_joining, '0000-00-00') <= '%(end_date)s'
|
||||||
and ifnull(t1.relieving_date, '2199-12-31') >= '%(from_date)s'
|
and ifnull(t1.relieving_date, '2199-12-31') >= '%(start_date)s'
|
||||||
""" % {"from_date": self.from_date, "to_date": self.to_date}
|
""" % {"start_date": self.start_date, "end_date": self.end_date}
|
||||||
return cond
|
return cond
|
||||||
|
|
||||||
|
|
||||||
def check_mandatory(self):
|
def check_mandatory(self):
|
||||||
for f in ['company', 'from_date', 'to_date']:
|
for fieldname in ['company', 'payroll_frequency', 'start_date', 'end_date']:
|
||||||
if not self.get(f):
|
if not self.get(fieldname):
|
||||||
frappe.throw(_("Please set {0}").format(f))
|
frappe.throw(_("Please set {0}").format(self.meta.get_label(fieldname)))
|
||||||
|
|
||||||
def create_sal_slip(self):
|
def create_sal_slip(self):
|
||||||
"""
|
"""
|
||||||
@ -74,28 +79,28 @@ class ProcessPayroll(Document):
|
|||||||
for emp in emp_list:
|
for emp in emp_list:
|
||||||
if not frappe.db.sql("""select name from `tabSalary Slip`
|
if not frappe.db.sql("""select name from `tabSalary Slip`
|
||||||
where docstatus!= 2 and employee = %s and start_date >= %s and end_date <= %s and company = %s
|
where docstatus!= 2 and employee = %s and start_date >= %s and end_date <= %s and company = %s
|
||||||
""", (emp[0], self.from_date, self.to_date, self.company)):
|
""", (emp[0], self.start_date, self.end_date, self.company)):
|
||||||
if self.salary_slip_based_on_timesheet:
|
if self.payroll_frequency == "Monthly" or self.payroll_frequency == '':
|
||||||
ss = frappe.get_doc({
|
ss = frappe.get_doc({
|
||||||
"doctype": "Salary Slip",
|
"doctype": "Salary Slip",
|
||||||
"salary_slip_based_on_timesheet": self.salary_slip_based_on_timesheet,
|
"salary_slip_based_on_timesheet": self.salary_slip_based_on_timesheet,
|
||||||
"start_date": self.from_date,
|
|
||||||
"end_date": self.to_date,
|
|
||||||
"employee": emp[0],
|
"employee": emp[0],
|
||||||
"employee_name": frappe.get_value("Employee", {"name":emp[0]}, "employee_name"),
|
"employee_name": frappe.get_value("Employee", {"name":emp[0]}, "employee_name"),
|
||||||
"company": self.company,
|
"company": self.company,
|
||||||
"posting_date": self.posting_date
|
"posting_date": self.posting_date,
|
||||||
|
"payroll_frequency": self.payroll_frequency
|
||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
ss = frappe.get_doc({
|
ss = frappe.get_doc({
|
||||||
"doctype": "Salary Slip",
|
"doctype": "Salary Slip",
|
||||||
"salary_slip_based_on_timesheet": self.salary_slip_based_on_timesheet,
|
"salary_slip_based_on_timesheet": self.salary_slip_based_on_timesheet,
|
||||||
"fiscal_year": self.fiscal_year,
|
"start_date": self.start_date,
|
||||||
"month": self.month,
|
"end_date": self.end_date,
|
||||||
"employee": emp[0],
|
"employee": emp[0],
|
||||||
"employee_name": frappe.get_value("Employee", {"name":emp[0]}, "employee_name"),
|
"employee_name": frappe.get_value("Employee", {"name":emp[0]}, "employee_name"),
|
||||||
"company": self.company,
|
"company": self.company,
|
||||||
"posting_date": self.posting_date
|
"posting_date": self.posting_date,
|
||||||
|
"payroll_frequency": self.payroll_frequency
|
||||||
})
|
})
|
||||||
ss.insert()
|
ss.insert()
|
||||||
ss_list.append(ss.name)
|
ss_list.append(ss.name)
|
||||||
@ -120,7 +125,7 @@ class ProcessPayroll(Document):
|
|||||||
select t1.name, t1.salary_structure from `tabSalary Slip` t1
|
select t1.name, t1.salary_structure from `tabSalary Slip` t1
|
||||||
where t1.docstatus = %s and t1.start_date >= %s and t1.end_date <= %s
|
where t1.docstatus = %s and t1.start_date >= %s and t1.end_date <= %s
|
||||||
and (t1.journal_entry is null or t1.journal_entry = "") and ifnull(salary_slip_based_on_timesheet,0) = %s %s
|
and (t1.journal_entry is null or t1.journal_entry = "") and ifnull(salary_slip_based_on_timesheet,0) = %s %s
|
||||||
""" % ('%s', '%s', '%s','%s', cond), (ss_status, self.from_date, self.to_date, self.salary_slip_based_on_timesheet), as_dict=as_dict)
|
""" % ('%s', '%s', '%s','%s', cond), (ss_status, self.start_date, self.end_date, self.salary_slip_based_on_timesheet), as_dict=as_dict)
|
||||||
return ss_list
|
return ss_list
|
||||||
|
|
||||||
|
|
||||||
@ -183,7 +188,7 @@ class ProcessPayroll(Document):
|
|||||||
tot = frappe.db.sql("""
|
tot = frappe.db.sql("""
|
||||||
select sum(rounded_total) from `tabSalary Slip` t1
|
select sum(rounded_total) from `tabSalary Slip` t1
|
||||||
where t1.docstatus = 1 and start_date >= %s and end_date <= %s %s
|
where t1.docstatus = 1 and start_date >= %s and end_date <= %s %s
|
||||||
""" % ('%s', '%s', cond), (self.from_date, self.to_date))
|
""" % ('%s', '%s', cond), (self.start_date, self.end_date))
|
||||||
|
|
||||||
return flt(tot[0][0])
|
return flt(tot[0][0])
|
||||||
|
|
||||||
@ -231,8 +236,8 @@ class ProcessPayroll(Document):
|
|||||||
if earnings or deductions:
|
if earnings or deductions:
|
||||||
journal_entry = frappe.new_doc('Journal Entry')
|
journal_entry = frappe.new_doc('Journal Entry')
|
||||||
journal_entry.voucher_type = 'Bank Entry'
|
journal_entry.voucher_type = 'Bank Entry'
|
||||||
journal_entry.user_remark = _('Payment of salary from {0} to {1}').format(self.from_date,
|
journal_entry.user_remark = _('Payment of salary from {0} to {1}').format(self.start_date,
|
||||||
self.to_date)
|
self.end_date)
|
||||||
journal_entry.company = self.company
|
journal_entry.company = self.company
|
||||||
journal_entry.posting_date = nowdate()
|
journal_entry.posting_date = nowdate()
|
||||||
|
|
||||||
@ -257,6 +262,7 @@ class ProcessPayroll(Document):
|
|||||||
journal_entry.set("accounts", account_amt_list)
|
journal_entry.set("accounts", account_amt_list)
|
||||||
journal_entry.cheque_no = reference_number
|
journal_entry.cheque_no = reference_number
|
||||||
journal_entry.cheque_date = reference_date
|
journal_entry.cheque_date = reference_date
|
||||||
|
journal_entry.multi_currency = 1
|
||||||
journal_entry.save()
|
journal_entry.save()
|
||||||
try:
|
try:
|
||||||
journal_entry.submit()
|
journal_entry.submit()
|
||||||
@ -279,7 +285,7 @@ class ProcessPayroll(Document):
|
|||||||
for ss in ss_list:
|
for ss in ss_list:
|
||||||
ss_obj = frappe.get_doc("Salary Slip",ss[0])
|
ss_obj = frappe.get_doc("Salary Slip",ss[0])
|
||||||
frappe.db.set_value("Salary Slip", ss_obj.name, "status", "Paid")
|
frappe.db.set_value("Salary Slip", ss_obj.name, "status", "Paid")
|
||||||
frappe.db.set_value("Salary Slip", ss_obj.name, "journal_entry", jv_name)
|
frappe.db.set_value("Salary Slip", ss_obj.name, "journal_entry", jv_name)
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
@ -293,12 +299,45 @@ def get_month_details(year, month):
|
|||||||
diff_mnt = 12-int(ysd.month)+cint(month)
|
diff_mnt = 12-int(ysd.month)+cint(month)
|
||||||
msd = ysd + relativedelta(months=diff_mnt) # month start date
|
msd = ysd + relativedelta(months=diff_mnt) # month start date
|
||||||
month_days = cint(calendar.monthrange(cint(msd.year) ,cint(month))[1]) # days in month
|
month_days = cint(calendar.monthrange(cint(msd.year) ,cint(month))[1]) # days in month
|
||||||
|
mid_start = datetime.date(msd.year, cint(month), 16) # month mid start date
|
||||||
|
mid_end = datetime.date(msd.year, cint(month), 15) # month mid end date
|
||||||
med = datetime.date(msd.year, cint(month), month_days) # month end date
|
med = datetime.date(msd.year, cint(month), month_days) # month end date
|
||||||
return frappe._dict({
|
return frappe._dict({
|
||||||
'year': msd.year,
|
'year': msd.year,
|
||||||
'month_start_date': msd,
|
'month_start_date': msd,
|
||||||
'month_end_date': med,
|
'month_end_date': med,
|
||||||
|
'month_mid_start_date': mid_start,
|
||||||
|
'month_mid_end_date': mid_end,
|
||||||
'month_days': month_days
|
'month_days': month_days
|
||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
frappe.throw(_("Fiscal Year {0} not found").format(year))
|
frappe.throw(_("Fiscal Year {0} not found").format(year))
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_start_end_dates(payroll_frequency, start_date, end_date):
|
||||||
|
if payroll_frequency == "Monthly" or payroll_frequency == "Bimonthly":
|
||||||
|
fiscal_year = get_fiscal_year(start_date)[0] or get_fiscal_year(end_date)[0]
|
||||||
|
month = "%02d" % getdate(start_date).month or "%02d" % getdate(end_date).month
|
||||||
|
m = get_month_details(fiscal_year, month)
|
||||||
|
if payroll_frequency == "Bimonthly":
|
||||||
|
if getdate(start_date).day <= 15:
|
||||||
|
start_date = m['month_start_date']
|
||||||
|
end_date = m['month_mid_end_date']
|
||||||
|
else:
|
||||||
|
start_date = m['month_mid_start_date']
|
||||||
|
end_date = m['month_end_date']
|
||||||
|
else:
|
||||||
|
start_date = m['month_start_date']
|
||||||
|
end_date = m['month_end_date']
|
||||||
|
|
||||||
|
if payroll_frequency == "Weekly":
|
||||||
|
end_date = add_days(start_date, 6)
|
||||||
|
|
||||||
|
if payroll_frequency == "Fortnightly":
|
||||||
|
end_date = add_days(start_date, 13)
|
||||||
|
|
||||||
|
if payroll_frequency == "Daily":
|
||||||
|
end_date = start_date
|
||||||
|
return frappe._dict({
|
||||||
|
'start_date': start_date, 'end_date': end_date
|
||||||
|
})
|
@ -18,15 +18,14 @@ class TestProcessPayroll(unittest.TestCase):
|
|||||||
get_salary_component_account(data.name)
|
get_salary_component_account(data.name)
|
||||||
|
|
||||||
payment_account = frappe.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name")
|
payment_account = frappe.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name")
|
||||||
if not frappe.db.get_value("Salary Slip", {"fiscal_year": fiscal_year, "month": month}):
|
if not frappe.db.get_value("Salary Slip", {"start_date": "2016-11-01", "end_date": "2016-11-30"}):
|
||||||
process_payroll = frappe.get_doc("Process Payroll", "Process Payroll")
|
process_payroll = frappe.get_doc("Process Payroll", "Process Payroll")
|
||||||
process_payroll.company = erpnext.get_default_company()
|
process_payroll.company = erpnext.get_default_company()
|
||||||
process_payroll.month = month
|
process_payroll.start_date = "2016-11-01"
|
||||||
process_payroll.fiscal_year = fiscal_year
|
process_payroll.end_date = "2016-11-30"
|
||||||
process_payroll.from_date = "2016-11-01"
|
|
||||||
process_payroll.to_date = "2016-11-30"
|
|
||||||
process_payroll.payment_account = payment_account
|
process_payroll.payment_account = payment_account
|
||||||
process_payroll.posting_date = nowdate()
|
process_payroll.posting_date = nowdate()
|
||||||
|
process_payroll.payroll_frequency = "Monthly"
|
||||||
process_payroll.create_sal_slip()
|
process_payroll.create_sal_slip()
|
||||||
process_payroll.submit_salary_slip()
|
process_payroll.submit_salary_slip()
|
||||||
if process_payroll.get_sal_slip_list(ss_status = 1):
|
if process_payroll.get_sal_slip_list(ss_status = 1):
|
||||||
|
@ -46,59 +46,44 @@ frappe.ui.form.on("Salary Slip", {
|
|||||||
salary_slip_based_on_timesheet: function(frm) {
|
salary_slip_based_on_timesheet: function(frm) {
|
||||||
frm.trigger("toggle_fields")
|
frm.trigger("toggle_fields")
|
||||||
},
|
},
|
||||||
|
|
||||||
|
payroll_frequency: function(frm) {
|
||||||
|
frm.trigger("toggle_fields")
|
||||||
|
},
|
||||||
|
|
||||||
toggle_fields: function(frm) {
|
toggle_fields: function(frm) {
|
||||||
frm.toggle_display(['start_date', 'end_date', 'hourly_wages', 'timesheets'],
|
frm.toggle_display(['hourly_wages', 'timesheets'],
|
||||||
cint(frm.doc.salary_slip_based_on_timesheet)==1);
|
cint(frm.doc.salary_slip_based_on_timesheet)==1);
|
||||||
frm.toggle_display(['fiscal_year', 'month', 'total_days_in_month', 'leave_without_pay', 'payment_days'],
|
|
||||||
cint(frm.doc.salary_slip_based_on_timesheet)==0);
|
frm.toggle_display(['payment_days', 'total_working_days', 'leave_without_pay'],
|
||||||
|
frm.doc.payroll_frequency!="");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
frappe.ui.form.on("Salary Slip Timesheet", {
|
|
||||||
time_sheet: function(frm, cdt, cdn) {
|
|
||||||
doc = frm.doc;
|
|
||||||
cur_frm.cscript.fiscal_year(doc, cdt, cdn)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
// On load
|
|
||||||
// -------------------------------------------------------------------
|
|
||||||
cur_frm.cscript.onload = function(doc,dt,dn){
|
|
||||||
if((cint(doc.__islocal) == 1) && !doc.amended_from){
|
|
||||||
if(!doc.month) {
|
|
||||||
var today=new Date();
|
|
||||||
month = (today.getMonth()+01).toString();
|
|
||||||
if(month.length>1) doc.month = month;
|
|
||||||
else doc.month = '0'+month;
|
|
||||||
}
|
|
||||||
if(!doc.fiscal_year) doc.fiscal_year = sys_defaults['fiscal_year'];
|
|
||||||
refresh_many(['month', 'fiscal_year']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get leave details
|
// Get leave details
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
cur_frm.cscript.fiscal_year = function(doc,dt,dn){
|
cur_frm.cscript.start_date = function(doc, dt, dn){
|
||||||
return $c_obj(doc, 'get_emp_and_leave_details','',function(r, rt) {
|
return frappe.call({
|
||||||
var doc = locals[dt][dn];
|
method: 'get_emp_and_leave_details',
|
||||||
|
doc: locals[dt][dn],
|
||||||
|
callback: function(r, rt) {
|
||||||
cur_frm.refresh();
|
cur_frm.refresh();
|
||||||
calculate_all(doc, dt, dn);
|
calculate_all(doc, dt, dn);
|
||||||
});
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.cscript.month = cur_frm.cscript.salary_slip_based_on_timesheet = cur_frm.cscript.fiscal_year;
|
cur_frm.cscript.payroll_frequency = cur_frm.cscript.salary_slip_based_on_timesheet = cur_frm.cscript.start_date;
|
||||||
cur_frm.cscript.start_date = cur_frm.cscript.end_date = cur_frm.cscript.fiscal_year;
|
cur_frm.cscript.end_date = cur_frm.cscript.start_date;
|
||||||
|
|
||||||
cur_frm.cscript.employee = function(doc,dt,dn){
|
cur_frm.cscript.employee = function(doc,dt,dn){
|
||||||
doc.salary_structure = ''
|
doc.salary_structure = ''
|
||||||
cur_frm.cscript.fiscal_year(doc, dt, dn)
|
cur_frm.cscript.start_date(doc, dt, dn)
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.cscript.leave_without_pay = function(doc,dt,dn){
|
cur_frm.cscript.leave_without_pay = function(doc,dt,dn){
|
||||||
if (doc.employee && doc.fiscal_year && doc.month) {
|
if (doc.employee && doc.start_date && doc.end_date) {
|
||||||
return $c_obj(doc, 'get_leave_details', {"lwp": doc.leave_without_pay}, function(r, rt) {
|
return $c_obj(doc, 'get_leave_details', {"lwp": doc.leave_without_pay}, function(r, rt) {
|
||||||
var doc = locals[dt][dn];
|
var doc = locals[dt][dn];
|
||||||
cur_frm.refresh();
|
cur_frm.refresh();
|
||||||
@ -135,7 +120,7 @@ var calculate_earning_total = function(doc, dt, dn, reset_amount) {
|
|||||||
for(var i = 0; i < tbl.length; i++){
|
for(var i = 0; i < tbl.length; i++){
|
||||||
if(cint(tbl[i].depends_on_lwp) == 1) {
|
if(cint(tbl[i].depends_on_lwp) == 1) {
|
||||||
tbl[i].amount = Math.round(tbl[i].default_amount)*(flt(doc.payment_days) /
|
tbl[i].amount = Math.round(tbl[i].default_amount)*(flt(doc.payment_days) /
|
||||||
cint(doc.total_days_in_month)*100)/100;
|
cint(doc.total_working_days)*100)/100;
|
||||||
refresh_field('amount', tbl[i].name, 'earnings');
|
refresh_field('amount', tbl[i].name, 'earnings');
|
||||||
} else if(reset_amount) {
|
} else if(reset_amount) {
|
||||||
tbl[i].amount = tbl[i].default_amount;
|
tbl[i].amount = tbl[i].default_amount;
|
||||||
@ -155,7 +140,7 @@ var calculate_ded_total = function(doc, dt, dn, reset_amount) {
|
|||||||
var total_ded = 0;
|
var total_ded = 0;
|
||||||
for(var i = 0; i < tbl.length; i++){
|
for(var i = 0; i < tbl.length; i++){
|
||||||
if(cint(tbl[i].depends_on_lwp) == 1) {
|
if(cint(tbl[i].depends_on_lwp) == 1) {
|
||||||
tbl[i].amount = Math.round(tbl[i].default_amount)*(flt(doc.payment_days)/cint(doc.total_days_in_month)*100)/100;
|
tbl[i].amount = Math.round(tbl[i].default_amount)*(flt(doc.payment_days)/cint(doc.total_working_days)*100)/100;
|
||||||
refresh_field('amount', tbl[i].name, 'deductions');
|
refresh_field('amount', tbl[i].name, 'deductions');
|
||||||
} else if(reset_amount) {
|
} else if(reset_amount) {
|
||||||
tbl[i].amount = tbl[i].default_amount;
|
tbl[i].amount = tbl[i].default_amount;
|
||||||
|
@ -421,69 +421,7 @@
|
|||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"depends_on": "",
|
"default": "Today",
|
||||||
"fieldname": "fiscal_year",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 1,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Fiscal Year",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "fiscal_year",
|
|
||||||
"oldfieldtype": "Data",
|
|
||||||
"options": "Fiscal Year",
|
|
||||||
"permlevel": 0,
|
|
||||||
"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,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "",
|
|
||||||
"fieldname": "month",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 1,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 1,
|
|
||||||
"label": "Month",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "month",
|
|
||||||
"oldfieldtype": "Select",
|
|
||||||
"options": "\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 1,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0,
|
|
||||||
"width": "37%"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "start_date",
|
"fieldname": "start_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -594,13 +532,44 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"default": "",
|
||||||
|
"depends_on": "eval:(!doc.salary_slip_based_on_timesheet)",
|
||||||
|
"fieldname": "payroll_frequency",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Payroll Frequency",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "\nMonthly\nFortnightly\nBimonthly\nWeekly\nDaily",
|
||||||
|
"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,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
"depends_on": "",
|
"depends_on": "",
|
||||||
"fieldname": "total_days_in_month",
|
"fieldname": "total_working_days",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
@ -1392,7 +1361,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-11-07 05:58:37.151587",
|
"modified": "2016-12-08 12:03:31.602913",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Salary Slip",
|
"name": "Salary Slip",
|
||||||
|
@ -10,10 +10,12 @@ from frappe.model.naming import make_autoname
|
|||||||
from frappe import msgprint, _
|
from frappe import msgprint, _
|
||||||
from erpnext.accounts.utils import get_fiscal_year
|
from erpnext.accounts.utils import get_fiscal_year
|
||||||
from erpnext.setup.utils import get_company_currency
|
from erpnext.setup.utils import get_company_currency
|
||||||
from erpnext.hr.doctype.process_payroll.process_payroll import get_month_details
|
from erpnext.hr.doctype.process_payroll.process_payroll import get_month_details, get_start_end_dates
|
||||||
from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
|
from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
|
||||||
from erpnext.utilities.transaction_base import TransactionBase
|
from erpnext.utilities.transaction_base import TransactionBase
|
||||||
|
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
class SalarySlip(TransactionBase):
|
class SalarySlip(TransactionBase):
|
||||||
def autoname(self):
|
def autoname(self):
|
||||||
self.name = make_autoname('Sal Slip/' +self.employee + '/.#####')
|
self.name = make_autoname('Sal Slip/' +self.employee + '/.#####')
|
||||||
@ -22,8 +24,7 @@ class SalarySlip(TransactionBase):
|
|||||||
self.status = self.get_status()
|
self.status = self.get_status()
|
||||||
self.validate_dates()
|
self.validate_dates()
|
||||||
self.check_existing()
|
self.check_existing()
|
||||||
self.set_month_dates()
|
self.get_date_details()
|
||||||
|
|
||||||
if not (len(self.get("earnings")) or len(self.get("deductions"))):
|
if not (len(self.get("earnings")) or len(self.get("deductions"))):
|
||||||
# get details from salary structure
|
# get details from salary structure
|
||||||
self.get_emp_and_leave_details()
|
self.get_emp_and_leave_details()
|
||||||
@ -120,7 +121,7 @@ class SalarySlip(TransactionBase):
|
|||||||
self.set("earnings", [])
|
self.set("earnings", [])
|
||||||
self.set("deductions", [])
|
self.set("deductions", [])
|
||||||
|
|
||||||
self.set_month_dates()
|
self.get_date_details()
|
||||||
self.validate_dates()
|
self.validate_dates()
|
||||||
joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
|
joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
|
||||||
["date_of_joining", "relieving_date"])
|
["date_of_joining", "relieving_date"])
|
||||||
@ -146,20 +147,24 @@ class SalarySlip(TransactionBase):
|
|||||||
'working_hours': data.total_hours
|
'working_hours': data.total_hours
|
||||||
})
|
})
|
||||||
|
|
||||||
def set_month_dates(self):
|
def get_date_details(self):
|
||||||
if self.month and not self.salary_slip_based_on_timesheet:
|
date_details = get_start_end_dates(self.payroll_frequency, self.start_date, self.end_date)
|
||||||
m = get_month_details(self.fiscal_year, self.month)
|
self.start_date = date_details.start_date
|
||||||
self.start_date = m['month_start_date']
|
self.end_date = date_details.end_date
|
||||||
self.end_date = m['month_end_date']
|
|
||||||
|
|
||||||
def check_sal_struct(self, joining_date, relieving_date):
|
def check_sal_struct(self, joining_date, relieving_date):
|
||||||
|
cond = ''
|
||||||
|
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 parent from `tabSalary Structure Employee`
|
||||||
where employee=%s
|
where employee=%s
|
||||||
and parent in (select name from `tabSalary Structure`
|
and parent in (select name from `tabSalary Structure`
|
||||||
where is_active = 'Yes'
|
where is_active = 'Yes'
|
||||||
and (from_date <= %s or from_date <= %s)
|
and (from_date <= %s or from_date <= %s)
|
||||||
and (to_date is null or to_date >= %s or to_date >= %s))
|
and (to_date is null or to_date >= %s or to_date >= %s) %s)
|
||||||
""",(self.employee, self.start_date, joining_date, self.end_date, relieving_date))
|
"""% ('%s', '%s', '%s','%s','%s', cond),(self.employee, self.start_date, joining_date, self.end_date, relieving_date))
|
||||||
|
|
||||||
if st_name:
|
if st_name:
|
||||||
if len(st_name) > 1:
|
if len(st_name) > 1:
|
||||||
@ -185,9 +190,11 @@ class SalarySlip(TransactionBase):
|
|||||||
|
|
||||||
def process_salary_structure(self):
|
def process_salary_structure(self):
|
||||||
'''Calculate salary after salary structure details have been updated'''
|
'''Calculate salary after salary structure details have been updated'''
|
||||||
|
self.get_date_details()
|
||||||
self.pull_emp_details()
|
self.pull_emp_details()
|
||||||
self.get_leave_details()
|
self.get_leave_details()
|
||||||
self.calculate_net_pay()
|
self.calculate_net_pay()
|
||||||
|
|
||||||
|
|
||||||
def add_earning_for_hourly_wages(self, salary_component):
|
def add_earning_for_hourly_wages(self, salary_component):
|
||||||
default_type = False
|
default_type = False
|
||||||
@ -210,14 +217,6 @@ class SalarySlip(TransactionBase):
|
|||||||
|
|
||||||
|
|
||||||
def get_leave_details(self, joining_date=None, relieving_date=None, lwp=None):
|
def get_leave_details(self, joining_date=None, relieving_date=None, lwp=None):
|
||||||
if not self.fiscal_year:
|
|
||||||
# if default fiscal year is not set, get from nowdate
|
|
||||||
self.fiscal_year = get_fiscal_year(nowdate())[0]
|
|
||||||
|
|
||||||
if not self.month:
|
|
||||||
self.month = "%02d" % getdate(nowdate()).month
|
|
||||||
self.set_month_dates()
|
|
||||||
|
|
||||||
if not joining_date:
|
if not joining_date:
|
||||||
joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
|
joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
|
||||||
["date_of_joining", "relieving_date"])
|
["date_of_joining", "relieving_date"])
|
||||||
@ -236,7 +235,7 @@ class SalarySlip(TransactionBase):
|
|||||||
elif lwp != actual_lwp:
|
elif lwp != actual_lwp:
|
||||||
frappe.msgprint(_("Leave Without Pay does not match with approved Leave Application records"))
|
frappe.msgprint(_("Leave Without Pay does not match with approved Leave Application records"))
|
||||||
|
|
||||||
self.total_days_in_month = working_days
|
self.total_working_days = working_days
|
||||||
self.leave_without_pay = lwp
|
self.leave_without_pay = lwp
|
||||||
|
|
||||||
payment_days = flt(self.get_payment_days(joining_date, relieving_date)) - flt(lwp)
|
payment_days = flt(self.get_payment_days(joining_date, relieving_date)) - flt(lwp)
|
||||||
@ -306,9 +305,9 @@ class SalarySlip(TransactionBase):
|
|||||||
def check_existing(self):
|
def check_existing(self):
|
||||||
if not self.salary_slip_based_on_timesheet:
|
if not self.salary_slip_based_on_timesheet:
|
||||||
ret_exist = frappe.db.sql("""select name from `tabSalary Slip`
|
ret_exist = frappe.db.sql("""select name from `tabSalary Slip`
|
||||||
where month = %s and fiscal_year = %s and docstatus != 2
|
where start_date = %s and end_date = %s and docstatus != 2
|
||||||
and employee = %s and name != %s""",
|
and employee = %s and name != %s""",
|
||||||
(self.month, self.fiscal_year, self.employee, self.name))
|
(self.start_date, self.end_date, self.employee, self.name))
|
||||||
if ret_exist:
|
if ret_exist:
|
||||||
self.employee = ''
|
self.employee = ''
|
||||||
frappe.throw(_("Salary Slip of employee {0} already created for this period").format(self.employee))
|
frappe.throw(_("Salary Slip of employee {0} already created for this period").format(self.employee))
|
||||||
@ -321,7 +320,7 @@ class SalarySlip(TransactionBase):
|
|||||||
for d in self.get(component_type):
|
for d in self.get(component_type):
|
||||||
if cint(d.depends_on_lwp) == 1 and not self.salary_slip_based_on_timesheet:
|
if cint(d.depends_on_lwp) == 1 and not self.salary_slip_based_on_timesheet:
|
||||||
d.amount = rounded((flt(d.default_amount) * flt(self.payment_days)
|
d.amount = rounded((flt(d.default_amount) * flt(self.payment_days)
|
||||||
/ cint(self.total_days_in_month)), self.precision("amount", component_type))
|
/ cint(self.total_working_days)), self.precision("amount", component_type))
|
||||||
elif not self.payment_days and not self.salary_slip_based_on_timesheet:
|
elif not self.payment_days and not self.salary_slip_based_on_timesheet:
|
||||||
d.amount = 0
|
d.amount = 0
|
||||||
elif not d.amount:
|
elif not d.amount:
|
||||||
@ -361,7 +360,7 @@ class SalarySlip(TransactionBase):
|
|||||||
receiver = frappe.db.get_value("Employee", self.employee, "prefered_email")
|
receiver = frappe.db.get_value("Employee", self.employee, "prefered_email")
|
||||||
|
|
||||||
if receiver:
|
if receiver:
|
||||||
subj = 'Salary Slip - from {0} to {1}, fiscal year {2}'.format(self.start_date, self.end_date, self.fiscal_year)
|
subj = 'Salary Slip - from {0} to {1}'.format(self.start_date, self.end_date)
|
||||||
frappe.sendmail([receiver], subject=subj, message = _("Please see attachment"),
|
frappe.sendmail([receiver], subject=subj, message = _("Please see attachment"),
|
||||||
attachments=[frappe.attach_print(self.doctype, self.name, file_name=self.name)], reference_doctype= self.doctype, reference_name= self.name)
|
attachments=[frappe.attach_print(self.doctype, self.name, file_name=self.name)], reference_doctype= self.doctype, reference_name= self.name)
|
||||||
else:
|
else:
|
||||||
|
@ -40,6 +40,6 @@
|
|||||||
"fiscal_year": "_Test Fiscal Year 2013",
|
"fiscal_year": "_Test Fiscal Year 2013",
|
||||||
"month": "01",
|
"month": "01",
|
||||||
"payment_days": 31,
|
"payment_days": 31,
|
||||||
"total_days_in_month": 31
|
"total_working_days": 31
|
||||||
}
|
}
|
||||||
]
|
]
|
@ -6,18 +6,22 @@ import unittest
|
|||||||
import frappe
|
import frappe
|
||||||
import erpnext
|
import erpnext
|
||||||
from frappe.utils.make_random import get_random
|
from frappe.utils.make_random import get_random
|
||||||
from frappe.utils import today, now_datetime, getdate, cstr, add_years, nowdate
|
from erpnext.accounts.utils import get_fiscal_year
|
||||||
|
from frappe.utils import today, now_datetime, getdate, cstr, add_years, nowdate, add_days
|
||||||
from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
|
from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
|
||||||
from erpnext.hr.doctype.process_payroll.test_process_payroll import get_salary_component_account
|
from erpnext.hr.doctype.process_payroll.test_process_payroll import get_salary_component_account
|
||||||
|
from erpnext.hr.doctype.process_payroll.process_payroll import get_month_details
|
||||||
|
|
||||||
class TestSalarySlip(unittest.TestCase):
|
class TestSalarySlip(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
make_salary_component(["Basic Salary", "Allowance", "HRA", "Professional Tax", "TDS"])
|
make_earning_salary_component(["Basic Salary", "Allowance", "HRA"])
|
||||||
|
make_deduction_salary_component(["Professional Tax", "TDS"])
|
||||||
|
|
||||||
for dt in ["Leave Application", "Leave Allocation", "Salary Slip"]:
|
for dt in ["Leave Application", "Leave Allocation", "Salary Slip"]:
|
||||||
frappe.db.sql("delete from `tab%s`" % dt)
|
frappe.db.sql("delete from `tab%s`" % dt)
|
||||||
|
|
||||||
self.make_holiday_list()
|
self.make_holiday_list()
|
||||||
|
|
||||||
frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", "Salary Slip Test Holiday List")
|
frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", "Salary Slip Test Holiday List")
|
||||||
|
|
||||||
from erpnext.hr.doctype.leave_application.test_leave_application import _test_records as leave_applications
|
from erpnext.hr.doctype.leave_application.test_leave_application import _test_records as leave_applications
|
||||||
@ -36,9 +40,9 @@ class TestSalarySlip(unittest.TestCase):
|
|||||||
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
|
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
|
||||||
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "status", "Active")
|
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "status", "Active")
|
||||||
ss = frappe.get_doc("Salary Slip",
|
ss = frappe.get_doc("Salary Slip",
|
||||||
self.make_employee_salary_slip("test_employee@salary.com"))
|
self.make_employee_salary_slip("test_employee@salary.com", "Monthly"))
|
||||||
|
|
||||||
self.assertEquals(ss.total_days_in_month, 31)
|
self.assertEquals(ss.total_working_days, 31)
|
||||||
self.assertEquals(ss.payment_days, 31)
|
self.assertEquals(ss.payment_days, 31)
|
||||||
self.assertEquals(ss.earnings[0].amount, 5000)
|
self.assertEquals(ss.earnings[0].amount, 5000)
|
||||||
self.assertEquals(ss.earnings[1].amount, 3000)
|
self.assertEquals(ss.earnings[1].amount, 3000)
|
||||||
@ -53,9 +57,9 @@ class TestSalarySlip(unittest.TestCase):
|
|||||||
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
|
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", None)
|
||||||
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "status", "Active")
|
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "status", "Active")
|
||||||
ss = frappe.get_doc("Salary Slip",
|
ss = frappe.get_doc("Salary Slip",
|
||||||
self.make_employee_salary_slip("test_employee@salary.com"))
|
self.make_employee_salary_slip("test_employee@salary.com", "Monthly"))
|
||||||
|
|
||||||
self.assertEquals(ss.total_days_in_month, 28)
|
self.assertEquals(ss.total_working_days, 28)
|
||||||
self.assertEquals(ss.payment_days, 28)
|
self.assertEquals(ss.payment_days, 28)
|
||||||
self.assertEquals(ss.earnings[0].amount, 5000)
|
self.assertEquals(ss.earnings[0].amount, 5000)
|
||||||
self.assertEquals(ss.earnings[0].default_amount, 5000)
|
self.assertEquals(ss.earnings[0].default_amount, 5000)
|
||||||
@ -74,16 +78,16 @@ class TestSalarySlip(unittest.TestCase):
|
|||||||
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "date_of_joining", "2013-01-11")
|
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "date_of_joining", "2013-01-11")
|
||||||
|
|
||||||
ss = frappe.get_doc("Salary Slip",
|
ss = frappe.get_doc("Salary Slip",
|
||||||
self.make_employee_salary_slip("test_employee@salary.com"))
|
self.make_employee_salary_slip("test_employee@salary.com", "Monthly"))
|
||||||
|
|
||||||
self.assertEquals(ss.total_days_in_month, 28)
|
self.assertEquals(ss.total_working_days, 28)
|
||||||
self.assertEquals(ss.payment_days, 28)
|
self.assertEquals(ss.payment_days, 28)
|
||||||
|
|
||||||
# set relieving date in the same month
|
# set relieving date in the same month
|
||||||
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", "12-12-2016")
|
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "relieving_date", "12-12-2016")
|
||||||
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "status", "Left")
|
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "status", "Left")
|
||||||
|
|
||||||
self.assertEquals(ss.total_days_in_month, 28)
|
self.assertEquals(ss.total_working_days, 28)
|
||||||
self.assertEquals(ss.payment_days, 28)
|
self.assertEquals(ss.payment_days, 28)
|
||||||
ss.save()
|
ss.save()
|
||||||
|
|
||||||
@ -91,7 +95,7 @@ class TestSalarySlip(unittest.TestCase):
|
|||||||
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "status", "Active")
|
frappe.db.set_value("Employee", frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"), "status", "Active")
|
||||||
# Holidays included in working days
|
# Holidays included in working days
|
||||||
frappe.db.set_value("HR Settings", None, "include_holidays_in_total_working_days", 1)
|
frappe.db.set_value("HR Settings", None, "include_holidays_in_total_working_days", 1)
|
||||||
self.assertEquals(ss.total_days_in_month, 28)
|
self.assertEquals(ss.total_working_days, 28)
|
||||||
self.assertEquals(ss.payment_days, 28)
|
self.assertEquals(ss.payment_days, 28)
|
||||||
ss.save()
|
ss.save()
|
||||||
#
|
#
|
||||||
@ -102,7 +106,7 @@ class TestSalarySlip(unittest.TestCase):
|
|||||||
self.make_employee("test_employee@salary.com")
|
self.make_employee("test_employee@salary.com")
|
||||||
|
|
||||||
salary_slip_test_employee = frappe.get_doc("Salary Slip",
|
salary_slip_test_employee = frappe.get_doc("Salary Slip",
|
||||||
self.make_employee_salary_slip("test_employee@salary.com"))
|
self.make_employee_salary_slip("test_employee@salary.com", "Monthly"))
|
||||||
frappe.set_user("test_employee@salary.com")
|
frappe.set_user("test_employee@salary.com")
|
||||||
self.assertTrue(salary_slip_test_employee.has_permission("read"))
|
self.assertTrue(salary_slip_test_employee.has_permission("read"))
|
||||||
|
|
||||||
@ -115,11 +119,33 @@ class TestSalarySlip(unittest.TestCase):
|
|||||||
|
|
||||||
self.make_employee("test_employee@salary.com")
|
self.make_employee("test_employee@salary.com")
|
||||||
ss = frappe.get_doc("Salary Slip",
|
ss = frappe.get_doc("Salary Slip",
|
||||||
self.make_employee_salary_slip("test_employee@salary.com"))
|
self.make_employee_salary_slip("test_employee@salary.com", "Monthly"))
|
||||||
ss.submit()
|
ss.submit()
|
||||||
email_queue = frappe.db.sql("""select name from `tabEmail Queue`""")
|
email_queue = frappe.db.sql("""select name from `tabEmail Queue`""")
|
||||||
self.assertTrue(email_queue)
|
self.assertTrue(email_queue)
|
||||||
|
|
||||||
|
def test_payroll_frequency(self):
|
||||||
|
fiscal_year = get_fiscal_year(nowdate())[0]
|
||||||
|
month = "%02d" % getdate(nowdate()).month or "%02d" % getdate(nowdate()).month
|
||||||
|
m = get_month_details(fiscal_year, month)
|
||||||
|
|
||||||
|
for payroll_frequncy in ["Monthly", "Bimonthly", "Fortnightly", "Weekly", "Daily"]:
|
||||||
|
self.make_employee(payroll_frequncy + "_test_employee@salary.com")
|
||||||
|
ss = frappe.get_doc("Salary Slip",
|
||||||
|
self.make_employee_salary_slip(payroll_frequncy + "_test_employee@salary.com", payroll_frequncy))
|
||||||
|
if payroll_frequncy == "Monthly":
|
||||||
|
self.assertEqual(ss.end_date, m['month_end_date'])
|
||||||
|
elif payroll_frequncy == "Bimonthly":
|
||||||
|
if getdate(ss.start_date).day <= 15:
|
||||||
|
self.assertEqual(ss.end_date, m['month_mid_end_date'])
|
||||||
|
else:
|
||||||
|
self.assertEqual(ss.end_date, m['month_end_date'])
|
||||||
|
elif payroll_frequncy == "Fortnightly":
|
||||||
|
self.assertEqual(ss.end_date, getdate(add_days(nowdate(),13)))
|
||||||
|
elif payroll_frequncy == "Weekly":
|
||||||
|
self.assertEqual(ss.end_date, getdate(add_days(nowdate(),6)))
|
||||||
|
elif payroll_frequncy == "Daily":
|
||||||
|
self.assertEqual(ss.end_date, getdate(nowdate()))
|
||||||
|
|
||||||
def make_employee(self, user):
|
def make_employee(self, user):
|
||||||
if not frappe.db.get_value("User", user):
|
if not frappe.db.get_value("User", user):
|
||||||
@ -148,7 +174,7 @@ class TestSalarySlip(unittest.TestCase):
|
|||||||
"status": "Active",
|
"status": "Active",
|
||||||
"employment_type": "Intern"
|
"employment_type": "Intern"
|
||||||
}).insert()
|
}).insert()
|
||||||
|
|
||||||
def make_holiday_list(self):
|
def make_holiday_list(self):
|
||||||
if not frappe.db.get_value("Holiday List", "Salary Slip Test Holiday List"):
|
if not frappe.db.get_value("Holiday List", "Salary Slip Test Holiday List"):
|
||||||
holiday_list = frappe.get_doc({
|
holiday_list = frappe.get_doc({
|
||||||
@ -160,17 +186,17 @@ class TestSalarySlip(unittest.TestCase):
|
|||||||
}).insert()
|
}).insert()
|
||||||
holiday_list.get_weekly_off_dates()
|
holiday_list.get_weekly_off_dates()
|
||||||
holiday_list.save()
|
holiday_list.save()
|
||||||
|
|
||||||
def make_employee_salary_slip(self, user):
|
def make_employee_salary_slip(self, user, payroll_frequency):
|
||||||
employee = frappe.db.get_value("Employee", {"user_id": user})
|
employee = frappe.db.get_value("Employee", {"user_id": user})
|
||||||
salary_structure = make_salary_structure("Salary Structure Test for Salary Slip")
|
salary_structure = make_salary_structure(payroll_frequency + " Salary Structure Test for Salary Slip", payroll_frequency, employee)
|
||||||
salary_slip = frappe.db.get_value("Salary Slip", {"employee": frappe.db.get_value("Employee", {"user_id": user})})
|
salary_slip = frappe.db.get_value("Salary Slip", {"employee": frappe.db.get_value("Employee", {"user_id": user})})
|
||||||
|
|
||||||
if not salary_slip:
|
if not salary_slip:
|
||||||
salary_slip = make_salary_slip(salary_structure, employee = employee)
|
salary_slip = make_salary_slip(salary_structure, employee = employee)
|
||||||
salary_slip.employee_name = frappe.get_value("Employee", {"name":frappe.db.get_value("Employee", {"user_id": user})}, "employee_name")
|
salary_slip.employee_name = frappe.get_value("Employee", {"name":frappe.db.get_value("Employee", {"user_id": user})}, "employee_name")
|
||||||
salary_slip.month = "12"
|
salary_slip.payroll_frequency = payroll_frequency
|
||||||
salary_slip.fiscal_year = "_Test Fiscal Year 2016"
|
salary_slip.start_date = nowdate()
|
||||||
salary_slip.posting_date = nowdate()
|
salary_slip.posting_date = nowdate()
|
||||||
salary_slip.insert()
|
salary_slip.insert()
|
||||||
# salary_slip.submit()
|
# salary_slip.submit()
|
||||||
@ -185,38 +211,60 @@ class TestSalarySlip(unittest.TestCase):
|
|||||||
activity_type.wage_rate = 25
|
activity_type.wage_rate = 25
|
||||||
activity_type.save()
|
activity_type.save()
|
||||||
|
|
||||||
def make_salary_component(salary_components):
|
def make_earning_salary_component(salary_components):
|
||||||
for salary_component in salary_components:
|
for salary_component in salary_components:
|
||||||
if not frappe.db.exists('Salary Component', salary_component):
|
if not frappe.db.exists('Salary Component', salary_component):
|
||||||
sal_comp = frappe.get_doc({
|
sal_comp = frappe.get_doc({
|
||||||
"doctype": "Salary Component",
|
"doctype": "Salary Component",
|
||||||
"salary_component": salary_component
|
"salary_component": salary_component,
|
||||||
|
"type": "Earning"
|
||||||
})
|
})
|
||||||
sal_comp.insert()
|
sal_comp.insert()
|
||||||
get_salary_component_account(salary_component)
|
get_salary_component_account(salary_component)
|
||||||
|
|
||||||
def make_salary_structure(sal_struct):
|
def make_deduction_salary_component(salary_components):
|
||||||
|
for salary_component in salary_components:
|
||||||
|
if not frappe.db.exists('Salary Component', salary_component):
|
||||||
|
sal_comp = frappe.get_doc({
|
||||||
|
"doctype": "Salary Component",
|
||||||
|
"salary_component": salary_component,
|
||||||
|
"type": "Deduction"
|
||||||
|
})
|
||||||
|
sal_comp.insert()
|
||||||
|
get_salary_component_account(salary_component)
|
||||||
|
|
||||||
|
def make_salary_structure(sal_struct, payroll_frequency, employee):
|
||||||
if not frappe.db.exists('Salary Structure', sal_struct):
|
if not frappe.db.exists('Salary Structure', sal_struct):
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
"doctype": "Salary Structure",
|
"doctype": "Salary Structure",
|
||||||
"name": sal_struct,
|
"name": sal_struct,
|
||||||
"company": erpnext.get_default_company(),
|
"company": erpnext.get_default_company(),
|
||||||
"from_date": nowdate(),
|
"from_date": nowdate(),
|
||||||
"employees": get_employee_details(),
|
"employees": get_employee_details(employee),
|
||||||
"earnings": get_earnings_component(),
|
"earnings": get_earnings_component(),
|
||||||
"deductions": get_deductions_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": frappe.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name")
|
||||||
}).insert()
|
}).insert()
|
||||||
|
|
||||||
|
elif not frappe.db.get_value("Salary Structure Employee",{'parent':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
|
||||||
|
})
|
||||||
|
sal_struct.save()
|
||||||
|
sal_struct = sal_struct.name
|
||||||
return sal_struct
|
return sal_struct
|
||||||
|
|
||||||
|
def get_employee_details(employee):
|
||||||
def get_employee_details():
|
return [{"employee": employee,
|
||||||
return [{"employee": frappe.get_value("Employee", {"employee_name":"test_employee@salary.com"}, "name"),
|
|
||||||
"base": 25000,
|
"base": 25000,
|
||||||
"variable": 5000
|
"variable": 5000
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_earnings_component():
|
def get_earnings_component():
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,8 @@ cur_frm.cscript.onload = function(doc, dt, dn){
|
|||||||
|
|
||||||
frappe.ui.form.on('Salary Structure', {
|
frappe.ui.form.on('Salary Structure', {
|
||||||
onload: function(frm) {
|
onload: function(frm) {
|
||||||
|
frm.toggle_reqd(['payroll_frequency'], !frm.doc.salary_slip_based_on_timesheet),
|
||||||
|
|
||||||
frm.set_query("salary_component", "earnings", function() {
|
frm.set_query("salary_component", "earnings", function() {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
@ -142,6 +144,7 @@ frappe.ui.form.on('Salary Structure', {
|
|||||||
toggle_fields: function(frm) {
|
toggle_fields: function(frm) {
|
||||||
frm.toggle_display(['salary_component', 'hour_rate'], frm.doc.salary_slip_based_on_timesheet);
|
frm.toggle_display(['salary_component', 'hour_rate'], frm.doc.salary_slip_based_on_timesheet);
|
||||||
frm.toggle_reqd(['salary_component', 'hour_rate'], frm.doc.salary_slip_based_on_timesheet);
|
frm.toggle_reqd(['salary_component', 'hour_rate'], frm.doc.salary_slip_based_on_timesheet);
|
||||||
|
frm.toggle_reqd(['payroll_frequency'], !frm.doc.salary_slip_based_on_timesheet);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -95,6 +95,37 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"default": "",
|
||||||
|
"depends_on": "eval:(!doc.salary_slip_based_on_timesheet)",
|
||||||
|
"fieldname": "payroll_frequency",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Payroll Frequency",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "\nMonthly\nFortnightly\nBimonthly\nWeekly\nDaily",
|
||||||
|
"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,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
@ -863,7 +894,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-11-07 05:13:46.584365",
|
"modified": "2016-12-07 14:57:22.083825",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Salary Structure",
|
"name": "Salary Structure",
|
||||||
|
@ -8,7 +8,7 @@ import erpnext
|
|||||||
from frappe.utils.make_random import get_random
|
from frappe.utils.make_random import get_random
|
||||||
from frappe.utils import nowdate, add_days, add_years
|
from frappe.utils import nowdate, add_days, add_years
|
||||||
from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
|
from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
|
||||||
from erpnext.hr.doctype.salary_slip.test_salary_slip import make_salary_component
|
from erpnext.hr.doctype.salary_slip.test_salary_slip import make_earning_salary_component, make_deduction_salary_component
|
||||||
# test_records = frappe.get_test_records('Salary Structure')
|
# test_records = frappe.get_test_records('Salary Structure')
|
||||||
|
|
||||||
class TestSalaryStructure(unittest.TestCase):
|
class TestSalaryStructure(unittest.TestCase):
|
||||||
@ -24,7 +24,8 @@ class TestSalaryStructure(unittest.TestCase):
|
|||||||
|
|
||||||
self.make_holiday_list()
|
self.make_holiday_list()
|
||||||
frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", "Salary Structure Test Holiday List")
|
frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", "Salary Structure Test Holiday List")
|
||||||
make_salary_component(["Basic Salary", "Allowance", "HRA", "Professional Tax", "TDS"])
|
make_earning_salary_component(["Basic Salary", "Allowance", "HRA"])
|
||||||
|
make_deduction_salary_component(["Professional Tax", "TDS"])
|
||||||
employee1 = self.make_employee("test_employee@salary.com")
|
employee1 = self.make_employee("test_employee@salary.com")
|
||||||
employee2 = self.make_employee("test_employee_2@salary.com")
|
employee2 = self.make_employee("test_employee_2@salary.com")
|
||||||
|
|
||||||
@ -90,6 +91,7 @@ def make_salary_slip_from_salary_structure(employee):
|
|||||||
sal_slip.month = "11"
|
sal_slip.month = "11"
|
||||||
sal_slip.fiscal_year = "_Test Fiscal Year 2016"
|
sal_slip.fiscal_year = "_Test Fiscal Year 2016"
|
||||||
sal_slip.posting_date = nowdate()
|
sal_slip.posting_date = nowdate()
|
||||||
|
sal_slip.payroll_frequency = "Monthly"
|
||||||
sal_slip.insert()
|
sal_slip.insert()
|
||||||
sal_slip.submit()
|
sal_slip.submit()
|
||||||
return sal_slip
|
return sal_slip
|
||||||
@ -104,6 +106,7 @@ def make_salary_structure(sal_struct):
|
|||||||
"employees": get_employee_details(),
|
"employees": get_employee_details(),
|
||||||
"earnings": get_earnings_component(),
|
"earnings": get_earnings_component(),
|
||||||
"deductions": get_deductions_component(),
|
"deductions": get_deductions_component(),
|
||||||
|
"payroll_frequency": "Monthly",
|
||||||
"payment_account": frappe.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name")
|
"payment_account": frappe.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name")
|
||||||
}).insert()
|
}).insert()
|
||||||
return sal_struct
|
return sal_struct
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "Print Format",
|
"doctype": "Print Format",
|
||||||
"font": "Default",
|
"font": "Default",
|
||||||
"format_data": "[{\"fieldname\": \"print_heading_template\", \"fieldtype\": \"HTML\", \"options\": \" <h3 style=\\\"text-align: right;\\\"><span style=\\\"line-height: 1.42857;\\\">{{doc.name}}</span></h3>\\n<div>\\n <hr style=\\\"text-align: center;\\\">\\n</div> \"}, {\"fieldtype\": \"Section Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"employee\"}, {\"print_hide\": 0, \"fieldname\": \"company\"}, {\"print_hide\": 0, \"fieldname\": \"employee_name\"}, {\"print_hide\": 0, \"fieldname\": \"department\"}, {\"print_hide\": 0, \"fieldname\": \"designation\"}, {\"print_hide\": 0, \"fieldname\": \"branch\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"start_date\"}, {\"print_hide\": 0, \"fieldname\": \"end_date\"}, {\"print_hide\": 0, \"fieldname\": \"total_days_in_month\"}, {\"print_hide\": 0, \"fieldname\": \"leave_without_pay\"}, {\"print_hide\": 0, \"fieldname\": \"payment_days\"}, {\"fieldtype\": \"Section Break\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"salary_component\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"depends_on_lwp\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"earnings\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"salary_component\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"depends_on_lwp\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"deductions\"}, {\"fieldtype\": \"Section Break\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"arrear_amount\"}, {\"print_hide\": 0, \"fieldname\": \"leave_encashment_amount\"}, {\"print_hide\": 0, \"fieldname\": \"gross_pay\"}, {\"print_hide\": 0, \"fieldname\": \"total_deduction\"}, {\"print_hide\": 0, \"fieldname\": \"net_pay\"}, {\"print_hide\": 0, \"fieldname\": \"rounded_total\"}, {\"print_hide\": 0, \"fieldname\": \"total_in_words\"}]",
|
"format_data": "[{\"fieldname\": \"print_heading_template\", \"fieldtype\": \"HTML\", \"options\": \" <h3 style=\\\"text-align: right;\\\"><span style=\\\"line-height: 1.42857;\\\">{{doc.name}}</span></h3>\\n<div>\\n <hr style=\\\"text-align: center;\\\">\\n</div> \"}, {\"fieldtype\": \"Section Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"employee\"}, {\"print_hide\": 0, \"fieldname\": \"company\"}, {\"print_hide\": 0, \"fieldname\": \"employee_name\"}, {\"print_hide\": 0, \"fieldname\": \"department\"}, {\"print_hide\": 0, \"fieldname\": \"designation\"}, {\"print_hide\": 0, \"fieldname\": \"branch\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"start_date\"}, {\"print_hide\": 0, \"fieldname\": \"end_date\"}, {\"print_hide\": 0, \"fieldname\": \"total_working_days\"}, {\"print_hide\": 0, \"fieldname\": \"leave_without_pay\"}, {\"print_hide\": 0, \"fieldname\": \"payment_days\"}, {\"fieldtype\": \"Section Break\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"salary_component\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"depends_on_lwp\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"earnings\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"salary_component\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"amount\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"depends_on_lwp\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"deductions\"}, {\"fieldtype\": \"Section Break\"}, {\"fieldtype\": \"Column Break\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"arrear_amount\"}, {\"print_hide\": 0, \"fieldname\": \"leave_encashment_amount\"}, {\"print_hide\": 0, \"fieldname\": \"gross_pay\"}, {\"print_hide\": 0, \"fieldname\": \"total_deduction\"}, {\"print_hide\": 0, \"fieldname\": \"net_pay\"}, {\"print_hide\": 0, \"fieldname\": \"rounded_total\"}, {\"print_hide\": 0, \"fieldname\": \"total_in_words\"}]",
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
"modified": "2016-08-22 00:21:42.600548",
|
"modified": "2016-08-22 00:21:42.600548",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
|
@ -7,7 +7,7 @@ import frappe
|
|||||||
import unittest
|
import unittest
|
||||||
import datetime
|
import datetime
|
||||||
from frappe.utils.make_random import get_random
|
from frappe.utils.make_random import get_random
|
||||||
from frappe.utils import now_datetime, nowdate
|
from frappe.utils import now_datetime, nowdate, add_days
|
||||||
from erpnext.projects.doctype.timesheet.timesheet import OverlapError
|
from erpnext.projects.doctype.timesheet.timesheet import OverlapError
|
||||||
from erpnext.projects.doctype.timesheet.timesheet import make_salary_slip, make_sales_invoice
|
from erpnext.projects.doctype.timesheet.timesheet import make_salary_slip, make_sales_invoice
|
||||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||||
@ -76,7 +76,7 @@ def make_salary_structure(employee):
|
|||||||
salary_structure = frappe.new_doc("Salary Structure")
|
salary_structure = frappe.new_doc("Salary Structure")
|
||||||
salary_structure.name = "Timesheet Salary Structure Test"
|
salary_structure.name = "Timesheet Salary Structure Test"
|
||||||
salary_structure.salary_slip_based_on_timesheet = 1
|
salary_structure.salary_slip_based_on_timesheet = 1
|
||||||
salary_structure.from_date = nowdate()
|
salary_structure.from_date = add_days(nowdate(), -30)
|
||||||
salary_structure.salary_component = "Basic"
|
salary_structure.salary_component = "Basic"
|
||||||
salary_structure.hour_rate = 50.0
|
salary_structure.hour_rate = 50.0
|
||||||
salary_structure.company = "_Test Company"
|
salary_structure.company = "_Test Company"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user