fix(employee-group): resolve current active call recipients

Call popup scheduling used saved child-row user IDs, so changing an employee user silently dropped their calls. Resolve active employees from the member links at popup time, reject duplicate members, and display their full employee name. Add focused regression checks for these cases.

Issue: frappe/erpnext-bug-reviews#383 (bug 1)
(cherry picked from commit e302a8a0e2)

# Conflicts:
#	erpnext/crm/doctype/utils.py
#	erpnext/setup/doctype/employee_group/test_employee_group.py
This commit is contained in:
Krishna Shirsath
2026-10-26 21:16:33 +00:00
committed by Mergify
parent ed59ce64f3
commit fe5d271562
4 changed files with 70 additions and 8 deletions
+18 -6
View File
@@ -32,15 +32,27 @@ def get_scheduled_employees_for_popup(communication_medium):
)
available_employee_groups = tuple([emp.employee_group for emp in available_employee_groups])
<<<<<<< HEAD
=======
if not available_employee_groups and medium and medium.catch_all:
available_employee_groups = (medium.catch_all,)
if not available_employee_groups:
return set()
>>>>>>> e302a8a (fix(employee-group): resolve current active call recipients)
employees = frappe.get_all(
"Employee Group Table", filters={"parent": ["in", available_employee_groups]}, fields=["user_id"]
member = frappe.qb.DocType("Employee Group Table")
employee = frappe.qb.DocType("Employee")
return set(
frappe.qb.from_(member)
.join(employee)
.on(member.employee == employee.name)
.select(employee.user_id)
.where(member.parent.isin(available_employee_groups))
.where(employee.status == "Active")
.where(employee.user_id.isnotnull() & (employee.user_id != ""))
.run(pluck=True)
)
employee_emails = set([employee.user_id for employee in employees])
return employee_emails
def strip_number(number):
if not number:
@@ -2,6 +2,8 @@
# For license information, please see license.txt
import frappe
from frappe import _
from frappe.model.document import Document
@@ -20,4 +22,7 @@ class EmployeeGroup(Document):
employee_list: DF.Table[EmployeeGroupTable]
# end: auto-generated types
pass
def validate(self):
employees = [row.employee for row in self.employee_list if row.employee]
if len(employees) != len(set(employees)):
frappe.throw(_("An employee can only appear once in an Employee Group"))
@@ -1,15 +1,60 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
<<<<<<< HEAD
import unittest
=======
from unittest.mock import patch
>>>>>>> e302a8a (fix(employee-group): resolve current active call recipients)
import frappe
from erpnext.crm.doctype.utils import get_scheduled_employees_for_popup
from erpnext.setup.doctype.employee.test_employee import make_employee
<<<<<<< HEAD
class TestEmployeeGroup(unittest.TestCase):
pass
=======
class TestEmployeeGroup(ERPNextTestSuite):
def test_duplicate_member(self):
employee = make_employee("group_duplicate@example.com", company="_Test Company")
group = frappe.get_doc(
{
"doctype": "Employee Group",
"employee_group_name": "_Test Duplicate Employee Group",
"employee_list": [{"employee": employee}, {"employee": employee}],
}
)
with self.assertRaises(frappe.ValidationError):
group.insert()
def test_popup_uses_current_active_employee_user(self):
employee = make_employee(
"group_member@example.com", company="_Test Company", first_name="Group", last_name="Member"
)
group = frappe.get_doc(
{
"doctype": "Employee Group",
"employee_group_name": "_Test Popup Employee Group",
"employee_list": [{"employee": employee}],
}
).insert()
self.assertEqual(group.employee_list[0].employee_name, "Group Member")
# Only replace the timeslot lookup; the member lookup must query the database.
with patch(
"erpnext.crm.doctype.utils.frappe.get_all", return_value=[frappe._dict(employee_group=group.name)]
):
self.assertEqual(get_scheduled_employees_for_popup("test-medium"), {"group_member@example.com"})
frappe.db.set_value("Employee", employee, "user_id", "Administrator")
self.assertEqual(get_scheduled_employees_for_popup("test-medium"), {"Administrator"})
frappe.db.set_value("Employee", employee, "status", "Left")
self.assertEqual(get_scheduled_employees_for_popup("test-medium"), set())
>>>>>>> e302a8a (fix(employee-group): resolve current active call recipients)
def make_employee_group():
@@ -17,7 +17,7 @@
"options": "Employee"
},
{
"fetch_from": "employee.first_name",
"fetch_from": "employee.employee_name",
"fieldname": "employee_name",
"fieldtype": "Data",
"in_list_view": 1,