From ae733cd7adba73b7d9eb40791b960977ece78f41 Mon Sep 17 00:00:00 2001 From: Abdeali Chharchhoda Date: Sat, 1 Nov 2025 17:32:52 +0530 Subject: [PATCH 1/9] chore: Removing unused import (cherry picked from commit 87c59f471cac0a49fed5d7d6b21db6eb5f3d2eae) --- erpnext/accounts/party.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index b8bcc3a4160..57c66d91351 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -7,18 +7,16 @@ from frappe import _, msgprint, qb, scrub from frappe.contacts.doctype.address.address import get_company_address, get_default_address from frappe.core.doctype.user_permission.user_permission import get_permitted_documents from frappe.model.utils import get_fetch_values -from frappe.query_builder.functions import Abs, Count, Date, Sum +from frappe.query_builder.functions import Abs, Date, Sum from frappe.utils import ( add_days, add_months, - add_years, cint, cstr, date_diff, flt, formatdate, get_last_day, - get_timestamp, getdate, nowdate, ) From 4b2ac626c5cd0abb7bf1ca0aca7916497a1b98d6 Mon Sep 17 00:00:00 2001 From: Abdeali Chharchhoda Date: Sat, 1 Nov 2025 17:55:09 +0530 Subject: [PATCH 2/9] feat: retrieve employee basic contact information (cherry picked from commit 4ad1474e32da7e729ab07cd35fc3bc2070fa7ee3) --- erpnext/setup/doctype/employee/employee.py | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/erpnext/setup/doctype/employee/employee.py b/erpnext/setup/doctype/employee/employee.py index 85f9e712fe0..654481917db 100755 --- a/erpnext/setup/doctype/employee/employee.py +++ b/erpnext/setup/doctype/employee/employee.py @@ -436,3 +436,28 @@ def has_upload_permission(doc, ptype="read", user=None): if get_doc_permissions(doc, user=user, ptype=ptype).get(ptype): return True return doc.user_id == user + + +@frappe.whitelist() +def get_contact_details(employee: str) -> dict: + """ + Returns basic contact details for the given employee. + + - employee_name as contact_display + - prefered_email as contact_email + - cell_number as contact_mobile + - designation as contact_designation + - department as contact_department + + :param employee: Employee docname + """ + doc: Employee = frappe.get_doc("Employee", employee) + doc.check_permission() + + return { + "contact_display": doc.get("employee_name"), + "contact_email": doc.get("prefered_email"), + "contact_mobile": doc.get("cell_number"), + "contact_designation": doc.get("designation"), + "contact_department": doc.get("department"), + } From caa03efbe11b17e55b269276ca8ce07e419f9ec6 Mon Sep 17 00:00:00 2001 From: Abdeali Chharchhoda Date: Sat, 1 Nov 2025 19:18:23 +0530 Subject: [PATCH 3/9] feat: retrieve employee contact details (cherry picked from commit a41297d8410eb4bd821689b77756d964aeaed280) --- erpnext/public/js/utils/party.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/erpnext/public/js/utils/party.js b/erpnext/public/js/utils/party.js index 958defa32c7..4e74cc3d6e7 100644 --- a/erpnext/public/js/utils/party.js +++ b/erpnext/public/js/utils/party.js @@ -314,6 +314,16 @@ erpnext.utils.get_contact_details = function (frm) { } }; +erpnext.utils.get_employee_contact_details = async function (employee) { + if (!employee) return; + + const response = await frappe.xcall("erpnext.setup.doctype.employee.employee.get_contact_details", { + employee, + }); + + return response?.message; +}; + erpnext.utils.validate_mandatory = function (frm, label, value, trigger_on) { if (!value) { frm.doc[trigger_on] = ""; From 4078e252c28e68ed392866366dc25d86084ee910 Mon Sep 17 00:00:00 2001 From: Abdeali Chharchhoda Date: Sat, 1 Nov 2025 20:18:52 +0530 Subject: [PATCH 4/9] refactor: fetch employee contact details in realtime (cherry picked from commit 2ea6508fa5e61442d7789f3502c4b609f695af1f) --- .../doctype/payment_entry/payment_entry.js | 4 ++ erpnext/public/js/utils/party.js | 64 +++++++++++-------- 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index 6f89f02a1a7..60c8e47f8f0 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -516,12 +516,16 @@ frappe.ui.form.on("Payment Entry", { frm.set_value("contact_email", ""); frm.set_value("contact_person", ""); } + if (frm.doc.payment_type && frm.doc.party_type && frm.doc.party && frm.doc.company) { if (!frm.doc.posting_date) { frappe.msgprint(__("Please select Posting Date before selecting Party")); frm.set_value("party", ""); return; } + + erpnext.utils.get_employee_contact_details(frm); + frm.set_party_account_based_on_party = true; let company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency; diff --git a/erpnext/public/js/utils/party.js b/erpnext/public/js/utils/party.js index 4e74cc3d6e7..1652a849850 100644 --- a/erpnext/public/js/utils/party.js +++ b/erpnext/public/js/utils/party.js @@ -293,37 +293,49 @@ erpnext.utils.set_taxes = function (frm, triggered_from_field) { erpnext.utils.get_contact_details = function (frm) { if (frm.updating_party_details) return; - if (frm.doc["contact_person"]) { - frappe.call({ - method: "frappe.contacts.doctype.contact.contact.get_contact_details", - args: { contact: frm.doc.contact_person }, - callback: function (r) { - if (r.message) frm.set_value(r.message); - }, - }); - } else { - frm.set_value({ - contact_person: "", - contact_display: "", - contact_email: "", - contact_mobile: "", - contact_phone: "", - contact_designation: "", - contact_department: "", - }); + if (!frm.doc.contact_person) { + reset_contact_fields(frm); + return; } -}; -erpnext.utils.get_employee_contact_details = async function (employee) { - if (!employee) return; - - const response = await frappe.xcall("erpnext.setup.doctype.employee.employee.get_contact_details", { - employee, + frappe.call({ + method: "frappe.contacts.doctype.contact.contact.get_contact_details", + args: { contact: frm.doc.contact_person }, + callback: function (r) { + if (r.message) frm.set_value(r.message); + }, }); - - return response?.message; }; +erpnext.utils.get_employee_contact_details = function (frm) { + if (frm.updating_party_details || frm.doc.party_type !== "Employee") return; + + if (!frm.doc.party) { + reset_contact_fields(frm); + return; + } + + frappe.call({ + method: "erpnext.setup.doctype.employee.employee.get_contact_details", + args: { employee: frm.doc.party }, + callback: function (r) { + if (r.message) frm.set_value(r.message); + }, + }); +}; + +function reset_contact_fields(frm) { + frm.set_value({ + contact_person: "", + contact_display: "", + contact_email: "", + contact_mobile: "", + contact_phone: "", + contact_designation: "", + contact_department: "", + }); +} + erpnext.utils.validate_mandatory = function (frm, label, value, trigger_on) { if (!value) { frm.doc[trigger_on] = ""; From 0866c03e209eea68518f4fd07520ab90ad928f6a Mon Sep 17 00:00:00 2001 From: Abdeali Chharchhoda Date: Sun, 2 Nov 2025 19:32:34 +0530 Subject: [PATCH 5/9] refactor: add validation for missing employee parameter (cherry picked from commit b8e06b9636d55abbaa84c74acdf6b74a3e040cac) --- erpnext/setup/doctype/employee/employee.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/setup/doctype/employee/employee.py b/erpnext/setup/doctype/employee/employee.py index 654481917db..60db8098fb3 100755 --- a/erpnext/setup/doctype/employee/employee.py +++ b/erpnext/setup/doctype/employee/employee.py @@ -451,6 +451,9 @@ def get_contact_details(employee: str) -> dict: :param employee: Employee docname """ + if not employee: + frappe.throw(msg=_("Employee is required"), title=_("Missing Parameter")) + doc: Employee = frappe.get_doc("Employee", employee) doc.check_permission() From 943e2c00bc92ae5c509c36d25988ca46d842b4dc Mon Sep 17 00:00:00 2001 From: Abdeali Chharchhoda Date: Thu, 18 Dec 2025 18:41:31 +0530 Subject: [PATCH 6/9] fix: get employee email with priority if preferred is not set (cherry picked from commit 7b89c12470993803327edf51f57176362db93602) --- erpnext/setup/doctype/employee/employee.py | 48 +++++++++++++++------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/erpnext/setup/doctype/employee/employee.py b/erpnext/setup/doctype/employee/employee.py index 60db8098fb3..d6146b965b6 100755 --- a/erpnext/setup/doctype/employee/employee.py +++ b/erpnext/setup/doctype/employee/employee.py @@ -442,25 +442,43 @@ def has_upload_permission(doc, ptype="read", user=None): def get_contact_details(employee: str) -> dict: """ Returns basic contact details for the given employee. - - - employee_name as contact_display - - prefered_email as contact_email - - cell_number as contact_mobile - - designation as contact_designation - - department as contact_department - - :param employee: Employee docname """ if not employee: frappe.throw(msg=_("Employee is required"), title=_("Missing Parameter")) - doc: Employee = frappe.get_doc("Employee", employee) - doc.check_permission() + frappe.has_permission("Employee", "read", employee, throw=True) + + contact_data = frappe.db.get_value( + "Employee", + employee, + [ + "employee_name", + "prefered_email", + "company_email", + "personal_email", + "user_id", + "cell_number", + "designation", + "department", + ], + as_dict=True, + ) + + if not contact_data: + frappe.throw(msg=_("Employee {0} not found").format(employee), title=_("Not Found")) + + # Email with priority + employee_email = ( + contact_data.get("prefered_email") + or contact_data.get("company_email") + or contact_data.get("personal_email") + or contact_data.get("user_id") + ) return { - "contact_display": doc.get("employee_name"), - "contact_email": doc.get("prefered_email"), - "contact_mobile": doc.get("cell_number"), - "contact_designation": doc.get("designation"), - "contact_department": doc.get("department"), + "contact_display": contact_data.get("employee_name"), + "contact_email": employee_email, + "contact_mobile": contact_data.get("cell_number"), + "contact_designation": contact_data.get("designation"), + "contact_department": contact_data.get("department"), } From cb17dbd6164e163103458a3b1b2c4b6c93090539 Mon Sep 17 00:00:00 2001 From: Abdeali Chharchhoda Date: Thu, 18 Dec 2025 18:48:09 +0530 Subject: [PATCH 7/9] refactor: use common method to get employee contacts (cherry picked from commit ec1eb6d22201bea85030529aefba7ae21cdf4ed3) --- erpnext/accounts/party.py | 14 ++------------ erpnext/setup/doctype/employee/employee.py | 7 ++++++- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 57c66d91351..6730fc98af0 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -300,19 +300,9 @@ def complete_contact_details(party_details): contact_details = frappe._dict() if party_details.party_type == "Employee": - contact_details = frappe.db.get_value( - "Employee", - party_details.party, - [ - "employee_name as contact_display", - "prefered_email as contact_email", - "cell_number as contact_mobile", - "designation as contact_designation", - "department as contact_department", - ], - as_dict=True, - ) + from erpnext.setup.doctype.employee.employee import get_contact_details as get_employee_contact + contact_details = get_employee_contact(party_details.party) contact_details.update({"contact_person": None, "contact_phone": None}) elif party_details.contact_person: contact_details = frappe.db.get_value( diff --git a/erpnext/setup/doctype/employee/employee.py b/erpnext/setup/doctype/employee/employee.py index d6146b965b6..927b42c2cca 100755 --- a/erpnext/setup/doctype/employee/employee.py +++ b/erpnext/setup/doctype/employee/employee.py @@ -6,7 +6,6 @@ from frappe.model.naming import set_name_by_naming_series from frappe.permissions import ( add_user_permission, get_doc_permissions, - has_permission, remove_user_permission, ) from frappe.utils import cstr, getdate, today, validate_email_address @@ -442,6 +441,12 @@ def has_upload_permission(doc, ptype="read", user=None): def get_contact_details(employee: str) -> dict: """ Returns basic contact details for the given employee. + + Email is selected based on the following priority: + 1. Prefered Email + 2. Company Email + 3. Personal Email + 4. User ID """ if not employee: frappe.throw(msg=_("Employee is required"), title=_("Missing Parameter")) From 773e56808a40ddae8fe8571db7869226fd1bf2db Mon Sep 17 00:00:00 2001 From: Abdeali Chharchhoda Date: Fri, 19 Dec 2025 11:39:02 +0530 Subject: [PATCH 8/9] refactor: method to get employee contact without permission check (cherry picked from commit 58cdb9503b1e44804aa57b49babd3de9d0668a9d) --- erpnext/accounts/party.py | 2 +- erpnext/setup/doctype/employee/employee.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 6730fc98af0..c4622f0b06b 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -300,7 +300,7 @@ def complete_contact_details(party_details): contact_details = frappe._dict() if party_details.party_type == "Employee": - from erpnext.setup.doctype.employee.employee import get_contact_details as get_employee_contact + from erpnext.setup.doctype.employee.employee import _get_contact_details as get_employee_contact contact_details = get_employee_contact(party_details.party) contact_details.update({"contact_person": None, "contact_phone": None}) diff --git a/erpnext/setup/doctype/employee/employee.py b/erpnext/setup/doctype/employee/employee.py index 927b42c2cca..d78d1993a16 100755 --- a/erpnext/setup/doctype/employee/employee.py +++ b/erpnext/setup/doctype/employee/employee.py @@ -453,6 +453,10 @@ def get_contact_details(employee: str) -> dict: frappe.has_permission("Employee", "read", employee, throw=True) + return _get_contact_details(employee) + + +def _get_contact_details(employee: str) -> dict: contact_data = frappe.db.get_value( "Employee", employee, From 0ba965aae615aec7f77f3d3c28755e398a0c72db Mon Sep 17 00:00:00 2001 From: diptanilsaha Date: Mon, 23 Feb 2026 20:07:27 +0530 Subject: [PATCH 9/9] fix: restore missing `has_permission` import --- erpnext/setup/doctype/employee/employee.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/setup/doctype/employee/employee.py b/erpnext/setup/doctype/employee/employee.py index d78d1993a16..14724ead051 100755 --- a/erpnext/setup/doctype/employee/employee.py +++ b/erpnext/setup/doctype/employee/employee.py @@ -6,6 +6,7 @@ from frappe.model.naming import set_name_by_naming_series from frappe.permissions import ( add_user_permission, get_doc_permissions, + has_permission, remove_user_permission, ) from frappe.utils import cstr, getdate, today, validate_email_address