logo

NJP

ServiceNow 3-strike rule on RITM (auto-close Service Request in awaiting customer)

Import · Jun 26, 2020 · article

(ordinarily for incident Flow Designer might be used)

alas, on New York version this is not possible, and below is a business rule + scheduled job option to avoid having to update all the RITM workflows (though a second workflow to attach to the RITM could be an alternative option)

in this particular solution, the customer carried out work at the RITM level as catalog tasks were not yet being used by the fulfilment teams

Code assumes a custom field u_closure_code is used on the RITM table

3-strike rule for RITMs

Contents

How it works

Build

New fields

Business rules

Event registry

ACLs

Scheduled job

Notification

How to test

Scheduled job script

How it works

· When an RITM is placed in state=on holdand on hold reason=awaiting caller, a business rule will populate a new field:

This field will not be editable by ITIL users or placed on the form but is viewable via list view.

· A scheduled job will run daily at 21h and will check for all active RITMs with this new date field populated where the date is > one day ago. The job will not run on Saturdays, Sundays or Mondays to account for weekends.

· If such requests are located, the following actions will take place

o Chase up notification is sent to the user

o An additional custom field is populated:

o The awaiting customer date is re-set to the date the scheduled job is run

· Simultaneously, the scheduled job checks for RITMs where the follow up email sent is true and the awaiting customer date is > 2days ago, and if such tickets are located, they are auto-closed. Close code and notes set as follows:

· If a response is received from the customer or the RITM is otherwise changed from awaiting caller, the awaiting customer date and follow up email will be re-set to blank / false

Build

Business rules

Business rule Purpose
RITM awaiting customer Set the ‘Awaiting customer date’ to today’s date if the on hold reason changes to 'awaiting caller'current.u_awaiting_customer_date.setDisplayValue(gs.nowDateTime());
RITM clear date and flag Reset the ‘Awaiting customer date’ and ‘Follow up email sent’ so the scheduled job ignores the record, as the RITM is no longer in awaiting caller stateif (previous.u_hold_reason == 1 && current.u_hold_reason != 1) { if (!gs.nil(current.u_awaiting_customer_date)) { current.u_awaiting_customer_date = ""; current.u_follow_up_email_sent = false; } }

Event registry (RITM table)

Used to queue the notification within the scheduled job script

emailcaller.reminder.ritm

ACLs

Restrict write access to the new fields to sys admins

Scheduled job (see further down for copy script)

“Send chase up email or close RITM - awaiting customer”

Dual purpose:

· Send follow up reminder email for awaiting customer RITMs where the ticket was set to awaiting customer > 1 day ago

· Auto-close RITMs which previously were set to awaiting customer and the follow up email flag was set to true

The job will not execute on Saturday, Sunday, Monday to exclude weekends

Notification

3-strike chase-Await cust response RITM

How to test

· Go to a RITM and set it to on hold> awaiting caller

· Verify that the Awaiting Customer date is set

· Either wait a day or 2, or from list view manually set the Awaiting Customer date field to > 2 days ago

· Execute the scheduled job, and check the email logs for the chase-up email (and check servicenowtest mailbox)

· Verify that the job has also set the Follow up email flag to true (from the RITM list) and has now re-set the Awaiting customer date to today’s date

· Verify that replies from the customer will set the ticket back to in progress and the job will skip over them (fields are reset and thus the record is excluded)

· If the RITM is still awaiting customer with the Follow up email flag set to true, update the Awaiting customer to > 2 days ago and execute the scheduled job

· Verify that the RITM is closed with close code and notes populated

Scheduled job script:

//--RDS CloudMinus89 Ltd, June2020 //--for 3 strike rule on requests //--in conjunction with business rule //--don't run it on a Sat, Sunvar sDateQuery='u_awaiting_customer_dateRELATIVELE@hour@ago@24';//updated over 24 hours agovar d = new Date(); var n = d.getDay(); //--Sunday is 0, Monday is 1, and so on. if (n != 6 && n != 0) { chaseAwaitingCustomer(sDateQuery); gs.sleep (2000); autoCloseRITMs(sDateQuery); } function chaseAwaitingCustomer(sDateQuery) { var grRITMs = new GlideRecord('sc_req_item'); grRITMs.addActiveQuery(); grRITMs.addQuery('u_hold_reason=1'); //--awaiting caller grRITMs.addQuery('u_follow_up_email_sent', 'false'); grRITMs.addQuery(sDateQuery); grRITMs.query(); while (grRITMs.next()) { gs.eventQueue("cu.emailcaller.reminder.ritm", grRITMs, "", ""); grRITMs.u_awaiting_customer_date.setDisplayValue(gs.nowDateTime()); //--reset the date counter grRITMs.u_follow_up_email_sent = true; grRITMs.update(); } } function autoCloseRITMs(sDateQuery) { var grRITMs_C = new GlideRecord('sc_req_item'); grRITMs_C.addActiveQuery(); grRITMs_C.addQuery('u_hold_reason=1'); //--awaiting caller grRITMs_C.addQuery('u_follow_up_email_sent', 'true'); grRITMs_C.addQuery(sDateQuery); grRITMs_C.query(); while (grRITMs_C.next()) { grRITMs_C.state=3; grRITMs_C.close_notes='No Response from User'; grRITMs_C.u_closure_code='No Response from User'; grRITMs_C.update(); gs.log(grRITMs_C.number, "schJob:autoCloseRITMs"); } }

Haven't tested these all recently within global/local scopes, so feel free to have a play! option 1 use an encoded query embedded in the GlideRecord , e.g. var grProf = new GlideRecord ( 'x_cls_clear_skye_i_profile' ); grProf . addQuery ( 'status=1^ owner=NULL ' ); grProf . query (); even better use the glideRecord addNotNullQuery or addNullQuery option 2 JSUtil.nil / notNil (this might be the most powerful. See this link ) example: if ( current . operation () == 'insert' && JSUtil . notNil ( current . parent ) && ! current . work_effort . nil ()) option 3 there might be times when you need to get inside the GlideRecord and perform the check there, for example if the code goes down 2 optional routes depending on null / not null can use gs.nil : var grAppr = new GlideRecord ( 'sysapproval_approver' ); var grUser = new GlideRecord ( 'sys_user' ); if ( grUser . get ( 'sys_id' , current . approver )){

Classic UI : var sURL_editparam = gs . action . getGlideURI (). getMap (). get ( ' sysparm_aparameter ' ); if ( sURL_editparam == 'true' ) { gs . addInfoMessage ( 'parameter passed ); } Portal : var sURL_editparam = $sp . getParameter ( " sysparm_aparameter " ); if ( sURL_editparam == 'true' ) { gs . addInfoMessage ( 'parameter passed ); }

Call a script include to apply a reference qualifier on a catalog item variable: - variable reference qualifier dependent on another variable selection, in this case a variable referencing sys_user (requested_for) On the catalog item form. variable name to apply ref qual filter : retail_equipment variable reference qualifier (on cmdb table ): javascript : new refqual_functions (). lostStolen_getAssignedCIs (); client-callable script include ( refqual_functions) function : lostStolen_getAssignedCIs : function (){ //--called from variable set client script, for lost/stolen request (service catalog) gs . log ( current . variables . requested_for , 'retail_lostStolen_getAssignedCIs' ); return ( 'install_statusNOT IN8,7owned_by=' + current . variables . requested_for ); //owned_by=1269b79937f1060041c5616043990e41install_statusNOT IN8,7 },

View original source

http://www.cloudminus89.com/2020/06/3-strike-rule-on-ritm.html