diff --git a/frappe/desk/notifications.py b/frappe/desk/notifications.py index 7eb597175a..a8063d0e03 100644 --- a/frappe/desk/notifications.py +++ b/frappe/desk/notifications.py @@ -267,35 +267,29 @@ def get_open_count(doctype, name, items=None): if not isinstance(items, list): items = json.loads(items) - out = [] + out = { + "external_links_found": [], + "internal_links_found": [], + } + for d in items: - if d in links.get("internal_links", {}) and not links.get("non_standard_fieldnames", {}).get( - d, {} - ): - continue - - filters = get_filters_for(d) - fieldname = links.get("non_standard_fieldnames", {}).get(d, links.get("fieldname")) - data = {"name": d} - if filters: - # get the fieldname for the current document - # we only need open documents related to the current document - filters[fieldname] = name - total = len( - frappe.get_all(d, fields="name", filters=filters, limit=100, distinct=True, ignore_ifnull=True) - ) - data["open_count"] = total - - total = len( - frappe.get_all( - d, fields="name", filters={fieldname: name}, limit=100, distinct=True, ignore_ifnull=True - ) - ) - data["count"] = total - out.append(data) + internal_link_for_doctype = links.get("internal_links", {}).get(d) + if internal_link_for_doctype: + internal_links_data_for_d = get_internal_links(doc, internal_link_for_doctype, d) + if internal_links_data_for_d["count"]: + out["internal_links_found"].append(internal_links_data_for_d) + else: + try: + external_links_data_for_d = get_external_links(d, name, links) + out["external_links_found"].append(external_links_data_for_d) + except Exception as e: + out["external_links_found"].append({"doctype": d, "open_count": 0, "count": 0}) + else: + external_links_data_for_d = get_external_links(d, name, links) + out["external_links_found"].append(external_links_data_for_d) out = { - "count": out, + "links_count_data": out, } if not meta.custom: @@ -306,6 +300,56 @@ def get_open_count(doctype, name, items=None): return out +def get_internal_links(doc, link, link_doctype): + names = [] + data = {"doctype": link_doctype} + + if isinstance(link, str): + # get internal links in parent document + value = doc.link + if value and value not in names: + names.append(value) + elif isinstance(link, list): + # get internal links in child documents + table_fieldname, link_fieldname = link + for row in doc.get(table_fieldname): + value = row.get(link_fieldname) + if value and value not in names: + names.append(value) + + data["open_count"] = 0 + data["count"] = len(names) + data["names"] = names + + return data + + +def get_external_links(doctype, name, links): + filters = get_filters_for(doctype) + fieldname = links.get("non_standard_fieldnames", {}).get(doctype, links.get("fieldname")) + data = {"doctype": doctype} + + if filters: + # get the fieldname for the current document + # we only need open documents related to the current document + filters[fieldname] = name + total = len( + frappe.get_all( + doctype, fields="name", filters=filters, limit=100, distinct=True, ignore_ifnull=True + ) + ) + data["open_count"] = total + + total = len( + frappe.get_all( + doctype, fields="name", filters={fieldname: name}, limit=100, distinct=True, ignore_ifnull=True + ) + ) + data["count"] = total + + return data + + def notify_mentions(ref_doctype, ref_name, content): if ref_doctype and ref_name and content: mentions = extract_mentions(content) diff --git a/frappe/public/js/frappe/form/dashboard.js b/frappe/public/js/frappe/form/dashboard.js index 633dd157d7..b3afe2802d 100644 --- a/frappe/public/js/frappe/form/dashboard.js +++ b/frappe/public/js/frappe/form/dashboard.js @@ -250,7 +250,6 @@ frappe.ui.form.Dashboard = class FormDashboard { this.data = this.frm.meta.__dashboard || {}; if (!this.data.transactions) this.data.transactions = []; if (!this.data.internal_links) this.data.internal_links = {}; - this.doctypes_in_both_external_and_internal_links_and_external_links_found = []; this.filter_permissions(); } @@ -370,24 +369,14 @@ frappe.ui.form.Dashboard = class FormDashboard { let doctype = $link.attr("data-doctype"), names = $link.attr("data-names") || []; - if (this.data.internal_links[doctype]) { - if ( - this.doctypes_in_both_external_and_internal_links_and_external_links_found && - this.doctypes_in_both_external_and_internal_links_and_external_links_found.includes( - doctype - ) && - this.data.fieldname - ) { - frappe.route_options = this.get_document_filter(doctype); - if (show_open && frappe.ui.notifications) { - frappe.ui.notifications.show_open_count_list(doctype); - } + if ( + this.internal_links_found && + this.internal_links_found.find((d) => d.doctype === doctype) + ) { + if (names.length) { + frappe.route_options = { name: ["in", names] }; } else { - if (names.length) { - frappe.route_options = { name: ["in", names] }; - } else { - return false; - } + return false; } } else if (this.data.fieldname) { frappe.route_options = this.get_document_filter(doctype); @@ -451,7 +440,7 @@ frappe.ui.form.Dashboard = class FormDashboard { me.update_heatmap(r.message.timeline_data); } - me.update_badges(items, r.message.count); + me.update_badges(r.message.links_count_data); me.frm.dashboard_data = r.message; me._fetched_counts = true; @@ -460,73 +449,26 @@ frappe.ui.form.Dashboard = class FormDashboard { }); } - update_badges(doctypes, external_links_doctypes_data) { + update_badges(links_count_data) { let me = this; - doctypes.forEach(function (doctype) { - const external_links_doctype_data = external_links_doctypes_data.find( - (d) => d.name === doctype - ); + this.internal_links_found = links_count_data.internal_links_found; - if ( - me.data.internal_links && - Object.keys(me.data.internal_links).includes(doctype) && - external_links_doctype_data && - (cint(external_links_doctype_data.open_count) || - cint(external_links_doctype_data.count)) - ) { - // doctype is both in internal and external links in the dashboard definition - // found external links and setting badge count - // not checking internal links - me.frm.dashboard.set_badge_count_for_external_link( - doctype, - cint(external_links_doctype_data.open_count), - cint(external_links_doctype_data.count) - ); - me.doctypes_in_both_external_and_internal_links_and_external_links_found.push( - doctype - ); - } else if ( - me.data.internal_links && - Object.keys(me.data.internal_links).includes(doctype) - ) { - // doctype is only in internal links in the dashboard definition or - // doctype is both in internal and external links in the dashboard definition - // checking internal links - // may or may not find internal links but setting badge count - const link = me.data.internal_links[doctype]; - let names = []; - if (typeof link === "string" || link instanceof String) { - // get internal links in parent document - let value = me.frm.doc[link]; - if (value && !names.includes(value)) { - names.push(value); - } - } else if (Array.isArray(link)) { - // get internal links in child documents - let [table_fieldname, link_fieldname] = link; - (me.frm.doc[table_fieldname] || []).forEach((d) => { - let value = d[link_fieldname]; - if (value && !names.includes(value)) { - names.push(value); - } - }); - } - me.frm.dashboard.set_badge_count_for_internal_link( - doctype, - 0, - names.length, - names - ); - } else { - // doctype is only in external links in the dashboard definition - // may or may not have found external links but setting badge count - me.frm.dashboard.set_badge_count_for_external_link( - doctype, - cint(external_links_doctype_data.open_count), - cint(external_links_doctype_data.count) - ); - } + $.each(links_count_data.internal_links_found, function (i, d) { + me.frm.dashboard.set_badge_count_for_internal_link( + d.doctype, + cint(d.open_count), + cint(d.count), + d.names + ); + }); + + $.each(links_count_data.external_links_found, function (i, d) { + me.frm.dashboard.set_badge_count_for_external_link( + d.doctype, + cint(d.open_count), + cint(d.count) + ); }); } @@ -545,12 +487,10 @@ frappe.ui.form.Dashboard = class FormDashboard { this.set_badge_count_common(open_count, count, $link); - if (this.data.internal_links[doctype]) { - if (names && names.length) { - $link.attr("data-names", names ? names.join(",") : ""); - } else { - $link.find("a").attr("disabled", true); - } + if (names && names.length) { + $link.attr("data-names", names ? names.join(",") : ""); + } else { + $link.find("a").attr("disabled", true); } }