diff --git a/erpnext/docs/assets/img/human-resources/employee_promotion.png b/erpnext/docs/assets/img/human-resources/employee_promotion.png new file mode 100644 index 00000000000..d9ca321e5aa Binary files /dev/null and b/erpnext/docs/assets/img/human-resources/employee_promotion.png differ diff --git a/erpnext/docs/assets/img/human-resources/employee_promotion_1.png b/erpnext/docs/assets/img/human-resources/employee_promotion_1.png new file mode 100644 index 00000000000..a0bc9cc0e5b Binary files /dev/null and b/erpnext/docs/assets/img/human-resources/employee_promotion_1.png differ diff --git a/erpnext/docs/assets/img/human-resources/employee_transfer.png b/erpnext/docs/assets/img/human-resources/employee_transfer.png new file mode 100644 index 00000000000..edc641e2765 Binary files /dev/null and b/erpnext/docs/assets/img/human-resources/employee_transfer.png differ diff --git a/erpnext/docs/assets/img/human-resources/employee_transfer_1.png b/erpnext/docs/assets/img/human-resources/employee_transfer_1.png new file mode 100644 index 00000000000..f9f87e65f09 Binary files /dev/null and b/erpnext/docs/assets/img/human-resources/employee_transfer_1.png differ diff --git a/erpnext/docs/user/manual/en/human-resources/employee_promption.md b/erpnext/docs/user/manual/en/human-resources/employee_promption.md new file mode 100644 index 00000000000..a3f1c2d7c94 --- /dev/null +++ b/erpnext/docs/user/manual/en/human-resources/employee_promption.md @@ -0,0 +1,15 @@ +# Employee Promotion + +You can manage Employee Promotions using this document. + +To record an Employee Promotion go to + +> Human Resource > Employee Promotion > New Employee Promotion + +Select Employee and add all details to be updated to Promotion Details table. + +Employee Promotion + +Promotion document can be submitted on or after Promotion Date. Once submitted all the changes added to Promotion Details table will applied to Employee. + +Employee Promotion diff --git a/erpnext/docs/user/manual/en/human-resources/employee_transfer.md b/erpnext/docs/user/manual/en/human-resources/employee_transfer.md new file mode 100644 index 00000000000..307f9b9fedb --- /dev/null +++ b/erpnext/docs/user/manual/en/human-resources/employee_transfer.md @@ -0,0 +1,17 @@ +# Employee Transfer + +You can transfer Employees to different Company or Department by using Employee Transfer. + +To reocord an Employee Transfer go to + +> Human Resource > Employee Transfer > New Employee Transfer + +Select Employee and add all details to be updated to Transfer Details table. + +Employee Transfer + +Transfer document can be submitted on or after Transfer Date. Once submitted all the changes added to Transfer Details table will applied to Employee. + +Employee Transfer + +> Note : If Create New Employee ID is checked, a new Employee will be created with property changes in Transfer Details table and old Employee will be marked as releived. Leave allocations for the new Employee has to be manually created from Leave Period. diff --git a/erpnext/docs/user/manual/en/human-resources/index.txt b/erpnext/docs/user/manual/en/human-resources/index.txt index 479e2ddef6e..758cdaac4c2 100644 --- a/erpnext/docs/user/manual/en/human-resources/index.txt +++ b/erpnext/docs/user/manual/en/human-resources/index.txt @@ -18,4 +18,6 @@ human-resource-setup daily-work-summary fleet-management loan-management +employee-promotion +employee-transfer articles diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py index 0f116399aec..4cf28a16ecb 100755 --- a/erpnext/hr/doctype/employee/employee.py +++ b/erpnext/hr/doctype/employee/employee.py @@ -156,6 +156,9 @@ class Employee(NestedSet): def on_trash(self): self.update_nsm_model() delete_events(self.doctype, self.name) + if frappe.db.exists("Employee Transfer", {'new_employee_id': self.name, 'docstatus': 1}): + emp_transfer = frappe.get_doc("Employee Transfer", {'new_employee_id': self.name, 'docstatus': 1}) + emp_transfer.db_set("new_employee_id", '') def validate_preferred_email(self): if self.prefered_contact_email and not self.get(scrub(self.prefered_contact_email)): diff --git a/erpnext/hr/doctype/employee_promotion/employee_promotion.js b/erpnext/hr/doctype/employee_promotion/employee_promotion.js index c1bb7888e58..54e06f4581b 100644 --- a/erpnext/hr/doctype/employee_promotion/employee_promotion.js +++ b/erpnext/hr/doctype/employee_promotion/employee_promotion.js @@ -1,6 +1,8 @@ // Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors // For license information, please see license.txt +{% include 'erpnext/hr/employee_property_update.js' %} + frappe.ui.form.on('Employee Promotion', { refresh: function(frm) { diff --git a/erpnext/hr/doctype/employee_promotion/employee_promotion.json b/erpnext/hr/doctype/employee_promotion/employee_promotion.json index a7d49bcad36..1e3081a30c1 100644 --- a/erpnext/hr/doctype/employee_promotion/employee_promotion.json +++ b/erpnext/hr/doctype/employee_promotion/employee_promotion.json @@ -77,6 +77,36 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_3", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -102,7 +132,7 @@ "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, - "reqd": 0, + "reqd": 1, "search_index": 0, "set_only_once": 0, "translatable": 0, @@ -189,7 +219,7 @@ "label": "Employee Promotion Detail", "length": 0, "no_copy": 0, - "options": "Employee Promotion Detail", + "options": "Employee Property History", "permlevel": 0, "precision": "", "print_hide": 0, @@ -245,7 +275,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-04-14 15:42:49.452085", + "modified": "2018-04-27 17:31:26.902394", "modified_by": "Administrator", "module": "HR", "name": "Employee Promotion", diff --git a/erpnext/hr/doctype/employee_promotion/employee_promotion.py b/erpnext/hr/doctype/employee_promotion/employee_promotion.py index 564f1ad6ac6..5fcceedac21 100644 --- a/erpnext/hr/doctype/employee_promotion/employee_promotion.py +++ b/erpnext/hr/doctype/employee_promotion/employee_promotion.py @@ -4,7 +4,27 @@ from __future__ import unicode_literals import frappe +from frappe import _ from frappe.model.document import Document +from frappe.utils import getdate +from erpnext.hr.utils import update_employee class EmployeePromotion(Document): - pass + def validate(self): + if frappe.get_value("Employee", self.employee, "status") == "Left": + frappe.throw(_("Cannot promote Employee with status Left")) + + def before_submit(self): + if getdate(self.promotion_date) > getdate(): + frappe.throw(_("Employee Promotion cannot be submitted before Promotion Date "), + frappe.DocstatusTransitionError) + + def on_submit(self): + employee = frappe.get_doc("Employee", self.employee) + employee = update_employee(employee, self.promotion_details) + employee.save() + + def on_cancel(self): + employee = frappe.get_doc("Employee", self.employee) + employee = update_employee(employee, self.promotion_details, True) + employee.save() diff --git a/erpnext/hr/doctype/employee_promotion/test_employee_promotion.py b/erpnext/hr/doctype/employee_promotion/test_employee_promotion.py index 8b668e7390f..420bbe6b1a9 100644 --- a/erpnext/hr/doctype/employee_promotion/test_employee_promotion.py +++ b/erpnext/hr/doctype/employee_promotion/test_employee_promotion.py @@ -5,6 +5,31 @@ from __future__ import unicode_literals import frappe import unittest +from frappe.utils import getdate, add_days +from erpnext.hr.doctype.salary_structure.test_salary_structure import make_employee class TestEmployeePromotion(unittest.TestCase): - pass + def setUp(self): + self.employee = make_employee("employee@promotions.com") + frappe.db.sql("""delete from `tabEmployee Promotion`""") + + def test_submit_before_promotion_date(self): + promotion_obj = frappe.get_doc({ + "doctype": "Employee Promotion", + "employee": self.employee, + "promotion_details" :[ + { + "property": "Designation", + "current": "Software Developer", + "new": "Project Manager", + "fieldname": "designation" + } + ] + }) + promotion_obj.promotion_date = add_days(getdate(), 1) + promotion_obj.save() + self.assertRaises(frappe.DocstatusTransitionError, promotion_obj.submit) + promotion = frappe.get_doc("Employee Promotion", promotion_obj.name) + promotion.promotion_date = getdate() + promotion.submit() + self.assertEqual(promotion.docstatus, 1) diff --git a/erpnext/hr/doctype/employee_property_history/employee_property_history.json b/erpnext/hr/doctype/employee_property_history/employee_property_history.json index 7a416b2ed1b..0a515795499 100644 --- a/erpnext/hr/doctype/employee_property_history/employee_property_history.json +++ b/erpnext/hr/doctype/employee_property_history/employee_property_history.json @@ -34,13 +34,12 @@ "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, - "read_only": 0, + "read_only": 1, "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, "unique": 0 }, { @@ -65,13 +64,12 @@ "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, - "read_only": 0, + "read_only": 1, "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, "unique": 0 }, { @@ -96,13 +94,42 @@ "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, - "read_only": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "fieldname", + "fieldtype": "Data", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Field Name", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, "unique": 0 } ], @@ -116,7 +143,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2018-04-14 11:44:36.458039", + "modified": "2018-05-02 18:19:54.436391", "modified_by": "Administrator", "module": "HR", "name": "Employee Property History", diff --git a/erpnext/hr/doctype/employee_transfer/employee_transfer.js b/erpnext/hr/doctype/employee_transfer/employee_transfer.js index 1d694bdc41d..af751a7c054 100644 --- a/erpnext/hr/doctype/employee_transfer/employee_transfer.js +++ b/erpnext/hr/doctype/employee_transfer/employee_transfer.js @@ -1,6 +1,8 @@ // Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors // For license information, please see license.txt +{% include 'erpnext/hr/employee_property_update.js' %} + frappe.ui.form.on('Employee Transfer', { refresh: function(frm) { diff --git a/erpnext/hr/doctype/employee_transfer/employee_transfer.json b/erpnext/hr/doctype/employee_transfer/employee_transfer.json index 55fa073fa20..ace9f938705 100644 --- a/erpnext/hr/doctype/employee_transfer/employee_transfer.json +++ b/erpnext/hr/doctype/employee_transfer/employee_transfer.json @@ -42,7 +42,6 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, - "translatable": 0, "unique": 0 }, { @@ -74,7 +73,6 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, "unique": 0 }, { @@ -102,10 +100,38 @@ "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_3", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, "unique": 0 }, { @@ -137,7 +163,6 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, "unique": 0 }, { @@ -169,7 +194,6 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, "unique": 0 }, { @@ -200,7 +224,6 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, "unique": 0 }, { @@ -221,7 +244,7 @@ "label": "Employee Transfer Detail", "length": 0, "no_copy": 0, - "options": "Employee Transfer Detail", + "options": "Employee Property History", "permlevel": 0, "precision": "", "print_hide": 0, @@ -232,7 +255,6 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, - "translatable": 0, "unique": 0 }, { @@ -243,7 +265,7 @@ "columns": 0, "fieldname": "reallocate_leaves", "fieldtype": "Check", - "hidden": 0, + "hidden": 1, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, @@ -263,7 +285,6 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, "unique": 0 }, { @@ -294,7 +315,37 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "new_employee_id", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "New Employee ID", + "length": 0, + "no_copy": 0, + "options": "Employee", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 }, { @@ -325,7 +376,6 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, "unique": 0 } ], @@ -339,7 +389,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-04-14 15:42:31.098910", + "modified": "2018-05-05 13:10:32.660537", "modified_by": "Administrator", "module": "HR", "name": "Employee Transfer", @@ -348,6 +398,7 @@ "permissions": [ { "amend": 0, + "apply_user_permissions": 0, "cancel": 0, "create": 0, "delete": 0, @@ -367,6 +418,7 @@ }, { "amend": 0, + "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 0, @@ -386,6 +438,7 @@ }, { "amend": 1, + "apply_user_permissions": 0, "cancel": 1, "create": 1, "delete": 1, diff --git a/erpnext/hr/doctype/employee_transfer/employee_transfer.py b/erpnext/hr/doctype/employee_transfer/employee_transfer.py index 96645c4d697..d80e293bbba 100644 --- a/erpnext/hr/doctype/employee_transfer/employee_transfer.py +++ b/erpnext/hr/doctype/employee_transfer/employee_transfer.py @@ -4,7 +4,59 @@ from __future__ import unicode_literals import frappe +from frappe import _ from frappe.model.document import Document +from frappe.utils import getdate +from erpnext.hr.utils import update_employee class EmployeeTransfer(Document): - pass + def validate(self): + if frappe.get_value("Employee", self.employee, "status") == "Left": + frappe.throw(_("Cannot transfer Employee with status Left")) + + def before_submit(self): + if getdate(self.transfer_date) > getdate(): + frappe.throw(_("Employee Transfer cannot be submitted before Transfer Date "), + frappe.DocstatusTransitionError) + + def on_submit(self): + employee = frappe.get_doc("Employee", self.employee) + if self.create_new_employee_id: + new_employee = frappe.copy_doc(employee) + new_employee = update_employee(new_employee, self.transfer_details) + if self.new_company: + new_employee.company = self.new_company + #move user_id to new employee before insert + if employee.user_id and not self.validate_user_in_details(): + new_employee.user_id = employee.user_id + employee.db_set("user_id", "") + new_employee.insert() + self.db_set("new_employee_id", new_employee.name) + #relieve the old employee + employee.db_set("relieving_date", self.transfer_date) + employee.db_set("status", "Left") + else: + employee = update_employee(employee, self.transfer_details) + if self.new_company: + employee.company = self.new_company + employee.save() + + def on_cancel(self): + employee = frappe.get_doc("Employee", self.employee) + if self.create_new_employee_id: + if self.new_employee_id: + frappe.throw(_("Please delete the Employee {0}\ + to cancel this document").format(self.new_employee_id)) + #mark the employee as active + employee.status = "Active" + employee.relieving_date = '' + employee.save() + else: + employee = update_employee(employee, self.transfer_details, True) + employee.save() + + def validate_user_in_details(self): + for item in self.transfer_details: + if item.fieldname == "user_id" and item.new != item.current: + return True + return False diff --git a/erpnext/hr/doctype/employee_transfer/test_employee_transfer.py b/erpnext/hr/doctype/employee_transfer/test_employee_transfer.py index 049273e0cf4..3dae1a9840c 100644 --- a/erpnext/hr/doctype/employee_transfer/test_employee_transfer.py +++ b/erpnext/hr/doctype/employee_transfer/test_employee_transfer.py @@ -5,6 +5,52 @@ from __future__ import unicode_literals import frappe import unittest +from frappe.utils import getdate, add_days +from erpnext.hr.doctype.salary_structure.test_salary_structure import make_employee class TestEmployeeTransfer(unittest.TestCase): - pass + def setUp(self): + make_employee("employee2@transfers.com") + make_employee("employee3@transfers.com") + frappe.db.sql("""delete from `tabEmployee Transfer`""") + + def test_submit_before_transfer_date(self): + transfer_obj = frappe.get_doc({ + "doctype": "Employee Transfer", + "employee": frappe.get_value("Employee", {"user_id":"employee2@transfers.com"}, "name"), + "transfer_details" :[ + { + "property": "Designation", + "current": "Software Developer", + "new": "Project Manager", + "fieldname": "designation" + } + ] + }) + transfer_obj.transfer_date = add_days(getdate(), 1) + transfer_obj.save() + self.assertRaises(frappe.DocstatusTransitionError, transfer_obj.submit) + transfer = frappe.get_doc("Employee Transfer", transfer_obj.name) + transfer.transfer_date = getdate() + transfer.submit() + self.assertEqual(transfer.docstatus, 1) + + def test_new_employee_creation(self): + transfer = frappe.get_doc({ + "doctype": "Employee Transfer", + "employee": frappe.get_value("Employee", {"user_id":"employee3@transfers.com"}, "name"), + "create_new_employee_id": 1, + "transfer_date": getdate(), + "transfer_details" :[ + { + "property": "Designation", + "current": "Software Developer", + "new": "Project Manager", + "fieldname": "designation" + } + ] + }).insert() + transfer.submit() + self.assertTrue(transfer.new_employee_id) + self.assertEqual(frappe.get_value("Employee", transfer.new_employee_id, "status"), "Active") + self.assertEqual(frappe.get_value("Employee", transfer.employee, "status"), "Left") diff --git a/erpnext/hr/employee_property_update.js b/erpnext/hr/employee_property_update.js new file mode 100644 index 00000000000..473916ca42f --- /dev/null +++ b/erpnext/hr/employee_property_update.js @@ -0,0 +1,147 @@ +frappe.ui.form.on(cur_frm.doctype, { + setup: function(frm) { + frm.set_query("employee", function() { + return { + filters: { + "status": "Active" + } + }; + }); + }, + onload: function(frm){ + if(frm.doc.__islocal){ + if(frm.doctype == "Employee Promotion"){ + frm.doc.promotion_details = []; + }else if (frm.doctype == "Employee Transfer") { + frm.doc.transfer_details = []; + } + } + }, + employee: function(frm) { + frm.add_fetch("employee", "company", "company"); + }, + refresh: function(frm) { + var table; + if(frm.doctype == "Employee Promotion"){ + table = "promotion_details"; + }else if (frm.doctype == "Employee Transfer") { + table = "transfer_details"; + } + if(!table){return;} + cur_frm.fields_dict[table].grid.wrapper.find('.grid-add-row').hide(); + cur_frm.fields_dict[table].grid.add_custom_button(__('Add Row'), () => { + if(!frm.doc.employee){ + frappe.msgprint(__("Please select Employee")); + return; + } + frappe.call({ + method: 'erpnext.hr.utils.get_employee_fields_label', + callback: function(r) { + if(r.message){ + show_dialog(frm, table, r.message); + } + } + }); + }); + } +}); + +var show_dialog = function(frm, table, field_labels) { + var d = new frappe.ui.Dialog({ + title: "Update Property", + fields: [ + {fieldname: "property", label: __('Select Property'), fieldtype:"Select", options: field_labels}, + {fieldname: "current", fieldtype: "Data", label:__('Current'), read_only: true}, + {fieldname: "field_html", fieldtype: "HTML"} + ], + primary_action_label: __('Add to Details'), + primary_action: () => { + d.get_primary_btn().attr('disabled', true); + if(d.data){ + add_to_details(frm, d, table); + } + } + }); + d.fields_dict["property"].df.onchange = () => { + let property = d.get_values().property; + d.data.fieldname = property; + if(!property){return;} + frappe.call({ + method: 'erpnext.hr.utils.get_employee_field_property', + args: {employee: frm.doc.employee, fieldname: property}, + callback: function(r) { + if(r.message){ + d.data.current = r.message.value; + d.data.property = r.message.label; + d.fields_dict.field_html.$wrapper.html(""); + d.set_value('current', r.message.value); + render_dynamic_field(d, r.message.datatype, r.message.options, property); + d.get_primary_btn().attr('disabled', false); + } + } + }); + }; + d.get_primary_btn().attr('disabled', true); + d.data = {}; + d.show(); +}; + +var render_dynamic_field = function(d, fieldtype, options, fieldname) { + d.data.new = null; + var dynamic_field = frappe.ui.form.make_control({ + df: { + "fieldtype": fieldtype, + "fieldname": fieldname, + "options": options || '' + }, + parent: d.fields_dict.field_html.wrapper, + only_input: false + }); + dynamic_field.make_input(); + $(dynamic_field.label_area).text(__("New")); + dynamic_field.$input.on("change", function(e) { + d.data.new = e.target.value; + }).on("awesomplete-close", function(e) { + d.data.new = e.target.value; + }); +}; + +var add_to_details = function(frm, d, table) { + let data = d.data; + if(data.fieldname){ + if(validate_duplicate(frm, table, data.fieldname)){ + frappe.show_alert({message:__("Property already added"), indicator:'orange'}); + return false; + } + if(data.current == data.new){ + frappe.show_alert({message:__("Nothing to change"), indicator:'orange'}); + d.get_primary_btn().attr('disabled', false); + return false; + } + frm.add_child(table, { + fieldname: data.fieldname, + property: data.property, + current: data.current, + new: data.new + }); + frm.refresh_field(table); + d.fields_dict.field_html.$wrapper.html(""); + d.set_value("property", ""); + d.set_value('current', ""); + frappe.show_alert({message:__("Added to details"),indicator:'green'}); + d.data = {}; + }else { + frappe.show_alert({message:__("Value missing"),indicator:'red'}); + } +}; + +var validate_duplicate = function(frm, table, fieldname){ + let duplicate = false; + $.each(frm.doc[table], function(i, detail) { + if(detail.fieldname === fieldname){ + duplicate = true; + return; + } + }); + return duplicate; +}; diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py index aa456aac60e..057f406e805 100644 --- a/erpnext/hr/utils.py +++ b/erpnext/hr/utils.py @@ -4,7 +4,48 @@ from __future__ import unicode_literals import frappe from frappe import _ +from frappe.utils import formatdate, format_datetime +from frappe.utils import getdate, get_datetime def set_employee_name(doc): if doc.employee and not doc.employee_name: doc.employee_name = frappe.db.get_value("Employee", doc.employee, "employee_name") + +@frappe.whitelist() +def get_employee_fields_label(): + fields = [] + for df in frappe.get_meta("Employee").get("fields"): + if df.fieldtype in ["Data", "Date", "Datetime", "Float", "Int", + "Link", "Percent", "Select", "Small Text"] and df.fieldname not in ["lft", "rgt", "old_parent"]: + fields.append({"value": df.fieldname, "label": df.label}) + return fields + +@frappe.whitelist() +def get_employee_field_property(employee, fieldname): + if employee and fieldname: + field = frappe.get_meta("Employee").get_field(fieldname) + value = frappe.db.get_value("Employee", employee, fieldname) + options = field.options + if field.fieldtype == "Date": + value = formatdate(value) + elif field.fieldtype == "Datetime": + value = format_datetime(value) + return { + "value" : value, + "datatype" : field.fieldtype, + "label" : field.label, + "options" : options + } + else: + return False + +def update_employee(employee, details, cancel=False): + for item in details: + fieldtype = frappe.get_meta("Employee").get_field(item.fieldname).fieldtype + new_data = item.new if not cancel else item.current + if fieldtype == "Date" and new_data: + new_data = getdate(new_data) + elif fieldtype =="Datetime" and new_data: + new_data = get_datetime(new_data) + setattr(employee, item.fieldname, new_data) + return employee