diff --git a/hr/doctype/employee/employee.js b/hr/doctype/employee/employee.js index 239b3b7a83..5a2dbab87f 100644 --- a/hr/doctype/employee/employee.js +++ b/hr/doctype/employee/employee.js @@ -14,62 +14,95 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -cur_frm.cscript.onload = function(doc) { - // bc - var india_specific = ["esic_card_no", "gratuity_lic_id", "pan_number", "pf_number"] - if(wn.control_panel.country!="India") { - hide_field(india_specific); - } -} - -cur_frm.cscript.refresh = function(doc) { - if(!doc.__islocal) { - hide_field("naming_series"); - cur_frm.add_custom_button('Make Salary Structure', - cur_frm.cscript['Make Salary Structure']); - } -} - -cur_frm.cscript.date_of_birth = function(doc, dt, dn) { - get_server_fields('get_retirement_date','','',doc,dt,dn,1); -} - -cur_frm.cscript.salutation = function(doc,dt,dn) { - if(doc.salutation){ - if(doc.salutation=='Mr') - doc.gender='Male'; - else if(doc.salutation=='Ms') - doc.gender='Female'; - refresh_field('gender'); - } -} - -cur_frm.cscript['Make Salary Structure']=function(){ - $c_obj(make_doclist (cur_frm.doc.doctype, cur_frm.doc.name), 'check_sal_structure', - cur_frm.doc.name, function(r, rt) { - if(r.message) - msgprint("You have already created Active salary structure.\n \ - If you want to create new one, please ensure that no active salary structure \ - exist.\nTo inactive salary structure select 'Is Active' as 'No'."); - else - cur_frm.cscript.make_salary_structure(cur_frm.doc); +wn.provide("erpnext.hr"); +erpnext.hr.EmployeeController = wn.ui.form.Controller.extend({ + setup: function() { + this.setup_leave_approver_select(); + this.frm.fields_dict.user_id.get_query = erpnext.utils.profile_query; + this.frm.fields_dict.reports_to.get_query = erpnext.utils.employee_query; + }, + + onload: function() { + this.frm.toggle_display(["esic_card_no", "gratuity_lic_id", "pan_number", "pf_number"], + wn.control_panel.country==="India"); + }, + + refresh: function() { + var me = this; + erpnext.hide_naming_series(); + if(!this.frm.doc.__islocal) { + cur_frm.add_custom_button('View Active Salary Structure', function() { + me.view_active_salary_structure(this); }); + + cur_frm.add_custom_button('Make Salary Structure', function() { + me.make_salary_structure(this); }); + } - ); -} - -cur_frm.cscript.make_salary_structure = function(doc, dt, dn, det){ - var st = wn.model.make_new_doc_and_get_name('Salary Structure'); - st = locals['Salary Structure'][st]; - st.employee = doc.name; - st.employee_name = doc.employee_name; - st.branch=doc.branch; - st.designation=doc.designation; - st.department=doc.department; - st.fiscal_year = doc.fiscal_year - st.grade=doc.grade; - loaddoc('Salary Structure', st.name); -} - -cur_frm.fields_dict.user_id.get_query = erpnext.utils.profile_query; - -cur_frm.fields_dict.reports_to.get_query = erpnext.utils.employee_query; \ No newline at end of file + }, + + setup_leave_approver_select: function() { + var me = this; + this.frm.call({ + method:"hr.utils.get_leave_approver_list", + callback: function(r) { + me.frm.fields_dict.employee_leave_approvers.grid.get_field("leave_approver").df.options = + $.map(r.message, function(profile) { + return {value: profile, label: wn.user_info(profile).fullname}; + }); + } + }); + }, + + date_of_birth: function() { + cur_frm.call({ + method: "get_retirement_date", + args: {date_of_birth: this.frm.doc.date_of_birth} + }); + }, + + salutation: function() { + if(this.frm.doc.salutation) { + this.frm.set_value("gender", { + "Mr": "Male", + "Ms": "Female" + }[this.frm.doc.salutation]); + } + }, + + make_salary_structure: function(btn) { + var me = this; + this.validate_salary_structure(btn, function(r) { + if(r.message) { + msgprint(wn._("Employee") + ' "' + me.frm.doc.name + '": ' + + wn._("An active Salary Structure already exists. \ + If you want to create new one, please ensure that no active Salary Structure \ + exists for this Employee. Go to the active Salary Structure and set \ + \"Is Active\" = \"No\"")); + } else if(!r.exc) { + wn.model.map({ + source: wn.model.get_doclist(me.frm.doc.doctype, me.frm.doc.name), + target: "Salary Structure" + }); + } + }); + }, + + validate_salary_structure: function(btn, callback) { + var me = this; + this.frm.call({ + btn: btn, + method: "webnotes.client.get_value", + args: { + doctype: "Salary Structure", + fieldname: "name", + filters: { + employee: me.frm.doc.name, + is_active: "Yes", + docstatus: ["!=", 2] + }, + }, + callback: callback + }); + }, +}); +cur_frm.cscript = new erpnext.hr.EmployeeController({frm: cur_frm}); \ No newline at end of file diff --git a/hr/doctype/employee/employee.py b/hr/doctype/employee/employee.py index 16ecb6d2ed..59c8380ee6 100644 --- a/hr/doctype/employee/employee.py +++ b/hr/doctype/employee/employee.py @@ -27,7 +27,7 @@ class DocType: def __init__(self,doc,doclist=[]): self.doc = doc self.doclist = doclist - + def autoname(self): ret = sql("select value from `tabSingles` where doctype = 'Global Defaults' and field = 'emp_created_by'") if not ret: @@ -49,30 +49,31 @@ class DocType: self.validate_email() self.validate_name() self.validate_status() - - def get_retirement_date(self): - import datetime - ret = {} - if self.doc.date_of_birth: - dt = getdate(self.doc.date_of_birth) + datetime.timedelta(21915) - ret = {'date_of_retirement': dt.strftime('%Y-%m-%d')} - return ret - - def check_sal_structure(self, nm): - ret_sal_struct=sql("select name from `tabSalary Structure` where employee='%s' and is_active = 'Yes' and docstatus!= 2"%nm) - return ret_sal_struct and ret_sal_struct[0][0] or '' - + self.validate_employee_leave_approver() + def on_update(self): if self.doc.user_id: self.update_user_default() self.update_profile() - + def update_user_default(self): webnotes.conn.set_default("employee", self.doc.name, self.doc.user_id) webnotes.conn.set_default("employee_name", self.doc.employee_name, self.doc.user_id) webnotes.conn.set_default("company", self.doc.company, self.doc.user_id) - if self.doc.reports_to: - webnotes.conn.set_default("leave_approver", webnotes.conn.get_value("Employee", self.doc.reports_to, "user_id"), self.doc.user_id) + self.set_default_leave_approver() + + def set_default_leave_approver(self): + employee_leave_approvers = self.doclist.get({"parentfield": "employee_leave_approvers"}) + + if len(employee_leave_approvers): + webnotes.conn.set_default("leave_approver", employee_leave_approvers[0].leave_approver, + self.doc.user_id) + + elif self.doc.reports_to: + from webnotes.profile import Profile + reports_to_user = webnotes.conn.get_value("Employee", self.doc.reports_to, "user_id") + if "Leave Approver" in Profile(reports_to_user).get_roles(): + webnotes.conn.set_default("leave_approver", reports_to_user, self.doc.user_id) def update_profile(self): # add employee role if missing @@ -116,7 +117,6 @@ class DocType: profile_wrapper.save() def validate_date(self): - import datetime if self.doc.date_of_birth and self.doc.date_of_joining and getdate(self.doc.date_of_birth) >= getdate(self.doc.date_of_joining): msgprint('Date of Joining must be greater than Date of Birth') raise Exception @@ -167,3 +167,21 @@ class DocType: if self.doc.status == 'Left' and not self.doc.relieving_date: msgprint("Please enter relieving date.") raise Exception + + def validate_employee_leave_approver(self): + from webnotes.profile import Profile + from hr.doctype.leave_application.leave_application import InvalidLeaveApproverError + + for l in self.doclist.get({"parentfield": "employee_leave_approvers"}): + if "Leave Approver" not in Profile(l.leave_approver).get_roles(): + msgprint(_("Invalid Leave Approver") + ": \"" + l.leave_approver + "\"", + raise_exception=InvalidLeaveApproverError) + +@webnotes.whitelist() +def get_retirement_date(date_of_birth=None): + import datetime + ret = {} + if date_of_birth: + dt = getdate(date_of_birth) + datetime.timedelta(21915) + ret = {'date_of_retirement': dt.strftime('%Y-%m-%d')} + return ret diff --git a/hr/doctype/employee/employee.txt b/hr/doctype/employee/employee.txt index 7b1f730353..997a1efb51 100644 --- a/hr/doctype/employee/employee.txt +++ b/hr/doctype/employee/employee.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-01-23 19:57:17", + "creation": "2013-03-07 09:04:18", "docstatus": 0, - "modified": "2013-02-08 13:07:25", + "modified": "2013-04-12 07:16:42", "modified_by": "Administrator", "owner": "Administrator" }, @@ -322,15 +322,6 @@ "options": "Grade", "reqd": 0 }, - { - "doctype": "DocField", - "fieldname": "reports_to", - "fieldtype": "Link", - "label": "Reports to", - "oldfieldname": "reports_to", - "oldfieldtype": "Link", - "options": "Employee" - }, { "description": "Provide email id registered in company", "doctype": "DocField", @@ -342,6 +333,14 @@ "oldfieldtype": "Data", "reqd": 0 }, + { + "doctype": "DocField", + "fieldname": "notice_number_of_days", + "fieldtype": "Int", + "label": "Notice - Number of Days", + "oldfieldname": "notice_number_of_days", + "oldfieldtype": "Int" + }, { "doctype": "DocField", "fieldname": "salary_information", @@ -405,6 +404,29 @@ "oldfieldname": "gratuity_lic_id", "oldfieldtype": "Data" }, + { + "doctype": "DocField", + "fieldname": "organization_profile", + "fieldtype": "Section Break", + "label": "Organization Profile" + }, + { + "doctype": "DocField", + "fieldname": "reports_to", + "fieldtype": "Link", + "label": "Reports to", + "oldfieldname": "reports_to", + "oldfieldtype": "Link", + "options": "Employee" + }, + { + "description": "The first Leave Approver in the list will be set as the default Leave Approver", + "doctype": "DocField", + "fieldname": "employee_leave_approvers", + "fieldtype": "Table", + "label": "Leave Approvers", + "options": "Employee Leave Approver" + }, { "doctype": "DocField", "fieldname": "contact_details", @@ -429,14 +451,6 @@ "fieldtype": "Data", "label": "Personal Email" }, - { - "doctype": "DocField", - "fieldname": "notice_number_of_days", - "fieldtype": "Int", - "label": "Notice - Number of Days", - "oldfieldname": "notice_number_of_days", - "oldfieldtype": "Int" - }, { "doctype": "DocField", "fieldname": "emergency_contact_details", @@ -767,4 +781,4 @@ "role": "HR Manager", "write": 1 } -] +] \ No newline at end of file diff --git a/hr/doctype/employee_leave_approver/__init__.py b/hr/doctype/employee_leave_approver/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/hr/doctype/employee_leave_approver/employee_leave_approver.py b/hr/doctype/employee_leave_approver/employee_leave_approver.py new file mode 100644 index 0000000000..928aa9ff9f --- /dev/null +++ b/hr/doctype/employee_leave_approver/employee_leave_approver.py @@ -0,0 +1,8 @@ +# For license information, please see license.txt + +from __future__ import unicode_literals +import webnotes + +class DocType: + def __init__(self, d, dl): + self.doc, self.doclist = d, dl \ No newline at end of file diff --git a/hr/doctype/employee_leave_approver/employee_leave_approver.txt b/hr/doctype/employee_leave_approver/employee_leave_approver.txt new file mode 100644 index 0000000000..31e3e09efa --- /dev/null +++ b/hr/doctype/employee_leave_approver/employee_leave_approver.txt @@ -0,0 +1,39 @@ +[ + { + "creation": "2013-04-12 06:56:15", + "docstatus": 0, + "modified": "2013-04-12 07:53:33", + "modified_by": "Administrator", + "owner": "Administrator" + }, + { + "allow_import": 0, + "autoname": "LAPPR-/.#####", + "description": "Users who can approve a specific employee's leave applications", + "doctype": "DocType", + "istable": 1, + "module": "HR", + "name": "__common__" + }, + { + "doctype": "DocField", + "fieldname": "leave_approver", + "fieldtype": "Select", + "label": "Leave Approver", + "name": "__common__", + "parent": "Employee Leave Approver", + "parentfield": "fields", + "parenttype": "DocType", + "permlevel": 0, + "print_hide": 1, + "reqd": 1, + "width": "200" + }, + { + "doctype": "DocType", + "name": "Employee Leave Approver" + }, + { + "doctype": "DocField" + } +] \ No newline at end of file diff --git a/hr/doctype/expense_claim/expense_claim.js b/hr/doctype/expense_claim/expense_claim.js index 72fe15cfa1..5b136d0a2e 100644 --- a/hr/doctype/expense_claim/expense_claim.js +++ b/hr/doctype/expense_claim/expense_claim.js @@ -29,7 +29,7 @@ cur_frm.cscript.onload = function(doc,cdt,cdn){ } cur_frm.call({ - method:"get_approver_list", + method:"hr.utils.get_expense_approver_list", callback: function(r) { cur_frm.set_df_property("exp_approver", "options", r.message); } diff --git a/hr/doctype/expense_claim/expense_claim.py b/hr/doctype/expense_claim/expense_claim.py index 0aa9ed80b9..0564d1d085 100644 --- a/hr/doctype/expense_claim/expense_claim.py +++ b/hr/doctype/expense_claim/expense_claim.py @@ -52,12 +52,3 @@ class DocType: if not getlist(self.doclist, 'expense_voucher_details'): msgprint("Please add expense voucher details") raise Exception - -@webnotes.whitelist() -def get_approver_list(): - roles = [r[0] for r in webnotes.conn.sql("""select distinct parent from `tabUserRole` - where role='Expense Approver'""")] - if not roles: - webnotes.msgprint("No Expense Approvers. Please assign 'Expense Approver' \ - Role to atleast one user.") - return roles diff --git a/hr/doctype/leave_application/leave_application.js b/hr/doctype/leave_application/leave_application.js index 025281826c..7f8948a674 100755 --- a/hr/doctype/leave_application/leave_application.js +++ b/hr/doctype/leave_application/leave_application.js @@ -26,7 +26,7 @@ cur_frm.cscript.onload = function(doc, dt, dn) { } cur_frm.set_df_property("leave_approver", "options", ""); cur_frm.call({ - method:"get_approver_list", + method:"hr.utils.get_leave_approver_list", callback: function(r) { cur_frm.set_df_property("leave_approver", "options", $.map(r.message, function(profile) { diff --git a/hr/doctype/leave_application/leave_application.py b/hr/doctype/leave_application/leave_application.py index d34abd88c1..b9f9e5bfef 100755 --- a/hr/doctype/leave_application/leave_application.py +++ b/hr/doctype/leave_application/leave_application.py @@ -18,11 +18,13 @@ from __future__ import unicode_literals import webnotes from webnotes import _ -from webnotes.utils import cint, cstr, date_diff, flt, formatdate, getdate, get_url_to_form +from webnotes.utils import cint, cstr, date_diff, flt, formatdate, getdate, get_url_to_form, \ + comma_or, get_fullname from webnotes import msgprint -class LeaveDayBlockedError(Exception): pass -class OverlapError(Exception): pass +class LeaveDayBlockedError(webnotes.ValidationError): pass +class OverlapError(webnotes.ValidationError): pass +class InvalidLeaveApproverError(webnotes.ValidationError): pass from webnotes.model.controller import DocListController class DocType(DocListController): @@ -39,6 +41,7 @@ class DocType(DocListController): self.validate_max_days() self.show_block_day_warning() self.validate_block_days() + self.validate_leave_approver() def on_update(self): if (not self.previous_doc and self.doc.leave_approver) or (self.previous_doc and \ @@ -156,6 +159,21 @@ class DocType(DocListController): msgprint("Sorry ! You cannot apply for %s for more than %s days" % (self.doc.leave_type, max_days)) raise Exception + def validate_leave_approver(self): + employee = webnotes.bean("Employee", self.doc.employee) + leave_approvers = [l.leave_approver for l in + employee.doclist.get({"parentfield": "employee_leave_approvers"})] + + if len(leave_approvers) and self.doc.leave_approver not in leave_approvers: + msgprint(("[" + _("For Employee") + ' "' + self.doc.employee + '"] ' + + _("Leave Approver can be one of") + ": " + + comma_or(leave_approvers)), raise_exception=InvalidLeaveApproverError) + + elif self.doc.leave_approver and not webnotes.conn.sql("""select name from `tabUserRole` + where parent=%s and role='Leave Approver'""", self.doc.leave_approver): + msgprint(get_fullname(self.doc.leave_approver) + ": " \ + + _("does not have role 'Leave Approver'"), raise_exception=InvalidLeaveApproverError) + def notify_employee(self, status): employee = webnotes.doc("Employee", self.doc.employee) if not employee.user_id: @@ -221,15 +239,6 @@ def get_leave_balance(employee, leave_type, fiscal_year): ret = {'leave_balance': leave_all - leave_app} return ret -@webnotes.whitelist() -def get_approver_list(): - roles = [r[0] for r in webnotes.conn.sql("""select distinct parent from `tabUserRole` - where role='Leave Approver'""")] - if not roles: - webnotes.msgprint("No Leave Approvers. Please assign 'Leave Approver' Role to atleast one user.") - - return roles - def is_lwp(leave_type): lwp = webnotes.conn.sql("select is_lwp from `tabLeave Type` where name = %s", leave_type) return lwp and cint(lwp[0][0]) or 0 diff --git a/hr/doctype/leave_application/test_leave_application.py b/hr/doctype/leave_application/test_leave_application.py index 672e668c1e..338225c45e 100644 --- a/hr/doctype/leave_application/test_leave_application.py +++ b/hr/doctype/leave_application/test_leave_application.py @@ -4,6 +4,23 @@ import unittest from hr.doctype.leave_application.leave_application import LeaveDayBlockedError, OverlapError class TestLeaveApplication(unittest.TestCase): + def _clear_roles(self): + webnotes.conn.sql("""delete from `tabUserRole` where parent in + ("test@example.com", "test1@example.com", "test2@example.com")""") + + def _clear_applications(self): + webnotes.conn.sql("""delete from `tabLeave Application`""") + + def _add_employee_leave_approver(self, employee, leave_approver): + webnotes.session.user = "Administrator" + employee = webnotes.bean("Employee", employee) + employee.doclist.append({ + "doctype": "Employee Leave Approver", + "parentfield": "employee_leave_approvers", + "leave_approver": leave_approver + }) + employee.save() + def get_application(self, doclist): application = webnotes.bean(copy=doclist) application.doc.from_date = "2013-01-01" @@ -11,8 +28,14 @@ class TestLeaveApplication(unittest.TestCase): return application def test_block_list(self): - import webnotes - webnotes.conn.set_value("Department", "_Test Department", "leave_block_list", "_Test Leave Block List") + webnotes.session.user = "Administrator" + self._clear_roles() + + from webnotes.profile import add_role + add_role("test1@example.com", "HR User") + + webnotes.conn.set_value("Department", "_Test Department", + "leave_block_list", "_Test Leave Block List") application = self.get_application(test_records[1]) application.insert() @@ -20,9 +43,6 @@ class TestLeaveApplication(unittest.TestCase): self.assertRaises(LeaveDayBlockedError, application.submit) webnotes.session.user = "test1@example.com" - - from webnotes.profile import add_role - add_role("test1@example.com", "HR User") # clear other applications webnotes.conn.sql("delete from `tabLeave Application`") @@ -31,11 +51,31 @@ class TestLeaveApplication(unittest.TestCase): self.assertTrue(application.insert()) def test_overlap(self): + webnotes.session.user = "Administrator" + self._clear_roles() + self._clear_applications() + + from webnotes.profile import add_role + add_role("test@example.com", "Employee") + add_role("test2@example.com", "Leave Approver") + + webnotes.session.user = "test@example.com" application = self.get_application(test_records[1]) + application.doc.leave_approver = "test2@example.com" + application.insert() + + application = self.get_application(test_records[1]) + application.doc.leave_approver = "test2@example.com" self.assertRaises(OverlapError, application.insert) def test_global_block_list(self): - + webnotes.session.user = "Administrator" + self._clear_roles() + + from webnotes.profile import add_role + add_role("test1@example.com", "Employee") + add_role("test@example.com", "Leave Approver") + application = self.get_application(test_records[3]) application.doc.leave_approver = "test@example.com" @@ -44,19 +84,120 @@ class TestLeaveApplication(unittest.TestCase): webnotes.conn.set_value("Employee", "_T-Employee-0002", "department", "_Test Department") - webnotes.session.user = "test2@example.com" - from webnotes.profile import add_role - add_role("test2@example.com", "Employee") - + webnotes.session.user = "test1@example.com" application.insert() webnotes.session.user = "test@example.com" - from webnotes.profile import add_role - add_role("test@example.com", "Leave Approver") - application.doc.status = "Approved" self.assertRaises(LeaveDayBlockedError, application.submit) + webnotes.conn.set_value("Leave Block List", "_Test Leave Block List", + "applies_to_all_departments", 0) + + def test_leave_approval(self): + webnotes.session.user = "Administrator" + self._clear_roles() + + from webnotes.profile import add_role + add_role("test@example.com", "Employee") + add_role("test1@example.com", "Leave Approver") + add_role("test2@example.com", "Leave Approver") + + self._test_leave_approval_basic_case_1() + self._test_leave_approval_basic_case_2() + self._test_leave_approval_invalid_leave_approver_insert() + self._test_leave_approval_invalid_leave_approver_submit() + self._test_leave_approval_valid_leave_approver_insert() + + def _test_leave_approval_basic_case_1(self): + self._clear_applications() + + # create leave application as Employee + webnotes.session.user = "test@example.com" + application = self.get_application(test_records[1]) + application.doc.leave_approver = "test1@example.com" + application.insert() + + # submit leave application by Leave Approver + webnotes.session.user = "test1@example.com" + application.doc.status = "Approved" + application.submit() + self.assertEqual(webnotes.conn.get_value("Leave Application", application.doc.name, + "docstatus"), 1) + + def _test_leave_approval_basic_case_2(self): + self._clear_applications() + + # create leave application by any leave approver, + # when no leave approver specified in employee's leave approvers list + application = self.get_application(test_records[1]) + application.doc.leave_approver = "test1@example.com" + application.insert() + application.doc.status = "Approved" + application.submit() + self.assertEqual(webnotes.conn.get_value("Leave Application", application.doc.name, + "docstatus"), 1) + + def _test_leave_approval_invalid_leave_approver_insert(self): + from hr.doctype.leave_application.leave_application import InvalidLeaveApproverError + + self._clear_applications() + + # add a different leave approver in the employee's list + # should raise exception if not a valid leave approver + self._add_employee_leave_approver("_T-Employee-0001", "test2@example.com") + + # TODO - add test2@example.com leave approver in employee's leave approvers list + application = self.get_application(test_records[1]) + webnotes.session.user = "test@example.com" + + application.doc.leave_approver = "test1@example.com" + self.assertRaises(InvalidLeaveApproverError, application.insert) + + webnotes.conn.sql("""delete from `tabEmployee Leave Approver` where parent=%s""", + "_T-Employee-0001") + + def _test_leave_approval_invalid_leave_approver_submit(self): + self._clear_applications() + self._add_employee_leave_approver("_T-Employee-0001", "test2@example.com") + + # create leave application as employee + # but submit as invalid leave approver - should raise exception + webnotes.session.user = "test@example.com" + application = self.get_application(test_records[1]) + application.doc.leave_approver = "test2@example.com" + application.insert() + webnotes.session.user = "test1@example.com" + application.doc.status = "Approved" + + from webnotes.model.bean import BeanPermissionError + self.assertRaises(BeanPermissionError, application.submit) + + webnotes.conn.sql("""delete from `tabEmployee Leave Approver` where parent=%s""", + "_T-Employee-0001") + + def _test_leave_approval_valid_leave_approver_insert(self): + self._clear_applications() + self._add_employee_leave_approver("_T-Employee-0001", "test2@example.com") + + original_department = webnotes.conn.get_value("Employee", "_T-Employee-0001", "department") + webnotes.conn.set_value("Employee", "_T-Employee-0001", "department", None) + + # change to valid leave approver and try to create and submit leave application + webnotes.session.user = "test2@example.com" + application = self.get_application(test_records[1]) + application.doc.leave_approver = "test2@example.com" + application.insert() + application.doc.status = "Approved" + application.submit() + self.assertEqual(webnotes.conn.get_value("Leave Application", application.doc.name, + "docstatus"), 1) + + webnotes.conn.sql("""delete from `tabEmployee Leave Approver` where parent=%s""", + "_T-Employee-0001") + + webnotes.conn.set_value("Employee", "_T-Employee-0001", "department", original_department) + test_dependencies = ["Leave Block List"] test_records = [ diff --git a/hr/utils.py b/hr/utils.py new file mode 100644 index 0000000000..0d23a16c44 --- /dev/null +++ b/hr/utils.py @@ -0,0 +1,38 @@ +# ERPNext - web based ERP (http://erpnext.com) +# Copyright (C) 2012 Web Notes Technologies Pvt Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from __future__ import unicode_literals +import webnotes +from webnotes import _ + +@webnotes.whitelist() +def get_leave_approver_list(): + roles = [r[0] for r in webnotes.conn.sql("""select distinct parent from `tabUserRole` + where role='Leave Approver'""")] + if not roles: + webnotes.msgprint(_("No Leave Approvers. Please assign 'Leave Approver' Role to atleast one user.")) + + return roles + + +@webnotes.whitelist() +def get_expense_approver_list(): + roles = [r[0] for r in webnotes.conn.sql("""select distinct parent from `tabUserRole` + where role='Expense Approver'""")] + if not roles: + webnotes.msgprint("No Expense Approvers. Please assign 'Expense Approver' \ + Role to atleast one user.") + return roles diff --git a/public/js/startup.js b/public/js/startup.js index 0a6580be94..76f2c264c1 100644 --- a/public/js/startup.js +++ b/public/js/startup.js @@ -136,10 +136,7 @@ erpnext.startup.set_periodic_updates = function() { erpnext.hide_naming_series = function() { if(cur_frm.fields_dict.naming_series) { - hide_field('naming_series'); - if(cur_frm.doc.__islocal) { - unhide_field('naming_series'); - } + cur_frm.toggle_display("naming_series", cur_frm.doc.__islocal?true:false); } }