ccajohnson
Kilo Sage

Contents


Overview

Many times clients want the ability to remind users of upcoming tasks, but do not want multiple notifications being sent to the same user at the same time. This is a method of capturing these multiple notifications into a single notification.

Use Case

Send Knowledge Article Reminder

The system will send a reminder notification on Mondays to the author of a knowledge article within one week of the valid to date. If multiple articles are due, the author will receive one notification listing all articles that are due.

Solution

Event Registry

Since this custom solution relies upon an event to trigger the notification, the following custom event will be created:

Event Name: kb_knowledge.review
Table: Knowledge [kb_knowledge]
Fired by: Scheduled Job
Description: Fruition Partners: Custom Event used to send notifications for Knowledge article review.

Scheduled Job

The following Scheduled Job will be created:

Name: Knowledge Review Notify
Run: Weekly
Day: Monday
Time: Hours 12 | 00 | 00
Run this script:
checkRevDate();

function checkRevDate() {
    var aDt = new GlideDateTime();                                          //1
    aDt.addDays(7);
    var cDate = aDt.toString().split(' ')[0];                               //2
    var kb = new GlideAggregate('kb_knowledge');                            //3
    kb.addQuery('workflow_state', '!=', 'retired');                         //4
    kb.addQuery('author', '!=', '');                                        //5
    kb.addQuery('valid_to', '<=', cDate);                                   //6
    kb.groupBy('author');                                                   //7
    kb.query();
    kbArray = [];
    while (kb.next()) {                                                     //8
        kbArray.push(kb.author.toString());
    }

    var arrUtil = new global.ArrayUtil();                                    //9
    var uKbArray = arrUtil.unique(kbArray);                                 //10
    for (k = 0; k < uKbArray.length; k++) {                                 //11
        var kno = new GlideRecord('kb_knowledge');
        kno.addQuery('workflow_state', '!=', 'retired');                    //12
        kno.addQuery('author', '!=', '');                                   //13
        kno.addQuery('valid_to', '<=', cDate);                              //14
        kno.addQuery('author', kbArray[k]);                                 //15
        kno.orderBy('number');                                              //16
        kno.query();
        var kbID = [];                                                      //17
        while (kno.next()) {
            kbID.push(kno.sys_id.toString());
            if (kbID.length == kno.getRowCount()) {                         //18
                gs.eventQueue('kb_knowledge.review', kno, kbArray[k], kbID);
            }
        }
    }
}

Notes:

  1. Variable aDt (add Date time) is created and 7 days are added.
  2. Variable cDate (check Date) takes only the date portion of the glide date time object. Used in the addQuery methods below.
  3. Perform a GlideAggregate query in order to group by Author.
  4. Find only records that are not retired.
  5. And find records that have an author.
  6. And find records where the valid_to date is less than or equal to cDate.
  7. Group the results by the author field to give you the unique authors.
  8. While iterating through the query, push the author to the kbArray.
  9. For each slice of the kbArray (each unique author), run a new GlideRecord query.
  10. Find only records that are not retired.
  11. And find records that have an author.
  12. And find records where the valid_to date is less than or equal to cDate.
  13. And find all knowledge articles of the author within the current slice.
  14. Order the query by number.
  15. Variable kbID stores the sys_id of all articles for the current author.
  16. Once the number of slices in kbID equals the number of records in the query, trigger the event. The eventQueue contains the event name kb_knowledge.review, the current query kno, the current author kbArray[k], and the string of sys_id's of all articles for the current author kbID.

Notification Email Script

Since the event.parm2 portion of the event holds all of the Sys IDs for the found Knowledge articles, we need to summarize them into a table to include in our Notification. We do this with a Notification Email Script:

Name: kb_knowledge_summary
Newlines to HTML: false
Script:
(function runMailScript(/* GlideRecord */ current, /* TemplatePrinter */ template,
        /* Optional EmailOutbound */ email, /* Optional GlideRecord */ email_action,
        /* Optional GlideRecord */ event) {

    /**
     * Looks up multiple Knowledge articles and displays them in a table.
     *
     * @param      {String}  event.parm2  Comma delimited list of Sys IDs
     */
    template.print("<table>");
    template.print("<tr><th align='left'>Number</th><th align='left'>Short Description</th><th align='left'>Valid to date</th></tr>");
    var kbRec = new GlideRecord('kb_knowledge');                                //1
    var sKbRec = event.parm2.split(',');                                        //2
    var tbl = current.getTableName();                                           //3
    for (x = 0; x < sKbRec.length; x++) {                                       //4
        kbRec.get(sKbRec[x]);                                                   //5
        var link = createLinkForObject(tbl,kbRec.sys_id,kbRec.number);          //6
        template.print("<tr><td>" + link + "</td><td style='padding: 4px;'>" + kbRec.short_description + "</td><td>" + kbRec.valid_to + "</td></tr>");
    }
    template.print("</table>");
})(current, template, email, email_action, event);

/**
 * Creates a URL that is used in Notifications
 *
 * @param      {string}  strTableName  Name of the table the record is on
 * @param      {string}  strSysID      sys_id of the record
 * @param      {string}  strLabel      Label to be used in the URL
 * @return     {string}  URL formatted string
 */
function createLinkForObject(strTableName, strSysID, strLabel) {                //7
    return '<a href="' + gs.getProperty('glide.servlet.uri') + 'nav_to.do?uri=' + gs.generateURL(strTableName, strSysID) + '">' + strLabel + '</a>';
}

Notes:

  1. Instantiate a new GlideRecord object.
  2. Variable sKbRec stores the string of sys_id's passed through event.parm2 into an array.
  3. Variable tbl stores the table name of the current record for the createLinkForObject() function.
  4. Iterate through the sKbRec array.
  5. Get the record for the current slice.
  6. Variable link calls the createLinkForObject() function passing the table name tbl, the sys_id of the current record kbRec.sys_id, and the number of the current record kbRec.number.
  7. This function generates a link that is used to click through from the notification.

Notification

The following notification will send to the author of the found articles. For each article found it will add a new line to the table.

Name: KB - Awaiting Review
Table: Knowledge [kb_knowledge]
When to send:
Send When: Event is fired
Event Name: kb_knowledge.review
Who will receive:
Users/Groups in fields: Author
Send to event creator: true
What it will contain:
Subject: Knowledge Articles Awaiting Review for ${author}
Message:
<p>Please review the expiring Knowledge articles below. Any article passed the Valid to date will no longer be searchable.</p>
<p>${mail_script:kb_knowledge_summary}</p>
Comments
mikkojuola
Giga Guru

Thanks for sharing!

 

We've been investigating an option to use Email Digest for a similar purpose, but that doesn't seem to work this way. Does anyone know, if ServiceNow is providing something similar out-of-the-box, or if Email Digests could be used for this?

 

Cheers,

--Mikko

Chris D
Kilo Sage
Kilo Sage

This looks great - a great example of a custom digest.

Just adding this in case you're not aware and/or somebody stumbles onto this custom solution, ServiceNow does actually have an ootb notification triggered by a monthly job to warn users about expiring KB articles, see: 

Knowledge Management email notifications (servicenow.com)

The custom solution definitely has some benefits to it but I just wanted to share that if anybody's interested for simplicity's sake.

Version history
Last update:
‎02-03-2022 02:01 PM
Updated by: