diff --git a/erpnext/hr/doctype/salary_manager/salary_manager.py b/erpnext/hr/doctype/salary_manager/salary_manager.py index 660890a3c8..a0cbb70e1d 100644 --- a/erpnext/hr/doctype/salary_manager/salary_manager.py +++ b/erpnext/hr/doctype/salary_manager/salary_manager.py @@ -45,14 +45,14 @@ class DocType: """ cond = self.get_filter_condition() + cond += self.get_joining_releiving_condition() emp_list = sql(""" select t1.name from `tabEmployee` t1, `tabSalary Structure` t2 where t1.docstatus!=2 and t2.docstatus != 2 - and ifnull(t1.status, 'Left') = 'Active' and ifnull(t2.is_active, 'No') = 'Yes' and t1.name = t2.employee - %s """% cond) + %s """% cond, debug=1) return emp_list @@ -63,9 +63,19 @@ class DocType: cond = '' for f in ['company', 'branch', 'department', 'designation', 'grade']: if self.doc.fields.get(f): - cond += " and t1." + f + " = '" + self.doc.fields.get(f) + "'" - + cond += " and t1." + f + " = '" + self.doc.fields.get(f) + "'" + return cond + + + def get_joining_releiving_condition(self): + m = self.get_month_details(self.doc.fiscal_year, self.doc.month) + cond = """ + and ifnull(t1.date_of_joining, '0000-00-00') <= '%(month_end_date)s' + and ifnull(t1.relieving_date, '2199-12-31') >= '%(month_start_date)s' + """ % m + return cond + def check_mandatory(self): @@ -73,6 +83,26 @@ class DocType: if not self.doc.fields[f]: msgprint("Please select %s to proceed" % f, raise_exception=1) + + def get_month_details(self, year, month): + ysd = sql("select year_start_date from `tabFiscal Year` where name ='%s'"%year)[0][0] + if ysd: + from dateutil.relativedelta import relativedelta + import calendar, datetime + diff_mnt = cint(month)-cint(ysd.month) + if diff_mnt<0: + diff_mnt = 12-int(ysd.month)+cint(month) + msd = ysd + relativedelta(months=diff_mnt) # month start date + month_days = cint(calendar.monthrange(cint(msd.year) ,cint(month))[1]) # days in month + med = datetime.date(msd.year, cint(month), month_days) # month end date + return { + 'year': msd.year, + 'month_start_date': msd, + 'month_end_date': med, + 'month_days': month_days + } + + def create_sal_slip(self): """ @@ -81,12 +111,7 @@ class DocType: """ emp_list = self.get_emp_list() - log = "" - if emp_list: - log = "" - else: - log = "
Following Salary Slip has been created:
SAL SLIP IDEMPLOYEE NAME
" - + ss_list = [] for emp in emp_list: if not sql("""select name from `tabSalary Slip` where docstatus!= 2 and employee = %s and month = %s and fiscal_year = %s and company = %s @@ -110,9 +135,18 @@ class DocType: for d in getlist(ss_obj.doclist, 'deduction_details'): d.save() - log += '' - log += '
No employee found for the above selected criteria
' + ss.name + '' + ss_obj.doc.employee_name + '
' - return log + ss_list.append(ss.name) + + return self.create_log(ss_list) + + + def create_log(self, ss_list): + log = "No employee for the above selected criteria OR salary slip already created" + if ss_list: + log = "Created Salary Slip has been created: \ +

%s" % '
'.join(ss_list) + return log + def get_sal_slip_list(self): """ @@ -146,10 +180,10 @@ class DocType: msgprint(e) continue - return self.create_log(ss_list, not_submitted_ss) + return self.create_submit_log(ss_list, not_submitted_ss) - def create_log(self, all_ss, not_submitted_ss): + def create_submit_log(self, all_ss, not_submitted_ss): log = '' if not all_ss: log = "No salary slip found to submit for the above selected criteria" @@ -188,7 +222,7 @@ class DocType: """ % (self.doc.month, self.doc.fiscal_year, cond)) return flt(tot[0][0]) - + def get_acc_details(self): """ diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.js b/erpnext/hr/doctype/salary_slip/salary_slip.js index 5fe93a68a5..3e61665a2b 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.js +++ b/erpnext/hr/doctype/salary_slip/salary_slip.js @@ -45,9 +45,13 @@ cur_frm.cscript.month = cur_frm.cscript.employee = cur_frm.cscript.fiscal_year; // Calculate total if lwp exists // ------------------------------------------------------------------------ cur_frm.cscript.leave_without_pay = function(doc,dt,dn){ - doc.payment_days = flt(doc.total_days_in_month) - flt(doc.leave_without_pay); - refresh_field('payment_days'); - calculate_all(doc, dt, dn); + if (doc.employee && doc.fiscal_year && doc.month) { + $c_obj(make_doclist(doc.doctype,doc.name), 'get_leave_details',doc.leave_without_pay,function(r, rt) { + var doc = locals[dt][dn]; + cur_frm.refresh(); + calculate_all(doc, dt, dn); + }); + } } // Calculate all diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index 3187eb43ff..9860eab750 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -39,27 +39,22 @@ class DocType(TransactionBase): self.doclist = doclist - # autoname - #======================================================= def autoname(self): self.doc.name = make_autoname('Sal Slip/' +self.doc.employee + '/.#####') - # Get employee details - #======================================================= - def get_emp_and_leave_details(self): - # Get payment days - if self.doc.fiscal_year and self.doc.month: - self.get_leave_details() - # check sal structure + def get_emp_and_leave_details(self): if self.doc.employee: + # Get payment days + if self.doc.fiscal_year and self.doc.month: + self.get_leave_details() + + # check sal structure struct = self.check_sal_struct() if struct: self.pull_sal_struct(struct) - # Check sal structure - #======================================================= def check_sal_struct(self): struct = sql("select name from `tabSalary Structure` where employee ='%s' and is_active = 'Yes' "%self.doc.employee) if not struct: @@ -67,8 +62,7 @@ class DocType(TransactionBase): self.doc.employee = '' return struct and struct[0][0] or '' - # Pull struct details - #======================================================= + def pull_sal_struct(self, struct): self.doclist = self.doc.clear_table(self.doclist, 'earning_details') self.doclist = self.doc.clear_table(self.doclist, 'deduction_details') @@ -81,41 +75,48 @@ class DocType(TransactionBase): self.doc.esic_no = basic_info[0][2] self.doc.pf_no = basic_info[0][3] - # Get leave details - #======================================================= - def get_leave_details(self): - m = self.get_month_details() - lwp = self.calculate_lwp(m) - self.doc.total_days_in_month = m[3] + + def get_leave_details(self, lwp=None): + m = get_obj('Salary Manager').get_month_details(self.doc.fiscal_year, self.doc.month) + + if not lwp: + lwp = self.calculate_lwp(m) + self.doc.total_days_in_month = m['month_days'] self.doc.leave_without_pay = lwp - self.doc.payment_days = flt(m[3]) - flt(lwp) + payment_days = flt(self.get_payment_days(m)) - flt(lwp) + self.doc.payment_days = payment_days > 0 and payment_days or 0 + + + def get_payment_days(self, m): + payment_days = m['month_days'] + emp = webnotes.conn.sql("select date_of_joining, relieving_date from `tabEmployee` \ + where name = %s", self.doc.employee, as_dict=1)[0] + + if emp['relieving_date']: + if getdate(emp['relieving_date']) > m['month_start_date'] and getdate(emp['relieving_date']) < m['month_end_date']: + payment_days = getdate(emp['relieving_date']).day + elif getdate(emp['relieving_date']) < m['month_start_date']: + payment_days = 0 + + if emp['date_of_joining']: + if getdate(emp['date_of_joining']) > m['month_start_date'] and getdate(emp['date_of_joining']) < m['month_end_date']: + payment_days = payment_days - getdate(emp['date_of_joining']).day + 1 + elif getdate(emp['date_of_joining']) > m['month_end_date']: + payment_days = 0 + + return payment_days + + - # Get month details - #======================================================= - def get_month_details(self): - ysd = sql("select year_start_date from `tabFiscal Year` where name ='%s'"%self.doc.fiscal_year)[0][0] - if ysd: - from dateutil.relativedelta import relativedelta - import calendar, datetime - mnt = int(self.doc.month) - diff_mnt = int(mnt)-int(ysd.month) - if diff_mnt<0: - diff_mnt = 12-int(ysd.month)+int(mnt) - msd = ysd + relativedelta(months=diff_mnt) # month start date - month_days = cint(calendar.monthrange(cint(msd.year) ,cint(self.doc.month))[1]) # days in month - med = datetime.date(msd.year, cint(self.doc.month), month_days) # month end date - return msd.year, msd, med, month_days - # Calculate LWP - #======================================================= def calculate_lwp(self, m): - holidays = sql("select t1.holiday_date from `tabHoliday` t1, tabEmployee t2 where t1.parent = t2.holiday_list and t2.name = '%s' and t1.holiday_date between '%s' and '%s'" % (self.doc.employee, m[1], m[2])) + holidays = sql("select t1.holiday_date from `tabHoliday` t1, tabEmployee t2 where t1.parent = t2.holiday_list and t2.name = '%s' and t1.holiday_date between '%s' and '%s'" % (self.doc.employee, m['month_start_date'], m['month_end_date'])) if not holidays: holidays = sql("select t1.holiday_date from `tabHoliday` t1, `tabHoliday List` t2 where t1.parent = t2.name and ifnull(t2.is_default, 0) = 1 and t2.fiscal_year = '%s'" % self.doc.fiscal_year) holidays = [cstr(i[0]) for i in holidays] lwp = 0 - for d in range(m[3]): - dt = add_days(cstr(m[1]), d) + for d in range(m['month_days']): + dt = add_days(cstr(m['month_start_date']), d) if dt not in holidays: leave = sql(""" select t1.name, t1.half_day @@ -130,8 +131,7 @@ class DocType(TransactionBase): lwp = cint(leave[0][1]) and lwp + 0.5 or lwp + 1 return lwp - # Check existing - #======================================================= + def check_existing(self): ret_exist = sql("select name from `tabSalary Slip` where month = '%s' and fiscal_year = '%s' and docstatus != 2 and employee = '%s' and name !='%s'" % (self.doc.month,self.doc.fiscal_year,self.doc.employee,self.doc.name)) if ret_exist: @@ -139,8 +139,7 @@ class DocType(TransactionBase): self.doc.employee = '' raise Exception - # Validate - #======================================================= + def validate(self): self.check_existing() dcc = TransactionBase().get_company_currency(self.doc.company) @@ -155,6 +154,8 @@ class DocType(TransactionBase): for d in getlist(self.doclist, 'earning_details'): if cint(d.e_depends_on_lwp) == 1: d.e_modified_amount = round(flt(d.e_amount)*flt(self.doc.payment_days)/cint(self.doc.total_days_in_month), 2) + elif not self.doc.payment_days: + d.e_modified_amount = 0 self.doc.gross_pay += d.e_modified_amount def calculate_ded_total(self): @@ -165,6 +166,9 @@ class DocType(TransactionBase): for d in getlist(self.doclist, 'deduction_details'): if cint(d.d_depends_on_lwp) == 1: d.d_modified_amount = round(flt(d.d_amount)*flt(self.doc.payment_days)/cint(self.doc.total_days_in_month), 2) + elif not self.doc.payment_days: + d.d_modified_amount = 0 + self.doc.total_deduction += d.d_modified_amount def calculate_net_pay(self): @@ -176,17 +180,12 @@ class DocType(TransactionBase): self.doc.net_pay = flt(self.doc.gross_pay) - flt(self.doc.total_deduction) self.doc.rounded_total = round(self.doc.net_pay) - # ON SUBMIT - #======================================================= + def on_submit(self): if(self.doc.email_check == 1): self.send_mail_funct() - - - # Send mail - #======================================================= def send_mail_funct(self): from webnotes.utils.email_lib import sendmail emailid_ret=sql("select company_email from `tabEmployee` where name = '%s'"%self.doc.employee)