S

ervice-now provides the ability to automatically move incidents marked as ‘Resolved’ into a ‘Closed’ state after a certain number of days. In my experience I’ve found that this type of resolution/closure workflow is really the best way to configure your incident management setup because it allows end-users the ability to reopen incidents within a certain window (while they’re still marked as ‘Resolved’) but it also ensures that eventually all of the incident tickets move to a ‘Closed’ state where they won’t be reopened so that you can accurately calculate SLAs and reporting metrics.

The key piece to this auto close functionality is the ‘incident autoclose’ business rule on the ‘Incident’ table. It works in conjunction with the property shown here – that sets the number of days after which a resolved incident will be moved to a closed state. The ‘incident autoclose’ script works great but it is based off of a basic date calculation that doesn’t take into account any business hours or holidays. Shown below are some modified versions of the ‘incident autoclose’ script that take into account the default system calendar (in the case of calendar-based autoclose), or your choice of any system schedule set up in your system (in the case of schedule-based autoclose).

Calendar-based Incident Autoclose Script

NOTE: Calendars have been replaced in favor of schedules in Service-now. This calendar-based script is provided simply for reference purposes for those who may be using this script already. I would advise you to use the schedule-based script below if at all possible because it allows you to specify a specific schedule for the calculation (giving you much more flexibility and control) rather than simply using the default system calendar.
// This script automatically closes incidents that are resolved
// and haven't been updated in a chosen number of days. You
// can set this number as a property in System Properties.
// If you want a comment placed in the incident, uncomment the
// 'gr.comments' line below.

var ps = gs.getProperty('glide.ui.autoclose.time');
var pn = parseInt(ps);

if (pn > 0) {
   var gr = new GlideRecord('incident');
   gr.addQuery('state', 6);
   gr.query();
   while(gr.next()){
      //Close any records that have not been updated in 'pn' number of days
      //Date difference calculated based on default system calendar
      var dif = gs.calDateDiff(gs.nowDateTime(), gr.sys_updated_on, true);
      if(dif >= pn*86400){
         gr.state = 7;
         //gr.comments = 'Incident automatically closed after ' + pn + ' days in the Resolved state.';
         gr.active = false;
         gr.update();
      }
   }
}

Schedule-based Incident Autoclose Script

This schedule-based script is the BEST solution if you are setting up any kind of autoclose functionality in your system. The use of schedules gives you much more flexibility to determine exactly how much time should pass before closing out a resolved ticket. Schedules can be managed by navigating to ‘System Scheduler->Schedules’ in the left navigation pane of your Service-now instance. One important thing to note is that ‘Number of days’ is actually the number of 24 hour periods!
// This script automatically closes incidents that are resolved
// and haven't been updated in a chosen number of days. You
// can set this number as a property in System Properties.
// If you want a comment placed in the incident, uncomment the
// 'gr.comments' line below.

var ps = gs.getProperty('glide.ui.autoclose.time');
var pn = parseInt(ps);

if(pn > 0){
   //Get a schedule by name to calculate duration
   var schedRec = new GlideRecord('cmn_schedule');
   schedRec.get('name', '8-5 weekdays');
   if (typeof GlideSchedule != 'undefined')
      var sched = new GlideSchedule(schedRec.sys_id);
   else
      var sched = new Packages.com.glide.schedules.Schedule(schedRec.sys_id);

   //Get the current date/time in correct format for duration calculation
   var actualDateTime = new GlideDateTime();
   actualDateTime.setDisplayValue(gs.nowDateTime());

   //Query for resolved incident records
   var gr = new GlideRecord('incident');
   gr.addQuery('state', 6);
   gr.query();
   while(gr.next()){
      //Close any records that have not been updated in 'pn' number of days
      //Date difference calculated based on specified schedule
      var dif = sched.duration(gr.sys_updated_on.getGlideObject(), actualDateTime).getDayPart();
      if(dif >= pn){
         gr.state = 7;
         gr.active = false;
         //gr.comments = 'Incident automatically closed after ' + pn + ' days in the Resolved state.';
         gr.update();
      }
   }
}

Schedule-based Incident Autoclose Script (BY HOURS!)

The fact that ‘Number of days’ is actually the number of 24 hour periods ends up being pretty confusing for people sometimes. As I’ve dealt with this issue several times now, I think the best way to do incident autoclose based on a schedule is to do the autoclose on an hourly basis. This eliminates the ‘Number of days’ confusion and it also gives you the added benefit of a bit more granularity. If you use this script, you should also make sure to change the ‘glide.ui.autoclose.time’ property description to hours instead of days.
// This script automatically closes incidents that are resolved
// and haven't been updated in a chosen number of hours. You
// can set this number as a property in System Properties.
// If you want a comment placed in the incident, uncomment the
// 'gr.comments' line below.

var ps = gs.getProperty('glide.ui.autoclose.time');
var pn = parseInt(ps);

if(pn > 0){
   //Get a schedule by name to calculate duration
   var schedRec = new GlideRecord('cmn_schedule');
   schedRec.get('name', '8-5 weekdays excluding holidays');
   if (typeof GlideSchedule != 'undefined')
      var sched = new GlideSchedule(schedRec.sys_id);
   else
      var sched = new Packages.com.glide.schedules.Schedule(schedRec.sys_id);
   
   //Get the current date/time in correct format for duration calculation
   var actualDateTime = new GlideDateTime();
   actualDateTime.setDisplayValue(gs.nowDateTime());
   
   //Query for resolved incident records
   var gr = new GlideRecord('incident');
   gr.addQuery('state', 6);
   gr.query();
   while(gr.next()){
      //Close any records that have not been updated in 'pn' number of hours
      //Date difference calculated based on specified schedule
      var difDay = sched.duration(gr.sys_updated_on.getGlideObject(), actualDateTime).getDayPart()*24;
      var difHour = sched.duration(gr.sys_updated_on.getGlideObject(), actualDateTime).getDurationValue().split(':')[0].substr(-2);
      var dif = difDay + parseInt(difHour.replace(/^[0]+/g,""));
     
      if(dif >= pn){
         gr.state = 7;
         gr.active = false;
         //gr.comments = 'Incident automatically closed after ' + pn + ' hours in the Resolved state.';
         gr.update();
      }
   }
}