From cf2e6c6c08e85836f489653e2cad5cd159911dfd Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Sat, 9 Apr 2022 13:15:37 +0530 Subject: [PATCH 1/9] fix: remove hardcoded employee fields that can be updated via Promotion --- .../employee_promotion.json | 491 ++++-------------- erpnext/hr/employee_property_update.js | 75 +-- erpnext/hr/utils.py | 23 - 3 files changed, 158 insertions(+), 431 deletions(-) diff --git a/erpnext/hr/doctype/employee_promotion/employee_promotion.json b/erpnext/hr/doctype/employee_promotion/employee_promotion.json index e0fbd23be4a..65f53b219a2 100644 --- a/erpnext/hr/doctype/employee_promotion/employee_promotion.json +++ b/erpnext/hr/doctype/employee_promotion/employee_promotion.json @@ -1,397 +1,134 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "HR-EMP-PRO-.YYYY.-.#####", - "beta": 0, - "creation": "2018-04-13 18:33:59.476562", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "actions": [], + "autoname": "HR-EMP-PRO-.YYYY.-.#####", + "creation": "2018-04-13 18:33:59.476562", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "employee", + "employee_name", + "department", + "column_break_3", + "promotion_date", + "company", + "details_section", + "promotion_details", + "amended_from" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "employee", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Employee", - "length": 0, - "no_copy": 0, - "options": "Employee", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "employee", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Employee", + "options": "Employee", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "employee.employee_name", - "fieldname": "employee_name", - "fieldtype": "Data", - "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": "Employee Name", - "length": 0, - "no_copy": 0, - "options": "", - "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 - }, + "fetch_from": "employee.employee_name", + "fieldname": "employee_name", + "fieldtype": "Data", + "label": "Employee Name", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "employee.department", - "fieldname": "department", - "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": "Department", - "length": 0, - "no_copy": 0, - "options": "Department", - "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 - }, + "fetch_from": "employee.department", + "fieldname": "department", + "fieldtype": "Link", + "label": "Department", + "options": "Department", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 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 - }, + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "promotion_date", - "fieldtype": "Date", - "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": "Promotion Date", - "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": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "promotion_date", + "fieldtype": "Date", + "label": "Promotion Date", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_from": "employee.company", - "fieldname": "company", - "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": "Company", - "length": 0, - "no_copy": 0, - "options": "Company", - "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 - }, + "fetch_from": "employee.company", + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "options": "Company" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "details_section", - "fieldtype": "Section 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, - "label": "Employee Promotion Details", - "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 - }, + "description": "Set the properties that should be updated in the Employee master on promotion submission", + "fieldname": "details_section", + "fieldtype": "Section Break", + "label": "Employee Promotion Details" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "promotion_details", - "fieldtype": "Table", - "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": "Employee Promotion Detail", - "length": 0, - "no_copy": 0, - "options": "Employee Property History", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "promotion_details", + "fieldtype": "Table", + "options": "Employee Property History", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "amended_from", - "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": "Amended From", - "length": 0, - "no_copy": 1, - "options": "Employee Promotion", - "permlevel": 0, - "print_hide": 1, - "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 + "fieldname": "amended_from", + "fieldtype": "Link", + "label": "Amended From", + "no_copy": 1, + "options": "Employee Promotion", + "print_hide": 1, + "read_only": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 1, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-08-21 16:15:40.284987", - "modified_by": "Administrator", - "module": "HR", - "name": "Employee Promotion", - "name_case": "", - "owner": "Administrator", + ], + "is_submittable": 1, + "links": [], + "modified": "2022-04-09 12:24:07.667237", + "modified_by": "Administrator", + "module": "HR", + "name": "Employee Promotion", + "naming_rule": "Expression (old style)", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Employee", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 0 - }, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Employee", + "share": 1 + }, { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 0, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "HR User", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "create": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "HR User", + "share": 1, + "submit": 1, "write": 1 - }, + }, { - "amend": 1, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "HR Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "HR Manager", + "share": 1, + "submit": 1, "write": 1 } - ], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "employee_name", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + ], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "states": [], + "title_field": "employee_name", + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/hr/employee_property_update.js b/erpnext/hr/employee_property_update.js index 60d06b41f07..97959ce2d96 100644 --- a/erpnext/hr/employee_property_update.js +++ b/erpnext/hr/employee_property_update.js @@ -8,39 +8,48 @@ frappe.ui.form.on(cur_frm.doctype, { }; }); }, - 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"){ + let table; + if (frm.doctype == "Employee Promotion") { table = "promotion_details"; - }else if (frm.doctype == "Employee Transfer") { + } 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")); + + if (!table) + return; + + frm.fields_dict[table].grid.wrapper.find(".grid-add-row").hide(); + frm.events.setup_employee_property_button(frm, table) + }, + + setup_employee_property_button: function(frm, table) { + frm.fields_dict[table].grid.add_custom_button(__("Add Employee Property"), () => { + if (!frm.doc.employee) { + frappe.msgprint(__("Please select Employee first.")); return; } - frappe.call({ - method: 'erpnext.hr.utils.get_employee_fields_label', - callback: function(r) { - if(r.message){ - show_dialog(frm, table, r.message); + + const allowed_fields = []; + const exclude_fields = ["naming_series", "employee", "first_name", "middle_name", "last_name", + "employee_name", "status", "image", "gender", "date_of_birth", "date_of_joining", "lft", "rgt", "old_parent"]; + + const exclude_field_types = ["HTML", "Section Break", "Column Break", "Button", "Read Only", "Tab Break", "Table"]; + + frappe.model.with_doctype("Employee", () => { + const field_label_map = {}; + frappe.get_meta("Employee").fields.forEach(d => { + field_label_map[d.fieldname] = __(d.label) + ` (${d.fieldname})`; + if (!in_list(exclude_field_types, d.fieldtype) && !in_list(exclude_fields, d.fieldname)) { + allowed_fields.push({ + label: field_label_map[d.fieldname], + value: d.fieldname, + }); } - } + }); + + show_dialog(frm, table, allowed_fields) }); }); } @@ -50,14 +59,14 @@ 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: "property", label: __("Select Property"), fieldtype: "Autocomplete", 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_label: __("Add to Details"), primary_action: () => { - d.get_primary_btn().attr('disabled', true); - if(d.data) { + d.get_primary_btn().attr("disabled", true); + if (d.data) { var input = $('[data-fieldname="field_html"] input'); d.data.new = input.val(); $(input).remove(); @@ -65,6 +74,7 @@ var show_dialog = function(frm, table, field_labels) { } } }); + d.fields_dict["property"].df.onchange = () => { let property = d.get_values().property; d.data.fieldname = property; @@ -123,6 +133,9 @@ var add_to_details = function(frm, d, table) { new: data.new }); frm.refresh_field(table); + + frm.fields_dict[table].grid.wrapper.find(".grid-add-row").hide(); + d.fields_dict.field_html.$wrapper.html(""); d.set_value("property", ""); d.set_value('current', ""); diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py index fd69a9b4f1d..3f15011a4fb 100644 --- a/erpnext/hr/utils.py +++ b/erpnext/hr/utils.py @@ -88,29 +88,6 @@ def delete_employee_work_history(details, employee, date): frappe.db.delete("Employee Internal Work History", filters) -@frappe.whitelist() -def get_employee_fields_label(): - fields = [] - for df in frappe.get_meta("Employee").get("fields"): - if df.fieldname in [ - "salutation", - "user_id", - "employee_number", - "employment_type", - "holiday_list", - "branch", - "department", - "designation", - "grade", - "notice_number_of_days", - "reports_to", - "leave_policy", - "company_email", - ]: - fields.append({"value": df.fieldname, "label": df.label}) - return fields - - @frappe.whitelist() def get_employee_field_property(employee, fieldname): if employee and fieldname: From c3dc5d5ce7d00f83972256e02e6fd8ced0678f2d Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Thu, 21 Apr 2022 08:17:00 +0530 Subject: [PATCH 2/9] fix: property addition not working for select fields --- erpnext/hr/employee_property_update.js | 39 ++++++++++++++++---------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/erpnext/hr/employee_property_update.js b/erpnext/hr/employee_property_update.js index 97959ce2d96..f22fc4dfc2a 100644 --- a/erpnext/hr/employee_property_update.js +++ b/erpnext/hr/employee_property_update.js @@ -9,6 +9,16 @@ frappe.ui.form.on(cur_frm.doctype, { }); }, + onload: function(frm){ + if (frm.doc.__islocal) { + if (frm.doctype == "Employee Promotion") { + frm.clear_table("promotion_details"); + } else if (frm.doctype == "Employee Transfer") { + frm.clear_table("transfer_details"); + } + } + }, + refresh: function(frm) { let table; if (frm.doctype == "Employee Promotion") { @@ -32,7 +42,7 @@ frappe.ui.form.on(cur_frm.doctype, { } const allowed_fields = []; - const exclude_fields = ["naming_series", "employee", "first_name", "middle_name", "last_name", + const exclude_fields = ["naming_series", "employee", "first_name", "middle_name", "last_name", "marital_status", "employee_name", "status", "image", "gender", "date_of_birth", "date_of_joining", "lft", "rgt", "old_parent"]; const exclude_field_types = ["HTML", "Section Break", "Column Break", "Button", "Read Only", "Tab Break", "Table"]; @@ -60,16 +70,14 @@ var show_dialog = function(frm, table, field_labels) { title: "Update Property", fields: [ {fieldname: "property", label: __("Select Property"), fieldtype: "Autocomplete", options: field_labels}, - {fieldname: "current", fieldtype: "Data", label:__("Current"), read_only: true}, - {fieldname: "field_html", fieldtype: "HTML"} + {fieldname: "current", fieldtype: "Data", label: __("Current"), read_only: true}, + {fieldname: "new_value", fieldtype: "Data", label: __("New")} ], primary_action_label: __("Add to Details"), primary_action: () => { d.get_primary_btn().attr("disabled", true); if (d.data) { - var input = $('[data-fieldname="field_html"] input'); - d.data.new = input.val(); - $(input).remove(); + d.data.new = d.get_values().new_value; add_to_details(frm, d, table); } } @@ -86,7 +94,7 @@ var show_dialog = function(frm, table, field_labels) { 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); @@ -105,18 +113,19 @@ var render_dynamic_field = function(d, fieldtype, options, fieldname) { df: { "fieldtype": fieldtype, "fieldname": fieldname, - "options": options || '' + "options": options || '', + "label": __("New") }, - parent: d.fields_dict.field_html.wrapper, + parent: d.fields_dict.new_value.wrapper, only_input: false }); dynamic_field.make_input(); - $(dynamic_field.label_area).text(__("New")); + d.replace_field("new_value", dynamic_field.df); }; var add_to_details = function(frm, d, table) { let data = d.data; - if(data.fieldname){ + if (data.fieldname) { if(validate_duplicate(frm, table, data.fieldname)){ frappe.show_alert({message:__("Property already added"), indicator:'orange'}); return false; @@ -136,12 +145,12 @@ var add_to_details = function(frm, d, table) { frm.fields_dict[table].grid.wrapper.find(".grid-add-row").hide(); - d.fields_dict.field_html.$wrapper.html(""); + d.fields_dict.new_value.$wrapper.html(""); d.set_value("property", ""); - d.set_value('current', ""); - frappe.show_alert({message:__("Added to details"),indicator:'green'}); + d.set_value("current", ""); + frappe.show_alert({message:__("Added to details"), indicator:'green'}); d.data = {}; - }else { + } else { frappe.show_alert({message:__("Value missing"),indicator:'red'}); } }; From a93867de1912a225a6b6851efc1301ffec6ff924 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Fri, 22 Apr 2022 16:28:14 +0530 Subject: [PATCH 3/9] feat: add CTC fields in Employee master and Promotion --- erpnext/hr/doctype/employee/employee.json | 18 ++++++++- .../employee_promotion.json | 39 ++++++++++++++++++- .../employee_promotion/employee_promotion.py | 4 ++ 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/erpnext/hr/doctype/employee/employee.json b/erpnext/hr/doctype/employee/employee.json index d592a9c79e2..e3358bf81f7 100644 --- a/erpnext/hr/doctype/employee/employee.json +++ b/erpnext/hr/doctype/employee/employee.json @@ -62,6 +62,8 @@ "holiday_list", "default_shift", "salary_information", + "salary_currency", + "ctc", "salary_mode", "payroll_cost_center", "column_break_52", @@ -807,17 +809,30 @@ "fieldtype": "Link", "label": "Shift Request Approver", "options": "User" + }, + { + "fieldname": "salary_currency", + "fieldtype": "Link", + "label": "Salary Currency", + "options": "Currency" + }, + { + "fieldname": "ctc", + "fieldtype": "Currency", + "label": "Cost to Company (CTC)", + "options": "salary_currency" } ], "icon": "fa fa-user", "idx": 24, "image_field": "image", "links": [], - "modified": "2021-06-17 11:31:37.730760", + "modified": "2022-04-22 16:21:55.811983", "modified_by": "Administrator", "module": "HR", "name": "Employee", "name_case": "Title Case", + "naming_rule": "By \"Naming Series\" field", "owner": "Administrator", "permissions": [ { @@ -859,5 +874,6 @@ "show_name_in_global_search": 1, "sort_field": "modified", "sort_order": "DESC", + "states": [], "title_field": "employee_name" } \ No newline at end of file diff --git a/erpnext/hr/doctype/employee_promotion/employee_promotion.json b/erpnext/hr/doctype/employee_promotion/employee_promotion.json index 65f53b219a2..64be96bd95a 100644 --- a/erpnext/hr/doctype/employee_promotion/employee_promotion.json +++ b/erpnext/hr/doctype/employee_promotion/employee_promotion.json @@ -9,11 +9,16 @@ "employee", "employee_name", "department", + "salary_currency", "column_break_3", "promotion_date", "company", "details_section", "promotion_details", + "salary_details_section", + "current_ctc", + "column_break_12", + "revised_ctc", "amended_from" ], "fields": [ @@ -77,11 +82,43 @@ "options": "Employee Promotion", "print_hide": 1, "read_only": 1 + }, + { + "fieldname": "salary_details_section", + "fieldtype": "Section Break", + "label": "Salary Details" + }, + { + "fieldname": "column_break_12", + "fieldtype": "Column Break" + }, + { + "fetch_from": "employee.salary_currency", + "fieldname": "salary_currency", + "fieldtype": "Link", + "label": "Salary Currency", + "options": "Currency", + "read_only": 1 + }, + { + "fetch_from": "employee.ctc", + "fetch_if_empty": 1, + "fieldname": "current_ctc", + "fieldtype": "Currency", + "label": "Current CTC", + "options": "salary_currency" + }, + { + "depends_on": "current_ctc", + "fieldname": "revised_ctc", + "fieldtype": "Currency", + "label": "Revised CTC", + "options": "salary_currency" } ], "is_submittable": 1, "links": [], - "modified": "2022-04-09 12:24:07.667237", + "modified": "2022-04-22 16:26:46.933791", "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 d77c1dddfd0..f3d27d0832e 100644 --- a/erpnext/hr/doctype/employee_promotion/employee_promotion.py +++ b/erpnext/hr/doctype/employee_promotion/employee_promotion.py @@ -26,6 +26,10 @@ class EmployeePromotion(Document): employee = update_employee_work_history( employee, self.promotion_details, date=self.promotion_date ) + + if self.revised_ctc: + employee.ctc = self.revised_ctc + employee.save() def on_cancel(self): From 833a33a94b73b948ef72aace235cd078808cc3f1 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Fri, 22 Apr 2022 16:28:25 +0530 Subject: [PATCH 4/9] test: employee property update via Employee Promotion --- .../test_employee_promotion.py | 72 ++++++++++++++++--- 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/erpnext/hr/doctype/employee_promotion/test_employee_promotion.py b/erpnext/hr/doctype/employee_promotion/test_employee_promotion.py index 06825ece910..c2ffcfeae13 100644 --- a/erpnext/hr/doctype/employee_promotion/test_employee_promotion.py +++ b/erpnext/hr/doctype/employee_promotion/test_employee_promotion.py @@ -4,21 +4,22 @@ import unittest import frappe +from frappe.tests.utils import FrappeTestCase from frappe.utils import add_days, getdate from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_employee -class TestEmployeePromotion(unittest.TestCase): +class TestEmployeePromotion(FrappeTestCase): def setUp(self): - self.employee = make_employee("employee@promotions.com") - frappe.db.sql("""delete from `tabEmployee Promotion`""") + frappe.db.delete("Employee Promotion") def test_submit_before_promotion_date(self): - promotion_obj = frappe.get_doc( + employee = make_employee("employee@promotions.com") + promotion = frappe.get_doc( { "doctype": "Employee Promotion", - "employee": self.employee, + "employee": employee, "promotion_details": [ { "property": "Designation", @@ -29,10 +30,63 @@ class TestEmployeePromotion(unittest.TestCase): ], } ) - 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 = add_days(getdate(), 1) + self.assertRaises(frappe.DocstatusTransitionError, promotion.submit) + promotion.promotion_date = getdate() promotion.submit() self.assertEqual(promotion.docstatus, 1) + + def test_employee_history(self): + for grade in ["L1", "L2"]: + frappe.get_doc({"doctype": "Employee Grade", "__newname": grade}).insert() + + employee = make_employee( + "test_employee_promotion@example.com", + company="Test Company", + date_of_birth=getdate("30-09-1980"), + date_of_joining=getdate("01-10-2021"), + designation="Software Developer", + grade="L1", + salary_currency="INR", + annual_ctc="500000", + ) + + promotion = frappe.get_doc( + { + "doctype": "Employee Promotion", + "employee": employee, + "promotion_date": getdate(), + "revised_annual_ctc": "1000000", + "promotion_details": [ + { + "property": "Designation", + "current": "Software Developer", + "new": "Project Manager", + "fieldname": "designation", + }, + {"property": "Grade", "current": "L1", "new": "L2", "fieldname": "grade"}, + ], + } + ).submit() + + # employee fields updated + employee = frappe.get_doc("Employee", employee) + self.assertEqual(employee.grade, "L2") + self.assertEqual(employee.designation, "Project Manager") + self.assertEqual(employee.annual_ctc, 1000000) + + # internal work history updated + self.assertEqual(employee.internal_work_history[0].designation, "Software Developer") + self.assertEqual(employee.internal_work_history[0].from_date, getdate("01-10-2021")) + + self.assertEqual(employee.internal_work_history[1].designation, "Project Manager") + self.assertEqual(employee.internal_work_history[1].from_date, getdate()) + + promotion.cancel() + employee.reload() + + # internal work history updated on cancellation + self.assertEqual(len(employee.internal_work_history), 1) + self.assertEqual(employee.internal_work_history[0].designation, "Software Developer") + self.assertEqual(employee.internal_work_history[0].from_date, getdate("01-10-2021")) From 788e0a1c6cc09cf5b1e70012c9fd14c2684aa84b Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Fri, 22 Apr 2022 17:25:37 +0530 Subject: [PATCH 5/9] chore: format `employee_property_update.js` --- erpnext/hr/employee_property_update.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/erpnext/hr/employee_property_update.js b/erpnext/hr/employee_property_update.js index f22fc4dfc2a..3c958f5d872 100644 --- a/erpnext/hr/employee_property_update.js +++ b/erpnext/hr/employee_property_update.js @@ -9,7 +9,7 @@ frappe.ui.form.on(cur_frm.doctype, { }); }, - onload: function(frm){ + onload: function(frm) { if (frm.doc.__islocal) { if (frm.doctype == "Employee Promotion") { frm.clear_table("promotion_details"); @@ -31,7 +31,7 @@ frappe.ui.form.on(cur_frm.doctype, { return; frm.fields_dict[table].grid.wrapper.find(".grid-add-row").hide(); - frm.events.setup_employee_property_button(frm, table) + frm.events.setup_employee_property_button(frm, table); }, setup_employee_property_button: function(frm, table) { @@ -59,7 +59,7 @@ frappe.ui.form.on(cur_frm.doctype, { } }); - show_dialog(frm, table, allowed_fields) + show_dialog(frm, table, allowed_fields); }); }); } @@ -91,7 +91,7 @@ var show_dialog = function(frm, table, field_labels) { method: 'erpnext.hr.utils.get_employee_field_property', args: {employee: frm.doc.employee, fieldname: property}, callback: function(r) { - if(r.message){ + if (r.message) { d.data.current = r.message.value; d.data.property = r.message.label; @@ -126,13 +126,13 @@ var render_dynamic_field = function(d, fieldtype, options, fieldname) { 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'}); + 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); + 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, { @@ -148,10 +148,10 @@ var add_to_details = function(frm, d, table) { d.fields_dict.new_value.$wrapper.html(""); d.set_value("property", ""); d.set_value("current", ""); - frappe.show_alert({message:__("Added to details"), indicator:'green'}); + frappe.show_alert({message: __("Added to details"), indicator: "green"}); d.data = {}; } else { - frappe.show_alert({message:__("Value missing"),indicator:'red'}); + frappe.show_alert({message: __("Value missing"), indicator: "red"}); } }; From 9b93c63830276de272c94e90d2567d3035c29e94 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Fri, 22 Apr 2022 17:54:32 +0530 Subject: [PATCH 6/9] fix: tests --- .../doctype/employee_promotion/test_employee_promotion.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/hr/doctype/employee_promotion/test_employee_promotion.py b/erpnext/hr/doctype/employee_promotion/test_employee_promotion.py index c2ffcfeae13..9eb064eb225 100644 --- a/erpnext/hr/doctype/employee_promotion/test_employee_promotion.py +++ b/erpnext/hr/doctype/employee_promotion/test_employee_promotion.py @@ -43,7 +43,7 @@ class TestEmployeePromotion(FrappeTestCase): employee = make_employee( "test_employee_promotion@example.com", - company="Test Company", + company="_Test Company", date_of_birth=getdate("30-09-1980"), date_of_joining=getdate("01-10-2021"), designation="Software Developer", @@ -57,7 +57,7 @@ class TestEmployeePromotion(FrappeTestCase): "doctype": "Employee Promotion", "employee": employee, "promotion_date": getdate(), - "revised_annual_ctc": "1000000", + "revised_ctc": "1000000", "promotion_details": [ { "property": "Designation", @@ -74,7 +74,7 @@ class TestEmployeePromotion(FrappeTestCase): employee = frappe.get_doc("Employee", employee) self.assertEqual(employee.grade, "L2") self.assertEqual(employee.designation, "Project Manager") - self.assertEqual(employee.annual_ctc, 1000000) + self.assertEqual(employee.ctc, 1000000) # internal work history updated self.assertEqual(employee.internal_work_history[0].designation, "Software Developer") From cfa4dfe7a8a5a2b41bb56e787922a5bd07a52ce8 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Fri, 22 Apr 2022 20:20:04 +0530 Subject: [PATCH 7/9] fix: reset old CTC on promotion cancellation --- .../hr/doctype/employee_promotion/employee_promotion.json | 3 ++- .../hr/doctype/employee_promotion/employee_promotion.py | 4 ++++ .../doctype/employee_promotion/test_employee_promotion.py | 7 ++++++- erpnext/hr/employee_property_update.js | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/erpnext/hr/doctype/employee_promotion/employee_promotion.json b/erpnext/hr/doctype/employee_promotion/employee_promotion.json index 64be96bd95a..173573e2030 100644 --- a/erpnext/hr/doctype/employee_promotion/employee_promotion.json +++ b/erpnext/hr/doctype/employee_promotion/employee_promotion.json @@ -106,6 +106,7 @@ "fieldname": "current_ctc", "fieldtype": "Currency", "label": "Current CTC", + "mandatory_depends_on": "revised_ctc", "options": "salary_currency" }, { @@ -118,7 +119,7 @@ ], "is_submittable": 1, "links": [], - "modified": "2022-04-22 16:26:46.933791", + "modified": "2022-04-22 18:47:10.168744", "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 f3d27d0832e..8c802e99918 100644 --- a/erpnext/hr/doctype/employee_promotion/employee_promotion.py +++ b/erpnext/hr/doctype/employee_promotion/employee_promotion.py @@ -35,4 +35,8 @@ class EmployeePromotion(Document): def on_cancel(self): employee = frappe.get_doc("Employee", self.employee) employee = update_employee_work_history(employee, self.promotion_details, cancel=True) + + if self.revised_ctc: + employee.ctc = self.current_ctc + 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 9eb064eb225..71bb1a62c18 100644 --- a/erpnext/hr/doctype/employee_promotion/test_employee_promotion.py +++ b/erpnext/hr/doctype/employee_promotion/test_employee_promotion.py @@ -49,7 +49,7 @@ class TestEmployeePromotion(FrappeTestCase): designation="Software Developer", grade="L1", salary_currency="INR", - annual_ctc="500000", + ctc="500000", ) promotion = frappe.get_doc( @@ -86,6 +86,11 @@ class TestEmployeePromotion(FrappeTestCase): promotion.cancel() employee.reload() + # fields restored + self.assertEqual(employee.grade, "L1") + self.assertEqual(employee.designation, "Software Developer") + self.assertEqual(employee.ctc, 500000) + # internal work history updated on cancellation self.assertEqual(len(employee.internal_work_history), 1) self.assertEqual(employee.internal_work_history[0].designation, "Software Developer") diff --git a/erpnext/hr/employee_property_update.js b/erpnext/hr/employee_property_update.js index 3c958f5d872..b11683347c2 100644 --- a/erpnext/hr/employee_property_update.js +++ b/erpnext/hr/employee_property_update.js @@ -42,7 +42,7 @@ frappe.ui.form.on(cur_frm.doctype, { } const allowed_fields = []; - const exclude_fields = ["naming_series", "employee", "first_name", "middle_name", "last_name", "marital_status", + const exclude_fields = ["naming_series", "employee", "first_name", "middle_name", "last_name", "marital_status", "ctc", "employee_name", "status", "image", "gender", "date_of_birth", "date_of_joining", "lft", "rgt", "old_parent"]; const exclude_field_types = ["HTML", "Section Break", "Column Break", "Button", "Read Only", "Tab Break", "Table"]; From 9d158088ee1ffb48e4683e1beca7e2a1352b0ea3 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Fri, 22 Apr 2022 20:20:12 +0530 Subject: [PATCH 8/9] chore: remove unused Employee Transfer Property doctype --- .../employee_transfer_property/__init__.py | 0 .../employee_transfer_property.js | 8 - .../employee_transfer_property.json | 154 ------------------ .../employee_transfer_property.py | 9 - .../test_employee_transfer_property.py | 8 - erpnext/patches.txt | 1 + ...lete_employee_transfer_property_doctype.py | 5 + 7 files changed, 6 insertions(+), 179 deletions(-) delete mode 100644 erpnext/hr/doctype/employee_transfer_property/__init__.py delete mode 100644 erpnext/hr/doctype/employee_transfer_property/employee_transfer_property.js delete mode 100644 erpnext/hr/doctype/employee_transfer_property/employee_transfer_property.json delete mode 100644 erpnext/hr/doctype/employee_transfer_property/employee_transfer_property.py delete mode 100644 erpnext/hr/doctype/employee_transfer_property/test_employee_transfer_property.py create mode 100644 erpnext/patches/v14_0/delete_employee_transfer_property_doctype.py diff --git a/erpnext/hr/doctype/employee_transfer_property/__init__.py b/erpnext/hr/doctype/employee_transfer_property/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/hr/doctype/employee_transfer_property/employee_transfer_property.js b/erpnext/hr/doctype/employee_transfer_property/employee_transfer_property.js deleted file mode 100644 index 9987c82d417..00000000000 --- a/erpnext/hr/doctype/employee_transfer_property/employee_transfer_property.js +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Employee Transfer Property', { - refresh: function(frm) { - - } -}); diff --git a/erpnext/hr/doctype/employee_transfer_property/employee_transfer_property.json b/erpnext/hr/doctype/employee_transfer_property/employee_transfer_property.json deleted file mode 100644 index 829169ddd66..00000000000 --- a/erpnext/hr/doctype/employee_transfer_property/employee_transfer_property.json +++ /dev/null @@ -1,154 +0,0 @@ -{ - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2018-04-13 18:24:30.579965", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", - "fields": [ - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "property", - "fieldtype": "Data", - "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": "Property", - "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, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "current", - "fieldtype": "Data", - "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": "Current", - "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, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "new", - "fieldtype": "Data", - "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", - "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 - } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-04-13 18:25:54.889579", - "modified_by": "Administrator", - "module": "HR", - "name": "Employee Transfer Property", - "name_case": "", - "owner": "Administrator", - "permissions": [ - { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - } - ], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0 -} \ No newline at end of file diff --git a/erpnext/hr/doctype/employee_transfer_property/employee_transfer_property.py b/erpnext/hr/doctype/employee_transfer_property/employee_transfer_property.py deleted file mode 100644 index 76e200602f5..00000000000 --- a/erpnext/hr/doctype/employee_transfer_property/employee_transfer_property.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - - -from frappe.model.document import Document - - -class EmployeeTransferProperty(Document): - pass diff --git a/erpnext/hr/doctype/employee_transfer_property/test_employee_transfer_property.py b/erpnext/hr/doctype/employee_transfer_property/test_employee_transfer_property.py deleted file mode 100644 index 981d46f57d2..00000000000 --- a/erpnext/hr/doctype/employee_transfer_property/test_employee_transfer_property.py +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt - -import unittest - - -class TestEmployeeTransferProperty(unittest.TestCase): - pass diff --git a/erpnext/patches.txt b/erpnext/patches.txt index c290551b730..d163ca52f5a 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -365,3 +365,4 @@ erpnext.patches.v13_0.remove_unknown_links_to_prod_plan_items # 24-03-2022 erpnext.patches.v13_0.update_expense_claim_status_for_paid_advances erpnext.patches.v13_0.create_gst_custom_fields_in_quotation erpnext.patches.v13_0.copy_custom_field_filters_to_website_item +erpnext.patches.v14_0.delete_employee_transfer_property_doctype diff --git a/erpnext/patches/v14_0/delete_employee_transfer_property_doctype.py b/erpnext/patches/v14_0/delete_employee_transfer_property_doctype.py new file mode 100644 index 00000000000..b50e010f94b --- /dev/null +++ b/erpnext/patches/v14_0/delete_employee_transfer_property_doctype.py @@ -0,0 +1,5 @@ +import frappe + + +def execute(): + frappe.delete_doc("DocType", "Employee Transfer Property", ignore_missing=True) From 8e5327a0e0890060ade7f486e028dd021ff5ecc9 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Fri, 22 Apr 2022 21:33:24 +0530 Subject: [PATCH 9/9] fix: clear property child table on changing employee --- erpnext/hr/employee_property_update.js | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/erpnext/hr/employee_property_update.js b/erpnext/hr/employee_property_update.js index b11683347c2..86130bf7930 100644 --- a/erpnext/hr/employee_property_update.js +++ b/erpnext/hr/employee_property_update.js @@ -10,13 +10,20 @@ frappe.ui.form.on(cur_frm.doctype, { }, onload: function(frm) { - if (frm.doc.__islocal) { - if (frm.doctype == "Employee Promotion") { - frm.clear_table("promotion_details"); - } else if (frm.doctype == "Employee Transfer") { - frm.clear_table("transfer_details"); - } - } + if (frm.doc.__islocal) + frm.trigger("clear_property_table"); + }, + + employee: function(frm) { + frm.trigger("clear_property_table"); + }, + + clear_property_table: function(frm) { + let table = (frm.doctype == "Employee Promotion") ? "promotion_details" : "transfer_details"; + frm.clear_table(table); + frm.refresh_field(table); + + frm.fields_dict[table].grid.wrapper.find(".grid-add-row").hide(); }, refresh: function(frm) {