diff --git a/frappe/email/__init__.py b/frappe/email/__init__.py index 4416535141..40af148bc1 100644 --- a/frappe/email/__init__.py +++ b/frappe/email/__init__.py @@ -9,20 +9,22 @@ def sendmail_to_system_managers(subject, content): @frappe.whitelist() -def get_contact_list(txt, page_length=20) -> list[dict]: +def get_contact_list(txt, page_length=20, extra_filters: str | None = None) -> list[dict]: """Return email ids for a multiselect field.""" - from frappe.contacts.doctype.contact.contact import get_full_name + if extra_filters: + extra_filters = frappe.parse_json(extra_filters) - if cached_contacts := get_cached_contacts(txt): - return cached_contacts[:page_length] + filters = [ + ["Contact Email", "email_id", "is", "set"], + ] + if extra_filters: + filters.extend(extra_filters) fields = ["first_name", "middle_name", "last_name", "company_name"] contacts = frappe.get_list( "Contact", - fields=[*fields, "`tabContact Email`.email_id"], - filters=[ - ["Contact Email", "email_id", "is", "set"], - ], + fields=["full_name", "`tabContact Email`.email_id"], + filters=filters, or_filters=[[field, "like", f"%{txt}%"] for field in fields] + [["Contact Email", "email_id", "like", f"%{txt}%"]], limit_page_length=page_length, @@ -31,19 +33,15 @@ def get_contact_list(txt, page_length=20) -> list[dict]: # The multiselect field will store the `label` as the selected value. # The `value` is just used as a unique key to distinguish between the options. # https://github.com/frappe/frappe/blob/6c6a89bcdd9454060a1333e23b855d0505c9ebc2/frappe/public/js/frappe/form/controls/autocomplete.js#L29-L35 - result = [ + return [ frappe._dict( value=d.email_id, label=d.email_id, - description=get_full_name(d.first_name, d.middle_name, d.last_name, d.company_name), + description=d.full_name, ) for d in contacts ] - update_contact_cache(result) - - return result - def get_system_managers(): return frappe.db.sql_list( @@ -94,28 +92,3 @@ def get_communication_doctype(doctype, txt, searchfield, start, page_len, filter ] return [[dt] for dt in com_doctypes if txt.lower().replace("%", "") in dt.lower() and dt in can_read] - - -def get_cached_contacts(txt): - contacts = frappe.cache.hget("contacts", frappe.session.user) or [] - - if not contacts: - return - - if not txt: - return contacts - - return [ - d - for d in contacts - if (d.value and ((d.value and txt in d.value) or (d.description and txt in d.description))) - ] - - -def update_contact_cache(contacts): - cached_contacts = frappe.cache.hget("contacts", frappe.session.user) or [] - - uncached_contacts = [d for d in contacts if d not in cached_contacts] - cached_contacts.extend(uncached_contacts) - - frappe.cache.hset("contacts", frappe.session.user, cached_contacts) diff --git a/frappe/public/js/frappe/views/communication.js b/frappe/public/js/frappe/views/communication.js index 6f3cd52efd..2bc57732bf 100755 --- a/frappe/public/js/frappe/views/communication.js +++ b/frappe/public/js/frappe/views/communication.js @@ -255,10 +255,18 @@ frappe.views.CommunicationComposer = class { this.dialog.fields_dict[field].get_data = () => { const data = this.dialog.fields_dict[field].get_value(); const txt = data.match(/[^,\s*]*$/)[0] || ""; + const args = { txt }; + + if (this.frm.events.get_email_recipient_filters) { + args.extra_filters = this.frm.events.get_email_recipient_filters( + this.frm, + field + ); + } frappe.call({ method: "frappe.email.get_contact_list", - args: { txt }, + args: args, callback: (r) => { this.dialog.fields_dict[field].set_data(r.message); },