Skip to main content

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

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

(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


How it works


New fields

Business rules

Event registry


Scheduled job


How to test

Scheduled job script


How it works


·       When an RITM is placed in state=on hold and 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



New fields


Business rules


Business rule


RITM awaiting customer


Set the ‘Awaiting customer date’ to today’s date if the on hold reason changes to 'awaiting caller'

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 state

if (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




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




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, Sun var sDateQuery='u_awaiting_customer_dateRELATIVELE@hour@ago@24';//updated over 24 hours ago var 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 ( { 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.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"); } }


Popular posts from this blog

ServiceNow check for null or nil or empty (or not)

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 )){

Get URL Parameter - server side script (portal or classic UI)

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 ); }