Merge pull request #24725 from blaggacao/chore/generalize-notification-receiver-fields
feat: generalize receiver logic in notifications
This commit is contained in:
commit
53b054e72e
2 changed files with 106 additions and 34 deletions
|
|
@ -14,10 +14,11 @@ frappe.notification = {
|
|||
let get_select_options = function (df, parent_field) {
|
||||
// Append parent_field name along with fieldname for child table fields
|
||||
let select_value = parent_field ? df.fieldname + "," + parent_field : df.fieldname;
|
||||
let path = parent_field ? parent_field + " > " + df.fieldname : df.fieldname;
|
||||
|
||||
return {
|
||||
value: select_value,
|
||||
label: df.fieldname + " (" + __(df.label, null, df.parent) + ")",
|
||||
label: path + " (" + __(df.label, null, df.parent) + ")",
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -33,6 +34,38 @@ frappe.notification = {
|
|||
{ value: "modified", label: `modified (${__("Last Modified Date")})` },
|
||||
]);
|
||||
};
|
||||
let get_receiver_fields = function (
|
||||
fields,
|
||||
is_extra_receiver_field = (_) => {
|
||||
return false;
|
||||
}
|
||||
) {
|
||||
// finds receiver fields from the fields or any child table
|
||||
// by default finds any link to the User doctype
|
||||
// however an additional optional predicate can be passed as argument
|
||||
// to find additional fields
|
||||
let is_receiver_field = function (df) {
|
||||
return (
|
||||
is_extra_receiver_field(df) ||
|
||||
(df.options == "User" && df.fieldtype == "Link") ||
|
||||
(df.options == "Customer" && df.fieldtype == "Link")
|
||||
);
|
||||
};
|
||||
let extract_receiver_field = function (df) {
|
||||
// Add recipients from child doctypes into select dropdown
|
||||
if (frappe.model.table_fields.includes(df.fieldtype)) {
|
||||
let child_fields = frappe.get_doc("DocType", df.options).fields;
|
||||
return $.map(child_fields, function (cdf) {
|
||||
return is_receiver_field(cdf)
|
||||
? get_select_options(cdf, df.fieldname)
|
||||
: null;
|
||||
});
|
||||
} else {
|
||||
return is_receiver_field(df) ? get_select_options(df) : null;
|
||||
}
|
||||
};
|
||||
return $.map(fields, extract_receiver_field);
|
||||
};
|
||||
|
||||
let fields = frappe.get_doc("DocType", frm.doc.document_type).fields;
|
||||
let options = $.map(fields, function (d) {
|
||||
|
|
@ -50,27 +83,12 @@ frappe.notification = {
|
|||
|
||||
let receiver_fields = [];
|
||||
if (frm.doc.channel === "Email") {
|
||||
receiver_fields = $.map(fields, function (d) {
|
||||
// Add User and Email fields from child into select dropdown
|
||||
if (frappe.model.table_fields.includes(d.fieldtype)) {
|
||||
let child_fields = frappe.get_doc("DocType", d.options).fields;
|
||||
return $.map(child_fields, function (df) {
|
||||
return df.options == "Email" ||
|
||||
(df.options == "User" && df.fieldtype == "Link")
|
||||
? get_select_options(df, d.fieldname)
|
||||
: null;
|
||||
});
|
||||
// Add User and Email fields from parent into select dropdown
|
||||
} else {
|
||||
return d.options == "Email" ||
|
||||
(d.options == "User" && d.fieldtype == "Link")
|
||||
? get_select_options(d)
|
||||
: null;
|
||||
}
|
||||
receiver_fields = get_receiver_fields(fields, function (df) {
|
||||
return df.options == "Email";
|
||||
});
|
||||
} else if (["WhatsApp", "SMS"].includes(frm.doc.channel)) {
|
||||
receiver_fields = $.map(fields, function (d) {
|
||||
return d.options == "Phone" ? get_select_options(d) : null;
|
||||
receiver_fields = get_receiver_fields(fields, function (df) {
|
||||
df.options == "Phone" || df.options == "Mobile";
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ def get_context(context):
|
|||
"""Build recipients and send Notification"""
|
||||
|
||||
context = get_context(doc)
|
||||
context = {"doc": doc, "alert": self, "comments": None}
|
||||
context.update({"alert": self, "comments": None})
|
||||
if doc.get("_comments"):
|
||||
context["comments"] = json.loads(doc.get("_comments"))
|
||||
|
||||
|
|
@ -316,10 +316,41 @@ def get_context(context):
|
|||
|
||||
def send_sms(self, doc, context):
|
||||
send_sms(
|
||||
receiver_list=self.get_receiver_list(doc, context),
|
||||
receiver_list=self.get_receiver_list(doc, context, "mobile_no", self.get_mobile_no),
|
||||
msg=frappe.utils.strip_html_tags(frappe.render_template(self.message, context)),
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_mobile_no(doc, field):
|
||||
option = doc.meta.get_field(field).options.strip()
|
||||
# users may sometimes register mobile numbers under Phone type fields
|
||||
if option == "Phone" or option == "Mobile":
|
||||
mobile_no = doc.get(field)
|
||||
if not mobile_no:
|
||||
doc.log_error(
|
||||
_("Notification: document {0} has no {1} number set (field: {2})").format(
|
||||
field, doc.name, option, field
|
||||
)
|
||||
)
|
||||
# but on user & customer it's expected to be set on the proper field
|
||||
elif option == "User":
|
||||
user = doc.get(field)
|
||||
mobile_no = frappe.get_value("User", user, "mobile_no")
|
||||
if not mobile_no:
|
||||
doc.log_error(_("Notification: user {0} has no Mobile number set").format(user))
|
||||
elif option == "Customer":
|
||||
customer = doc.get(field)
|
||||
mobile_no = frappe.get_value("Customer", customer, "mobile_no")
|
||||
if not mobile_no:
|
||||
doc.log_error(_("Notification: customer {0} has no Mobile number set").format(customer))
|
||||
else:
|
||||
frappe.throw(
|
||||
_(
|
||||
"Field {0} on document {1} is neither a Mobile number field nor a Customer or User link"
|
||||
).format(field, doc.name)
|
||||
)
|
||||
return mobile_no
|
||||
|
||||
def get_list_of_recipients(self, doc, context):
|
||||
recipients = []
|
||||
cc = []
|
||||
|
|
@ -329,16 +360,17 @@ def get_context(context):
|
|||
if not frappe.safe_eval(recipient.condition, None, context):
|
||||
continue
|
||||
if recipient.receiver_by_document_field:
|
||||
fields = recipient.receiver_by_document_field.split(",")
|
||||
# fields from child table
|
||||
if len(fields) > 1:
|
||||
for d in doc.get(fields[1]):
|
||||
email_id = d.get(fields[0])
|
||||
data_field, child_field = _parse_receiver_by_document_field(
|
||||
recipient.receiver_by_document_field
|
||||
)
|
||||
if child_field:
|
||||
for d in doc.get(child_field):
|
||||
email_id = d.get(data_field)
|
||||
if validate_email_address(email_id):
|
||||
recipients.append(email_id)
|
||||
# field from parent doc
|
||||
# field from current doc
|
||||
else:
|
||||
email_ids_value = doc.get(fields[0])
|
||||
email_ids_value = doc.get(data_field)
|
||||
if validate_email_address(email_ids_value):
|
||||
email_ids = email_ids_value.replace(",", "\n")
|
||||
recipients = recipients + email_ids.split("\n")
|
||||
|
|
@ -358,8 +390,10 @@ def get_context(context):
|
|||
|
||||
return list(set(recipients)), list(set(cc)), list(set(bcc))
|
||||
|
||||
def get_receiver_list(self, doc, context):
|
||||
def get_receiver_list(self, doc, context, field_on_user="mobile_no", recipient_extractor_func=None):
|
||||
"""return receiver list based on the doc field and role specified"""
|
||||
if not recipient_extractor_func:
|
||||
recipient_extractor_func = self.get_mobile_no
|
||||
receiver_list = []
|
||||
for recipient in self.recipients:
|
||||
if recipient.condition:
|
||||
|
|
@ -368,18 +402,28 @@ def get_context(context):
|
|||
|
||||
# For sending messages to the owner's mobile phone number
|
||||
if recipient.receiver_by_document_field == "owner":
|
||||
receiver_list += get_user_info([dict(user_name=doc.get("owner"))], "mobile_no")
|
||||
receiver_list += get_user_info([dict(user_name=doc.get("owner"))], field_on_user)
|
||||
# For sending messages to the number specified in the receiver field
|
||||
elif recipient.receiver_by_document_field:
|
||||
receiver_list.append(doc.get(recipient.receiver_by_document_field))
|
||||
data_field, child_field = _parse_receiver_by_document_field(
|
||||
recipient.receiver_by_document_field
|
||||
)
|
||||
if child_field:
|
||||
for d in doc.get(child_field):
|
||||
if recv := recipient_extractor_func(d, data_field):
|
||||
receiver_list.append(recv)
|
||||
# field from current doc
|
||||
else:
|
||||
if recv := recipient_extractor_func(doc, data_field):
|
||||
receiver_list.append(recv)
|
||||
|
||||
# For sending messages to specified role
|
||||
if recipient.receiver_by_role:
|
||||
receiver_list += get_info_based_on_role(
|
||||
recipient.receiver_by_role, "mobile_no", ignore_permissions=True
|
||||
recipient.receiver_by_role, field_on_user, ignore_permissions=True
|
||||
)
|
||||
|
||||
return receiver_list
|
||||
return list(set(receiver_list))
|
||||
|
||||
def get_attachment(self, doc):
|
||||
"""check print settings are attach the pdf"""
|
||||
|
|
@ -555,3 +599,13 @@ def get_reference_doctype(doc):
|
|||
|
||||
def get_reference_name(doc):
|
||||
return doc.parent if doc.meta.istable else doc.name
|
||||
|
||||
|
||||
def _parse_receiver_by_document_field(s):
|
||||
fragments = s.split(",")
|
||||
# fields from child table or linked doctype
|
||||
if len(fragments) > 1:
|
||||
data_field, child_field = fragments
|
||||
else:
|
||||
data_field, child_field = fragments[0], None
|
||||
return data_field, child_field
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue