mirror of
https://github.com/frappe/erpnext.git
synced 2026-09-15 01:43:10 +00:00
Merge pull request #5538 from rohitwaghchaure/time_sheet_wages
[Enhancement] Time log wages and multiple active salary structure
This commit is contained in:
@@ -9,7 +9,7 @@ links = {
|
||||
},
|
||||
{
|
||||
'label': _('Payroll'),
|
||||
'items': ['Salary Structure', 'Salary Slip']
|
||||
'items': ['Salary Structure', 'Salary Slip', 'Time Sheet']
|
||||
},
|
||||
{
|
||||
'label': _('Expense'),
|
||||
|
||||
@@ -166,7 +166,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"default": "1",
|
||||
"description": "Check if you want to send salary slip in mail to each employee while submitting salary slip",
|
||||
"description": "",
|
||||
"fieldname": "email_salary_slip_to_employee",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
@@ -200,7 +200,7 @@
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-06-25 17:43:06.643469",
|
||||
"modified": "2016-06-27 16:20:59.737869",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "HR Settings",
|
||||
@@ -220,8 +220,6 @@
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 0,
|
||||
"restrict": 0,
|
||||
"restricted": 0,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
|
||||
@@ -58,7 +58,8 @@ cur_frm.cscript.make_jv = function(doc, dt, dn) {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
frappe.ui.form.on("Process Payroll", "refresh", function(frm) {
|
||||
frm.disable_save();
|
||||
});
|
||||
frappe.ui.form.on("Process Payroll", {
|
||||
refresh: function(frm) {
|
||||
frm.disable_save();
|
||||
}
|
||||
})
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"allow_copy": 1,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2012-03-27 14:35:59",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
@@ -180,6 +181,55 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "section_break_8",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "salary_slip_based_on_timesheet",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Salary Slip Based on Timesheet",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -503,13 +553,14 @@
|
||||
"hide_toolbar": 1,
|
||||
"icon": "icon-cog",
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-04-26 07:22:41.792785",
|
||||
"modified": "2016-06-22 18:14:02.418857",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Process Payroll",
|
||||
@@ -536,8 +587,10 @@
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
"sort_order": "DESC",
|
||||
"track_seen": 0
|
||||
}
|
||||
@@ -15,20 +15,18 @@ class ProcessPayroll(Document):
|
||||
Returns list of active employees based on selected criteria
|
||||
and for which salary structure exists
|
||||
"""
|
||||
|
||||
cond = self.get_filter_condition()
|
||||
cond += self.get_joining_releiving_condition()
|
||||
|
||||
emp_list = frappe.db.sql("""
|
||||
select t1.name
|
||||
from `tabEmployee` t1, `tabSalary Structure` t2
|
||||
where t1.docstatus!=2 and t2.docstatus != 2
|
||||
and t1.name = t2.employee
|
||||
where t1.docstatus!=2 and t2.docstatus != 2 and
|
||||
ifnull(t2.salary_slip_based_on_timesheet,0) = 0 and t1.name = t2.employee
|
||||
%s """% cond)
|
||||
|
||||
return emp_list
|
||||
|
||||
|
||||
def get_filter_condition(self):
|
||||
self.check_mandatory()
|
||||
|
||||
@@ -67,6 +65,7 @@ class ProcessPayroll(Document):
|
||||
""", (emp[0], self.month, self.fiscal_year, self.company)):
|
||||
ss = frappe.get_doc({
|
||||
"doctype": "Salary Slip",
|
||||
"salary_slip_based_on_timesheet": 0,
|
||||
"fiscal_year": self.fiscal_year,
|
||||
"employee": emp[0],
|
||||
"month": self.month,
|
||||
|
||||
@@ -2,13 +2,51 @@
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
cur_frm.add_fetch('employee', 'company', 'company');
|
||||
cur_frm.add_fetch('time_sheet', 'total_hours', 'working_hours');
|
||||
|
||||
frappe.ui.form.on("Salary Slip", {
|
||||
setup: function(frm) {
|
||||
frm.fields_dict["timesheets"].grid.get_field("time_sheet").get_query = function(){
|
||||
return {
|
||||
filters: {
|
||||
employee: frm.doc.employee,
|
||||
make_for: 'Salary Slip'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
company: function(frm) {
|
||||
var company = locals[':Company'][frm.doc.company];
|
||||
if(!frm.doc.letter_head && company.default_letter_head) {
|
||||
frm.set_value('letter_head', company.default_letter_head);
|
||||
}
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
frm.trigger("toggle_fields")
|
||||
},
|
||||
|
||||
salary_slip_based_on_timesheet: function(frm) {
|
||||
frm.trigger("toggle_fields")
|
||||
},
|
||||
|
||||
toggle_fields: function(frm) {
|
||||
if(frm.doc.salary_slip_based_on_timesheet) {
|
||||
hide_field(['fiscal_year', 'month', 'total_days_in_month', 'leave_without_pay', 'payment_days'])
|
||||
unhide_field(['start_date', 'end_date', 'hourly_wages', 'timesheets'])
|
||||
}else {
|
||||
unhide_field(['fiscal_year', 'month', 'total_days_in_month', 'leave_without_pay', 'payment_days'])
|
||||
hide_field(['start_date', 'end_date', 'hourly_wages', 'timesheets'])
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
frappe.ui.form.on("Salary Slip Timesheet", {
|
||||
time_sheet: function(frm, cdt, cdn) {
|
||||
doc = frm.doc;
|
||||
cur_frm.cscript.fiscal_year(doc, cdt, cdn)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -38,7 +76,13 @@ cur_frm.cscript.fiscal_year = function(doc,dt,dn){
|
||||
});
|
||||
}
|
||||
|
||||
cur_frm.cscript.month = cur_frm.cscript.employee = cur_frm.cscript.fiscal_year;
|
||||
cur_frm.cscript.month = cur_frm.cscript.salary_slip_based_on_timesheet = cur_frm.cscript.fiscal_year;
|
||||
cur_frm.cscript.start_date = cur_frm.cscript.end_date = cur_frm.cscript.fiscal_year;
|
||||
|
||||
cur_frm.cscript.employee = function(doc,dt,dn){
|
||||
doc.salary_structure = ''
|
||||
cur_frm.cscript.fiscal_year(doc, dt, dn)
|
||||
}
|
||||
|
||||
cur_frm.cscript.leave_without_pay = function(doc,dt,dn){
|
||||
if (doc.employee && doc.fiscal_year && doc.month) {
|
||||
@@ -56,7 +100,7 @@ var calculate_all = function(doc, dt, dn) {
|
||||
calculate_net_pay(doc, dt, dn);
|
||||
}
|
||||
|
||||
cur_frm.cscript.e_modified_amount = function(doc,dt,dn){
|
||||
cur_frm.cscript.earning_amount = function(doc,dt,dn){
|
||||
calculate_earning_total(doc, dt, dn);
|
||||
calculate_net_pay(doc, dt, dn);
|
||||
}
|
||||
@@ -67,7 +111,7 @@ cur_frm.cscript.e_depends_on_lwp = function(doc,dt,dn){
|
||||
}
|
||||
// Trigger on earning modified amount and depends on lwp
|
||||
// ------------------------------------------------------------------------
|
||||
cur_frm.cscript.d_modified_amount = function(doc,dt,dn){
|
||||
cur_frm.cscript.deduction_amount = function(doc,dt,dn){
|
||||
calculate_ded_total(doc, dt, dn);
|
||||
calculate_net_pay(doc, dt, dn);
|
||||
}
|
||||
@@ -85,17 +129,17 @@ var calculate_earning_total = function(doc, dt, dn, reset_amount) {
|
||||
var total_earn = 0;
|
||||
for(var i = 0; i < tbl.length; i++){
|
||||
if(cint(tbl[i].e_depends_on_lwp) == 1) {
|
||||
tbl[i].e_modified_amount = Math.round(tbl[i].e_amount)*(flt(doc.payment_days) /
|
||||
tbl[i].earning_amount = Math.round(tbl[i].e_amount)*(flt(doc.payment_days) /
|
||||
cint(doc.total_days_in_month)*100)/100;
|
||||
refresh_field('e_modified_amount', tbl[i].name, 'earnings');
|
||||
refresh_field('earning_amount', tbl[i].name, 'earnings');
|
||||
} else if(reset_amount) {
|
||||
tbl[i].e_modified_amount = tbl[i].e_amount;
|
||||
refresh_field('e_modified_amount', tbl[i].name, 'earnings');
|
||||
tbl[i].earning_amount = tbl[i].e_amount;
|
||||
refresh_field('earning_amount', tbl[i].name, 'earnings');
|
||||
}
|
||||
total_earn += flt(tbl[i].e_modified_amount);
|
||||
total_earn += flt(tbl[i].earning_amount);
|
||||
}
|
||||
doc.gross_pay = total_earn + flt(doc.arrear_amount) + flt(doc.leave_encashment_amount);
|
||||
refresh_many(['e_modified_amount', 'gross_pay']);
|
||||
refresh_many(['earning_amount', 'gross_pay']);
|
||||
}
|
||||
|
||||
// Calculate deduction total
|
||||
@@ -106,13 +150,13 @@ var calculate_ded_total = function(doc, dt, dn, reset_amount) {
|
||||
var total_ded = 0;
|
||||
for(var i = 0; i < tbl.length; i++){
|
||||
if(cint(tbl[i].d_depends_on_lwp) == 1) {
|
||||
tbl[i].d_modified_amount = Math.round(tbl[i].d_amount)*(flt(doc.payment_days)/cint(doc.total_days_in_month)*100)/100;
|
||||
refresh_field('d_modified_amount', tbl[i].name, 'deductions');
|
||||
tbl[i].deduction_amount = Math.round(tbl[i].d_amount)*(flt(doc.payment_days)/cint(doc.total_days_in_month)*100)/100;
|
||||
refresh_field('deduction_amount', tbl[i].name, 'deductions');
|
||||
} else if(reset_amount) {
|
||||
tbl[i].d_modified_amount = tbl[i].d_amount;
|
||||
refresh_field('d_modified_amount', tbl[i].name, 'earnings');
|
||||
tbl[i].deduction_amount = tbl[i].d_amount;
|
||||
refresh_field('deduction_amount', tbl[i].name, 'earnings');
|
||||
}
|
||||
total_ded += flt(tbl[i].d_modified_amount);
|
||||
total_ded += flt(tbl[i].deduction_amount);
|
||||
}
|
||||
doc.total_deduction = total_ded;
|
||||
refresh_field('total_deduction');
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2013-01-10 16:34:15",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
@@ -65,7 +66,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "employee_name",
|
||||
"fieldtype": "Data",
|
||||
"fieldtype": "Read Only",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@@ -76,10 +77,11 @@
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "employee_name",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "employee.employee_name",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
@@ -167,6 +169,31 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0,
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -221,8 +248,8 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"fieldname": "section_break_10",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@@ -230,8 +257,8 @@
|
||||
"in_list_view": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
@@ -239,41 +266,40 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0,
|
||||
"width": "50%"
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "month",
|
||||
"fieldtype": "Select",
|
||||
"depends_on": "",
|
||||
"fieldname": "salary_slip_based_on_timesheet",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Month",
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Salary Slip Based on Timesheet",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "month",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\n01\n02\n03\n04\n05\n06\n07\n08\n09\n10\n11\n12",
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0,
|
||||
"width": "37%"
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "fiscal_year",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -301,6 +327,139 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "month",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 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,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"unique": 0,
|
||||
"width": "37%"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "start_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Start Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"default": "Today",
|
||||
"depends_on": "",
|
||||
"fieldname": "end_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "End Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_15",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "salary_structure",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Salary Structure",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Salary Structure",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "total_days_in_month",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -327,6 +486,7 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "leave_without_pay",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -353,6 +513,7 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "payment_days",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -375,6 +536,159 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "hourly_wages",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "timesheets",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Salary Slip Timesheet",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Salary Slip Timesheet",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_20",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "total_working_hours",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Total Working Hours",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "hour_rate",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Hour Rate",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "2",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "section_break_26",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -427,6 +741,30 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_01",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -610,52 +948,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_25",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_26",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -737,6 +1029,29 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_25",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -849,13 +1164,14 @@
|
||||
"hide_toolbar": 0,
|
||||
"icon": "icon-file-text",
|
||||
"idx": 9,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-04-26 06:02:06.940543",
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-06-27 16:22:46.063078",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Salary Slip",
|
||||
@@ -923,6 +1239,7 @@
|
||||
"write": 0
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
|
||||
@@ -20,14 +20,16 @@ class SalarySlip(TransactionBase):
|
||||
self.name = make_autoname('Sal Slip/' +self.employee + '/.#####')
|
||||
|
||||
def validate(self):
|
||||
self.validate_dates()
|
||||
self.check_existing()
|
||||
self.set_month_dates()
|
||||
|
||||
if not (len(self.get("earnings")) or len(self.get("deductions"))):
|
||||
self.get_emp_and_leave_details()
|
||||
else:
|
||||
self.get_leave_details(lwp = self.leave_without_pay)
|
||||
|
||||
if not self.net_pay:
|
||||
if self.salary_slip_based_on_timesheet or not self.net_pay:
|
||||
self.calculate_net_pay()
|
||||
|
||||
company_currency = get_company_currency(self.company)
|
||||
@@ -35,38 +37,85 @@ class SalarySlip(TransactionBase):
|
||||
|
||||
set_employee_name(self)
|
||||
|
||||
def validate_dates(self):
|
||||
if date_diff(self.end_date, self.start_date) < 0:
|
||||
frappe.throw(_("To date cannot be before From date"))
|
||||
|
||||
def get_emp_and_leave_details(self):
|
||||
if self.employee:
|
||||
self.set("earnings", [])
|
||||
self.set("deductions", [])
|
||||
|
||||
self.set_month_dates()
|
||||
self.validate_dates()
|
||||
joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
|
||||
["date_of_joining", "relieving_date"])
|
||||
|
||||
self.get_leave_details(joining_date, relieving_date)
|
||||
|
||||
struct = self.check_sal_struct(joining_date, relieving_date)
|
||||
|
||||
if struct:
|
||||
self.set("earnings", [])
|
||||
self.set("deduction", [])
|
||||
self.pull_sal_struct(struct)
|
||||
ss_doc = frappe.get_doc('Salary Structure', struct)
|
||||
self.salary_slip_based_on_timesheet = ss_doc.salary_slip_based_on_timesheet or 0
|
||||
self.set_time_sheet()
|
||||
self.pull_sal_struct(ss_doc)
|
||||
|
||||
def set_time_sheet(self):
|
||||
if self.salary_slip_based_on_timesheet and not self.get('timesheets'):
|
||||
self.set("timesheets", [])
|
||||
|
||||
timesheets = frappe.db.sql(""" select * from `tabTime Sheet` where employee = %(employee)s and (status = 'Submitted' or
|
||||
status = 'Billed')""", {'employee': self.employee}, as_dict=1)
|
||||
|
||||
for data in timesheets:
|
||||
self.append('timesheets', {
|
||||
'time_sheet': data.name,
|
||||
'working_hours': data.total_hours
|
||||
})
|
||||
|
||||
def set_month_dates(self):
|
||||
if self.month and not self.salary_slip_based_on_timesheet:
|
||||
m = get_month_details(self.fiscal_year, self.month)
|
||||
self.start_date = m['month_start_date']
|
||||
self.end_date = m['month_end_date']
|
||||
|
||||
def check_sal_struct(self, joining_date, relieving_date):
|
||||
m = get_month_details(self.fiscal_year, self.month)
|
||||
|
||||
timesheet = 1 if self.salary_slip_based_on_timesheet else 0
|
||||
struct = frappe.db.sql("""select name from `tabSalary Structure`
|
||||
where employee=%s and is_active = 'Yes'
|
||||
and (from_date <= %s or from_date <= %s)
|
||||
and (to_date is null or to_date >= %s or to_date >= %s)""",
|
||||
(self.employee, m.month_start_date, joining_date, m.month_end_date, relieving_date))
|
||||
and (to_date is null or to_date >= %s or to_date >= %s) and salary_slip_based_on_timesheet=%s""",
|
||||
(self.employee, self.start_date, joining_date, self.end_date, relieving_date, timesheet))
|
||||
|
||||
if not struct:
|
||||
msgprint(_("No active Salary Structure found for employee {0} and the month")
|
||||
self.salary_structure = None
|
||||
msgprint(_("No active or default Salary Structure found for employee {0} and the month")
|
||||
.format(self.employee))
|
||||
self.employee = None
|
||||
|
||||
return struct and struct[0][0] or ''
|
||||
|
||||
def pull_sal_struct(self, struct):
|
||||
def pull_sal_struct(self, ss_doc):
|
||||
from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
|
||||
make_salary_slip(struct, self)
|
||||
make_salary_slip(ss_doc.name, self)
|
||||
|
||||
if self.salary_slip_based_on_timesheet:
|
||||
self.salary_structure = ss_doc.name
|
||||
self.hour_rate = ss_doc.hour_rate
|
||||
self.total_working_hours = sum([d.working_hours or 0.0 for d in self.timesheets]) or 0.0
|
||||
self.add_earning_for_hourly_wages(ss_doc.earning_type)
|
||||
|
||||
def add_earning_for_hourly_wages(self, earning_type):
|
||||
default_type = False
|
||||
for data in self.earnings:
|
||||
if data.earning_type == earning_type:
|
||||
data.earning_amount = self.hour_rate * self.total_working_hours
|
||||
default_type = True
|
||||
break
|
||||
|
||||
if not default_type:
|
||||
earnings = self.append('earnings', {})
|
||||
earnings.earning_type = earning_type
|
||||
earnings.earning_amount = self.hour_rate * self.total_working_hours
|
||||
|
||||
def pull_emp_details(self):
|
||||
emp = frappe.db.get_value("Employee", self.employee, ["bank_name", "bank_ac_no"], as_dict=1)
|
||||
@@ -81,40 +130,41 @@ class SalarySlip(TransactionBase):
|
||||
|
||||
if not self.month:
|
||||
self.month = "%02d" % getdate(nowdate()).month
|
||||
self.set_month_dates()
|
||||
|
||||
if not joining_date:
|
||||
joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
|
||||
["date_of_joining", "relieving_date"])
|
||||
|
||||
m = get_month_details(self.fiscal_year, self.month)
|
||||
holidays = self.get_holidays_for_employee(m['month_start_date'], m['month_end_date'])
|
||||
holidays = self.get_holidays_for_employee(self.start_date, self.end_date)
|
||||
|
||||
working_days = m["month_days"]
|
||||
working_days = date_diff(self.end_date, self.start_date) + 1
|
||||
if not cint(frappe.db.get_value("HR Settings", None, "include_holidays_in_total_working_days")):
|
||||
working_days -= len(holidays)
|
||||
if working_days < 0:
|
||||
frappe.throw(_("There are more holidays than working days this month."))
|
||||
|
||||
if not lwp:
|
||||
lwp = self.calculate_lwp(holidays, m)
|
||||
lwp = self.calculate_lwp(holidays, working_days)
|
||||
self.total_days_in_month = working_days
|
||||
self.leave_without_pay = lwp
|
||||
payment_days = flt(self.get_payment_days(m, joining_date, relieving_date)) - flt(lwp)
|
||||
payment_days = flt(self.get_payment_days(joining_date, relieving_date)) - flt(lwp)
|
||||
self.payment_days = payment_days > 0 and payment_days or 0
|
||||
|
||||
def get_payment_days(self, month, joining_date, relieving_date):
|
||||
start_date = month['month_start_date']
|
||||
def get_payment_days(self, joining_date, relieving_date):
|
||||
start_date = getdate(self.start_date)
|
||||
|
||||
if joining_date:
|
||||
if joining_date > month['month_start_date']:
|
||||
if joining_date > getdate(self.start_date):
|
||||
start_date = joining_date
|
||||
elif joining_date > month['month_end_date']:
|
||||
elif joining_date > getdate(self.end_date):
|
||||
return
|
||||
|
||||
end_date = month['month_end_date']
|
||||
end_date = getdate(self.end_date)
|
||||
if relieving_date:
|
||||
if relieving_date > start_date and relieving_date < month['month_end_date']:
|
||||
if relieving_date > start_date and relieving_date < getdate(self.end_date):
|
||||
end_date = relieving_date
|
||||
elif relieving_date < month['month_start_date']:
|
||||
elif relieving_date < getdate(self.start_date):
|
||||
frappe.throw(_("Employee relieved on {0} must be set as 'Left'")
|
||||
.format(relieving_date))
|
||||
|
||||
@@ -142,10 +192,10 @@ class SalarySlip(TransactionBase):
|
||||
|
||||
return holidays
|
||||
|
||||
def calculate_lwp(self, holidays, m):
|
||||
def calculate_lwp(self, holidays, working_days):
|
||||
lwp = 0
|
||||
for d in range(m['month_days']):
|
||||
dt = add_days(cstr(m['month_start_date']), d)
|
||||
for d in range(working_days):
|
||||
dt = add_days(cstr(self.start_date), d)
|
||||
if dt not in holidays:
|
||||
leave = frappe.db.sql("""
|
||||
select t1.name, t1.half_day
|
||||
@@ -161,38 +211,43 @@ class SalarySlip(TransactionBase):
|
||||
return lwp
|
||||
|
||||
def check_existing(self):
|
||||
ret_exist = frappe.db.sql("""select name from `tabSalary Slip`
|
||||
where month = %s and fiscal_year = %s and docstatus != 2
|
||||
and employee = %s and name != %s""",
|
||||
(self.month, self.fiscal_year, self.employee, self.name))
|
||||
if ret_exist:
|
||||
self.employee = ''
|
||||
frappe.throw(_("Salary Slip of employee {0} already created for this month").format(self.employee))
|
||||
if not self.salary_slip_based_on_timesheet:
|
||||
ret_exist = frappe.db.sql("""select name from `tabSalary Slip`
|
||||
where month = %s and fiscal_year = %s and docstatus != 2
|
||||
and employee = %s and name != %s""",
|
||||
(self.month, self.fiscal_year, self.employee, self.name))
|
||||
if ret_exist:
|
||||
self.employee = ''
|
||||
frappe.throw(_("Salary Slip of employee {0} already created for this period").format(self.employee))
|
||||
else:
|
||||
for data in self.timesheets:
|
||||
if frappe.db.get_value('Time Sheet', data.time_sheet, 'status') == 'Payrolled':
|
||||
frappe.throw(_("Salary Slip of employee {0} already created for time sheet {1}").format(self.employee, data.time_sheet))
|
||||
|
||||
def calculate_earning_total(self):
|
||||
self.gross_pay = flt(self.arrear_amount) + flt(self.leave_encashment_amount)
|
||||
for d in self.get("earnings"):
|
||||
if cint(d.e_depends_on_lwp) == 1:
|
||||
d.e_modified_amount = rounded((flt(d.e_amount) * flt(self.payment_days)
|
||||
/ cint(self.total_days_in_month)), self.precision("e_modified_amount", "earnings"))
|
||||
d.earning_amount = rounded((flt(d.e_amount) * flt(self.payment_days)
|
||||
/ cint(self.total_days_in_month)), self.precision("earning_amount", "earnings"))
|
||||
elif not self.payment_days:
|
||||
d.e_modified_amount = 0
|
||||
elif not d.e_modified_amount:
|
||||
d.e_modified_amount = d.e_amount
|
||||
self.gross_pay += flt(d.e_modified_amount)
|
||||
d.earning_amount = 0
|
||||
elif not d.earning_amount:
|
||||
d.earning_amount = d.e_amount
|
||||
self.gross_pay += flt(d.earning_amount)
|
||||
|
||||
def calculate_ded_total(self):
|
||||
self.total_deduction = 0
|
||||
for d in self.get('deductions'):
|
||||
if cint(d.d_depends_on_lwp) == 1:
|
||||
d.d_modified_amount = rounded((flt(d.d_amount) * flt(self.payment_days)
|
||||
/ cint(self.total_days_in_month)), self.precision("d_modified_amount", "deductions"))
|
||||
d.deduction_amount = rounded((flt(d.d_amount) * flt(self.payment_days)
|
||||
/ cint(self.total_days_in_month)), self.precision("deduction_amount", "deductions"))
|
||||
elif not self.payment_days:
|
||||
d.d_modified_amount = 0
|
||||
elif not d.d_modified_amount:
|
||||
d.d_modified_amount = d.d_amount
|
||||
d.deduction_amount = 0
|
||||
elif not d.deduction_amount:
|
||||
d.deduction_amount = d.d_amount
|
||||
|
||||
self.total_deduction += flt(d.d_modified_amount)
|
||||
self.total_deduction += flt(d.deduction_amount)
|
||||
|
||||
def calculate_net_pay(self):
|
||||
disable_rounded_total = cint(frappe.db.get_value("Global Defaults", None, "disable_rounded_total"))
|
||||
@@ -204,16 +259,28 @@ class SalarySlip(TransactionBase):
|
||||
self.precision("net_pay") if disable_rounded_total else 0)
|
||||
|
||||
def on_submit(self):
|
||||
self.update_status(self.name)
|
||||
if(frappe.db.get_single_value("HR Settings", "email_salary_slip_to_employee")):
|
||||
self.email_salary_slip()
|
||||
|
||||
|
||||
def on_cancel(self):
|
||||
self.update_status()
|
||||
|
||||
def email_salary_slip(self):
|
||||
receiver = frappe.db.get_value("Employee", self.employee, "company_email") or \
|
||||
frappe.db.get_value("Employee", self.employee, "personal_email")
|
||||
if receiver:
|
||||
subj = 'Salary Slip - ' + cstr(self.month) +'/'+cstr(self.fiscal_year)
|
||||
subj = 'Salary Slip - from {0} to {1}, fiscal year {2}'.format(self.start_date, self.end_date, self.fiscal_year)
|
||||
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)
|
||||
else:
|
||||
msgprint(_("{0}: Employee email not found, hence email not sent").format(self.employee_name))
|
||||
|
||||
def update_status(self, salary_slip=None):
|
||||
for data in self.timesheets:
|
||||
if data.time_sheet:
|
||||
timesheet = frappe.get_doc('Time Sheet', data.time_sheet)
|
||||
timesheet.salary_slip = salary_slip
|
||||
timesheet.flags.ignore_validate_update_after_submit = True
|
||||
timesheet.set_status()
|
||||
timesheet.save()
|
||||
@@ -5,14 +5,14 @@
|
||||
{
|
||||
"d_amount": 100,
|
||||
"d_depends_on_lwp": 0,
|
||||
"d_type": "_Test Professional Tax",
|
||||
"deduction_type": "_Test Professional Tax",
|
||||
"doctype": "Salary Slip Deduction",
|
||||
"parentfield": "deductions"
|
||||
},
|
||||
{
|
||||
"d_amount": 50,
|
||||
"d_depends_on_lwp": 1,
|
||||
"d_type": "_Test TDS",
|
||||
"deduction_type": "_Test TDS",
|
||||
"doctype": "Salary Slip Deduction",
|
||||
"parentfield": "deductions"
|
||||
}
|
||||
@@ -23,14 +23,14 @@
|
||||
"doctype": "Salary Slip Earning",
|
||||
"e_amount": 15000,
|
||||
"e_depends_on_lwp": 1,
|
||||
"e_type": "_Test Basic Salary",
|
||||
"earning_type": "_Test Basic Salary",
|
||||
"parentfield": "earnings"
|
||||
},
|
||||
{
|
||||
"doctype": "Salary Slip Earning",
|
||||
"e_amount": 500,
|
||||
"e_depends_on_lwp": 0,
|
||||
"e_type": "_Test Allowance",
|
||||
"earning_type": "_Test Allowance",
|
||||
"parentfield": "earnings"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@ from __future__ import unicode_literals
|
||||
|
||||
import unittest
|
||||
import frappe
|
||||
from frappe.utils import today
|
||||
from frappe.utils import today, now_datetime, getdate, cstr
|
||||
from erpnext.hr.doctype.employee.employee import make_salary_structure
|
||||
from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
|
||||
from erpnext.hr.doctype.leave_application.test_leave_application import make_allocation_record
|
||||
@@ -35,10 +35,10 @@ class TestSalarySlip(unittest.TestCase):
|
||||
|
||||
self.assertEquals(ss.total_days_in_month, 31)
|
||||
self.assertEquals(ss.payment_days, 30)
|
||||
self.assertEquals(ss.earnings[0].e_modified_amount, 14516.13)
|
||||
self.assertEquals(ss.earnings[1].e_modified_amount, 500)
|
||||
self.assertEquals(ss.deductions[0].d_modified_amount, 100)
|
||||
self.assertEquals(ss.deductions[1].d_modified_amount, 48.39)
|
||||
self.assertEquals(ss.earnings[0].earning_amount, 14516.13)
|
||||
self.assertEquals(ss.earnings[1].earning_amount, 500)
|
||||
self.assertEquals(ss.deductions[0].deduction_amount, 100)
|
||||
self.assertEquals(ss.deductions[1].deduction_amount, 48.39)
|
||||
self.assertEquals(ss.gross_pay, 15016.13)
|
||||
self.assertEquals(ss.net_pay, 14867.74)
|
||||
|
||||
@@ -49,10 +49,10 @@ class TestSalarySlip(unittest.TestCase):
|
||||
|
||||
self.assertEquals(ss.total_days_in_month, 29)
|
||||
self.assertEquals(ss.payment_days, 28)
|
||||
self.assertEquals(ss.earnings[0].e_modified_amount, 14482.76)
|
||||
self.assertEquals(ss.earnings[1].e_modified_amount, 500)
|
||||
self.assertEquals(ss.deductions[0].d_modified_amount, 100)
|
||||
self.assertEquals(ss.deductions[1].d_modified_amount, 48.28)
|
||||
self.assertEquals(ss.earnings[0].earning_amount, 14482.76)
|
||||
self.assertEquals(ss.earnings[1].earning_amount, 500)
|
||||
self.assertEquals(ss.deductions[0].deduction_amount, 100)
|
||||
self.assertEquals(ss.deductions[1].deduction_amount, 48.28)
|
||||
self.assertEquals(ss.gross_pay, 14982.76)
|
||||
self.assertEquals(ss.net_pay, 14834.48)
|
||||
|
||||
@@ -153,6 +153,13 @@ class TestSalarySlip(unittest.TestCase):
|
||||
|
||||
return salary_slip
|
||||
|
||||
def make_activity_for_employee(self):
|
||||
activity_type = frappe.get_doc("Activity Type", "_Test Activity Type")
|
||||
activity_type.billing_rate = 50
|
||||
activity_type.costing_rate = 20
|
||||
activity_type.wage_rate = 25
|
||||
activity_type.save()
|
||||
|
||||
test_dependencies = ["Leave Application", "Holiday List"]
|
||||
|
||||
test_records = frappe.get_test_records('Salary Slip')
|
||||
|
||||
@@ -2,19 +2,22 @@
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2013-02-22 01:27:48",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "d_type",
|
||||
"fieldname": "deduction_type",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Type",
|
||||
@@ -25,6 +28,7 @@
|
||||
"options": "Deduction Type",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "200px",
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -42,6 +46,7 @@
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Default Amount",
|
||||
@@ -52,6 +57,7 @@
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@@ -67,6 +73,7 @@
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Depends on Leave Without Pay",
|
||||
@@ -74,6 +81,7 @@
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@@ -85,10 +93,11 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "d_modified_amount",
|
||||
"fieldname": "deduction_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Amount",
|
||||
@@ -97,6 +106,7 @@
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@@ -108,18 +118,22 @@
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2015-11-16 06:29:55.610195",
|
||||
"modified": "2016-06-27 16:02:25.613138",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Salary Slip Deduction",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0
|
||||
"read_only_onload": 0,
|
||||
"sort_order": "ASC",
|
||||
"track_seen": 0
|
||||
}
|
||||
@@ -2,19 +2,22 @@
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2013-02-22 01:27:48",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "e_type",
|
||||
"fieldname": "earning_type",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Type",
|
||||
@@ -25,6 +28,7 @@
|
||||
"options": "Earning Type",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "",
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -42,6 +46,7 @@
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Default Amount",
|
||||
@@ -52,6 +57,7 @@
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@@ -67,6 +73,7 @@
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Depends on Leave Without Pay",
|
||||
@@ -74,6 +81,7 @@
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@@ -85,10 +93,11 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "e_modified_amount",
|
||||
"fieldname": "earning_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Amount",
|
||||
@@ -97,6 +106,7 @@
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@@ -108,18 +118,22 @@
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2015-11-16 06:29:55.649418",
|
||||
"modified": "2016-06-27 15:56:04.146109",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Salary Slip Earning",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0
|
||||
"read_only_onload": 0,
|
||||
"sort_order": "ASC",
|
||||
"track_seen": 0
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2016-06-14 19:22:29.811658",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "time_sheet",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Time Sheet",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Time Sheet",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "working_hours",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Working Hours",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "3",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-06-15 17:59:57.876373",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Salary Slip Timesheet",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_seen": 0
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class SalarySlipTimesheet(Document):
|
||||
pass
|
||||
@@ -12,7 +12,7 @@ cur_frm.cscript.onload = function(doc, dt, dn){
|
||||
}
|
||||
|
||||
cur_frm.cscript.refresh = function(doc, dt, dn){
|
||||
if((!doc.__islocal) && (doc.is_active == 'Yes')){
|
||||
if((!doc.__islocal) && (doc.is_active == 'Yes') && (doc.salary_slip_based_on_timesheet == 0)){
|
||||
cur_frm.add_custom_button(__('Salary Slip'),
|
||||
cur_frm.cscript['Make Salary Slip'], __("Make"));
|
||||
cur_frm.page.set_inner_btn_group_as_primary(__("Make"));
|
||||
@@ -52,7 +52,11 @@ var calculate_totals = function(doc, cdt, cdn) {
|
||||
}
|
||||
doc.total_earning = total_earn;
|
||||
doc.total_deduction = total_ded;
|
||||
doc.net_pay = flt(total_earn) - flt(total_ded);
|
||||
doc.net_pay = 0.0
|
||||
if(doc.salary_slip_based_on_timesheet == 0){
|
||||
doc.net_pay = flt(total_earn) - flt(total_ded);
|
||||
}
|
||||
|
||||
refresh_many(['total_earning', 'total_deduction', 'net_pay']);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"allow_copy": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2013-03-07 18:50:29",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
@@ -269,6 +270,33 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"default": "No",
|
||||
"fieldname": "is_default",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Is Default",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Yes\nNo",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -325,6 +353,136 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "eval:!doc.__islocal",
|
||||
"fieldname": "salary_slip_based_on_timesheet",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Salary Slip Based on Timesheet",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "eval:doc.salary_slip_based_on_timesheet",
|
||||
"fieldname": "section_break_15",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "",
|
||||
"description": "Earning type for timesheet based payroll.",
|
||||
"fieldname": "earning_type",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Earning Type",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Earning Type",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_17",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "hour_rate",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Hour Rate",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "2",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "",
|
||||
"description": "Salary breakup based on Earning and Deduction.",
|
||||
"fieldname": "earning_deduction",
|
||||
"fieldtype": "Section Break",
|
||||
@@ -333,7 +491,7 @@
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Monthly Earning & Deduction",
|
||||
"label": "",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "earning_deduction",
|
||||
@@ -379,6 +537,7 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "earnings",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
@@ -397,7 +556,7 @@
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
@@ -460,7 +619,8 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "section_break0",
|
||||
"depends_on": "",
|
||||
"fieldname": "net_pay_detail",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
@@ -612,13 +772,14 @@
|
||||
"hide_toolbar": 0,
|
||||
"icon": "icon-file-text",
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-03-18 16:10:30.031811",
|
||||
"modified": "2016-06-27 16:23:16.856237",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Salary Structure",
|
||||
@@ -649,7 +810,7 @@
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
@@ -665,10 +826,12 @@
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"timeline_field": "employee",
|
||||
"title_field": "employee_name"
|
||||
"title_field": "employee_name",
|
||||
"track_seen": 0
|
||||
}
|
||||
@@ -16,7 +16,7 @@ class SalaryStructure(Document):
|
||||
self.name = make_autoname(self.employee + '/.SST' + '/.#####')
|
||||
|
||||
def validate(self):
|
||||
self.check_existing()
|
||||
self.check_overlap()
|
||||
self.validate_amount()
|
||||
self.validate_employee()
|
||||
self.validate_joining_date()
|
||||
@@ -48,43 +48,44 @@ class SalaryStructure(Document):
|
||||
for li in list1:
|
||||
child = self.append(tab_fname, {})
|
||||
if(tab_fname == 'earnings'):
|
||||
child.e_type = cstr(li[0])
|
||||
child.earning_type = cstr(li[0])
|
||||
child.modified_value = 0
|
||||
elif(tab_fname == 'deductions'):
|
||||
child.d_type = cstr(li[0])
|
||||
child.deduction_type = cstr(li[0])
|
||||
child.d_modified_amt = 0
|
||||
|
||||
def make_earn_ded_table(self):
|
||||
self.make_table('Earning Type','earnings','Salary Structure Earning')
|
||||
self.make_table('Deduction Type','deductions', 'Salary Structure Deduction')
|
||||
|
||||
def check_existing(self):
|
||||
ret = self.get_other_active_salary_structure()
|
||||
|
||||
if ret and self.is_active=='Yes':
|
||||
frappe.throw(_("Another Salary Structure {0} is active for employee {1}. Please make its status 'Inactive' to proceed.").format(ret, self.employee))
|
||||
|
||||
def get_other_active_salary_structure(self):
|
||||
ret = frappe.db.sql("""select name from `tabSalary Structure` where is_active = 'Yes'
|
||||
and employee = %s and name!=%s""", (self.employee,self.name))
|
||||
|
||||
return ret[0][0] if ret else None
|
||||
|
||||
def before_test_insert(self):
|
||||
"""Make any existing salary structure for employee inactive."""
|
||||
ret = self.get_other_active_salary_structure()
|
||||
if ret:
|
||||
frappe.db.set_value("Salary Structure", ret, "is_active", "No")
|
||||
def check_overlap(self):
|
||||
existing = frappe.db.sql("""select name from `tabSalary Structure`
|
||||
where employee = %(employee)s and
|
||||
(
|
||||
(%(from_date)s > from_date and %(from_date)s < to_date) or
|
||||
(%(to_date)s > from_date and %(to_date)s < to_date) or
|
||||
(%(from_date)s <= from_date and %(to_date)s >= to_date))
|
||||
and name!=%(name)s
|
||||
and docstatus < 2""",
|
||||
{
|
||||
"employee": self.employee,
|
||||
"from_date": self.from_date,
|
||||
"to_date": self.to_date,
|
||||
"name": self.name or "No Name"
|
||||
}, as_dict=True)
|
||||
|
||||
if existing:
|
||||
frappe.throw(_("Salary structure {0} already exist, more than one salary structure for same period is not allowed").format(existing[0].name))
|
||||
|
||||
def validate_amount(self):
|
||||
if flt(self.net_pay) < 0:
|
||||
if flt(self.net_pay) < 0 and self.salary_slip_based_on_timesheet:
|
||||
frappe.throw(_("Net pay cannot be negative"))
|
||||
|
||||
def validate_employee(self):
|
||||
old_employee = frappe.db.get_value("Salary Structure", self.name, "employee")
|
||||
if old_employee and self.employee != old_employee:
|
||||
frappe.throw(_("Employee can not be changed"))
|
||||
|
||||
|
||||
def validate_joining_date(self):
|
||||
joining_date = getdate(frappe.db.get_value("Employee", self.employee, "date_of_joining"))
|
||||
if getdate(self.from_date) < joining_date:
|
||||
@@ -93,6 +94,7 @@ class SalaryStructure(Document):
|
||||
@frappe.whitelist()
|
||||
def make_salary_slip(source_name, target_doc=None):
|
||||
def postprocess(source, target):
|
||||
target.salary_structure = source.name
|
||||
target.run_method("pull_emp_details")
|
||||
target.run_method("get_leave_details")
|
||||
target.run_method("calculate_net_pay")
|
||||
@@ -109,7 +111,7 @@ def make_salary_slip(source_name, target_doc=None):
|
||||
"field_map": [
|
||||
["depend_on_lwp", "d_depends_on_lwp"],
|
||||
["d_modified_amt", "d_amount"],
|
||||
["d_modified_amt", "d_modified_amount"]
|
||||
["d_modified_amt", "deduction_amount"]
|
||||
],
|
||||
"add_if_empty": True
|
||||
},
|
||||
@@ -117,8 +119,8 @@ def make_salary_slip(source_name, target_doc=None):
|
||||
"doctype": "Salary Slip Earning",
|
||||
"field_map": [
|
||||
["depend_on_lwp", "e_depends_on_lwp"],
|
||||
["modified_value", "e_modified_amount"],
|
||||
["modified_value", "e_amount"]
|
||||
["modified_value", "e_amount"],
|
||||
["modified_value", "earning_amount"]
|
||||
],
|
||||
"add_if_empty": True
|
||||
}
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
"from_date": "2014-02-01",
|
||||
"earnings": [
|
||||
{
|
||||
"e_type": "_Test Basic Salary"
|
||||
"earning_type": "_Test Basic Salary"
|
||||
},
|
||||
{
|
||||
"e_type": "_Test Allowance"
|
||||
"earning_type": "_Test Allowance"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -2,19 +2,22 @@
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2013-02-22 01:27:48",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "d_type",
|
||||
"fieldname": "deduction_type",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Type",
|
||||
@@ -25,6 +28,7 @@
|
||||
"options": "Deduction Type",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "200px",
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -42,6 +46,7 @@
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Amount",
|
||||
@@ -52,6 +57,7 @@
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@@ -67,6 +73,7 @@
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Reduce Deduction for Leave Without Pay (LWP)",
|
||||
@@ -76,6 +83,7 @@
|
||||
"oldfieldtype": "Check",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@@ -87,18 +95,21 @@
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2015-11-16 06:29:55.793274",
|
||||
"modified": "2016-06-27 15:36:26.491643",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Salary Structure Deduction",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0
|
||||
"read_only_onload": 0,
|
||||
"track_seen": 0
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2013-02-22 01:27:48",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
@@ -11,10 +12,11 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "e_type",
|
||||
"fieldname": "earning_type",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Type",
|
||||
@@ -25,6 +27,7 @@
|
||||
"options": "Earning Type",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "200px",
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -42,6 +45,7 @@
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Amount",
|
||||
@@ -52,6 +56,7 @@
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@@ -67,6 +72,7 @@
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Reduce Earning for Leave Without Pay (LWP)",
|
||||
@@ -76,6 +82,7 @@
|
||||
"oldfieldtype": "Check",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@@ -87,18 +94,22 @@
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2015-11-16 06:29:55.830492",
|
||||
"modified": "2016-06-27 15:28:58.884891",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Salary Structure Earning",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0
|
||||
"read_only_onload": 0,
|
||||
"sort_order": "ASC",
|
||||
"track_seen": 0
|
||||
}
|
||||
@@ -42,12 +42,12 @@ def get_columns(salary_slips):
|
||||
_("Payment Days") + ":Float:120"
|
||||
]
|
||||
|
||||
earning_types = frappe.db.sql_list("""select distinct e_type from `tabSalary Slip Earning`
|
||||
where e_modified_amount != 0 and parent in (%s)""" %
|
||||
earning_types = frappe.db.sql_list("""select distinct earning_type from `tabSalary Slip Earning`
|
||||
where earning_amount != 0 and parent in (%s)""" %
|
||||
(', '.join(['%s']*len(salary_slips))), tuple([d.name for d in salary_slips]))
|
||||
|
||||
ded_types = frappe.db.sql_list("""select distinct d_type from `tabSalary Slip Deduction`
|
||||
where d_modified_amount != 0 and parent in (%s)""" %
|
||||
ded_types = frappe.db.sql_list("""select distinct deduction_type from `tabSalary Slip Deduction`
|
||||
where deduction_amount != 0 and parent in (%s)""" %
|
||||
(', '.join(['%s']*len(salary_slips))), tuple([d.name for d in salary_slips]))
|
||||
|
||||
columns = columns + [(e + ":Currency:120") for e in earning_types] + \
|
||||
@@ -83,25 +83,25 @@ def get_conditions(filters):
|
||||
return conditions, filters
|
||||
|
||||
def get_ss_earning_map(salary_slips):
|
||||
ss_earnings = frappe.db.sql("""select parent, e_type, e_modified_amount
|
||||
ss_earnings = frappe.db.sql("""select parent, earning_type, earning_amount
|
||||
from `tabSalary Slip Earning` where parent in (%s)""" %
|
||||
(', '.join(['%s']*len(salary_slips))), tuple([d.name for d in salary_slips]), as_dict=1)
|
||||
|
||||
ss_earning_map = {}
|
||||
for d in ss_earnings:
|
||||
ss_earning_map.setdefault(d.parent, frappe._dict()).setdefault(d.e_type, [])
|
||||
ss_earning_map[d.parent][d.e_type] = flt(d.e_modified_amount)
|
||||
ss_earning_map.setdefault(d.parent, frappe._dict()).setdefault(d.earning_type, [])
|
||||
ss_earning_map[d.parent][d.earning_type] = flt(d.earning_amount)
|
||||
|
||||
return ss_earning_map
|
||||
|
||||
def get_ss_ded_map(salary_slips):
|
||||
ss_deductions = frappe.db.sql("""select parent, d_type, d_modified_amount
|
||||
ss_deductions = frappe.db.sql("""select parent, deduction_type, deduction_amount
|
||||
from `tabSalary Slip Deduction` where parent in (%s)""" %
|
||||
(', '.join(['%s']*len(salary_slips))), tuple([d.name for d in salary_slips]), as_dict=1)
|
||||
|
||||
ss_ded_map = {}
|
||||
for d in ss_deductions:
|
||||
ss_ded_map.setdefault(d.parent, frappe._dict()).setdefault(d.d_type, [])
|
||||
ss_ded_map[d.parent][d.d_type] = flt(d.d_modified_amount)
|
||||
ss_ded_map.setdefault(d.parent, frappe._dict()).setdefault(d.deduction_type, [])
|
||||
ss_ded_map[d.parent][d.deduction_type] = flt(d.deduction_amount)
|
||||
|
||||
return ss_ded_map
|
||||
Reference in New Issue
Block a user