Business Rules - Incident Autoclose based on Schedule not working as expected
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-19-2024 10:52 AM - edited 04-01-2024 04:25 PM
Hi,
I am trying to write a code where resolved Incidents will have their state updated to Closed after 10 Business Days based on the Schedule: 8-5 weekdays excluding holidays.
I have referred to the ServiceNow Developer documentation below where its mentioned there is a need to query using whenNext(GlideDateTime time, String timeZone).
https://developer.servicenow.com/dev.do#!/reference/api/utah/server/c_GlideScheduleScopedAPI
testScript();
function testScript() {
var now = new GlideDateTime(); //current date and time
var sched = new GlideSchedule("<sys_id>"); // Use a cmn_schedule sys_id
if (sched.isInSchedule(now)){
gs.info('We are in an active schedule window so whenNext() is not helpful');
} else{
gs.info('Not currently in schedule so call whenNext()');
var msUntilNext = sched.whenNext(new GlideDateTime(), 'US/Pacific');
gs.info('Next schedule starts in '+msUntilNext+' milliseconds');
}
}
\\ Output [schedule inactive)]:
\\ *** Script: Not currently in schedule so call whenNext()
\\ *** Script: Next schedule starts in -1 milliseconds
Below is the code that I have came up with and I need help as during testing some of the resolved tickets are getting closed earlier although they have yet to pass/hit 10 Business Days based on the schedule 8-5 weekdays excluding holidays.
var ps = gs.getProperty('glide.ui.autoclose.time');
var pn = parseInt(ps);
// Check if autoclose time is enabled
if (pn > 0) {
// Query for the schedule record
var schedRec = new GlideRecord('cmn_schedule');
schedRec.get('name', '8-5 weekdays excluding holidays');
// Check if the schedule record exists and the GlideSchedule object is defined
if (schedRec.isValid() && typeof GlideSchedule != 'undefined') {
var sched = new GlideSchedule(schedRec.sys_id);
var now = new GlideDateTime();
// Debugging: Log the current date and time
gs.info('Current date and time: ' + now.getDisplayValue());
// Query for the incidents
var gr = new GlideRecord('incident');
gr.addQuery('incident_state', 6);
gr.query();
// Check if the incident record exists
if (gr.hasNext()) {
gs.info('Number of resolved incidents: ' + gr.getRowCount());
// Check if we are currently within the schedule window
if (sched.whenNext(now, 'GMT') <= 0) {
gs.info('We are in an active schedule window. Closing incidents...');
while (gr.next()) {
var resolvedDate = new GlideDateTime(gr.resolved_at);
//Log the resolved date of the incident
gs.info('Resolved date for incident ' + gr.number + ': ' + resolvedDate.getDisplayValue());
// Calculate the due date based on resolved date and schedule
var dueDate = sched.add(resolvedDate, 10, '');
//Log the due date for the incident
gs.info('Due date for incident ' + gr.number + ': ' + dueDate.getDisplayValue());
Log the schedule end date for the incident
gs.info('Schedule end date for incident ' + gr.number + ': ' + getScheduleEndDate(resolvedDate, 7).getDisplayValue());
// Check if the due date falls within the schedule
if (sched.isInSchedule(dueDate)) {
// Close the incident
gr.state = 7;
gr.active = false;
gr.update();
gs.info('Incident ' + gr.number + ' closed on ' + now.getDisplayValue());
} else {
gs.info('Incident ' + gr.number + ' due to be closed outside of schedule window.');
}
}
} else {
var msUntilNext = sched.whenNext(now, 'GMT');
gs.info('Not currently in schedule window. Next schedule starts in ' + msUntilNext + ' milliseconds.');
}
}
}
}
}
Thank you.. 😀
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-19-2024 12:43 PM
Hi, I would take a slightly different approach and simplify the solution by adding a new date/time field to your Incident or task table and use this to set a set a close date using a before BR based on your state field.
Your scheduled job then becomes a simple check for tasks that have a close date of yesterday - I assume the schedule will run daily just after midnight. I would think this was more efficient and also provides clear visibility to everyone involved as to when a specific task is expected to close.
Untested but something like
var startDate = new GlideDateTime();
var days = 10;
var busHours = 8.5;
var myDuration = new GlideDuration(60 * 60 * busHours * 1000 * days);
gs.info(myDuration);
var schedule = new GlideSchedule('090eecae0a0a0b260077e1dfa71da828');
var closeDate = schedule.add(startDate, myDuration);
gs.info('closeDate ' + closeDate);
current.yourAutoCloseDateField = closeDate;
var incCheck = new GlideRecord('incident');
incCheck.addEncodedQuery('yourAutoCloseDateFieldONYesterday@javascript:gs.beginningOfYesterday()@javascript:gs.endOfYesterday()');
incCheck.query();
while(incCheck.next()) {
incCheck.state = 7;
incCheck.active = false;
incCheck.comments = 'Auto closed incident';
incCheck.update();
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-19-2024 12:50 PM
Try this :
autoclose();
function autoclose() {
var gr = new GlideRecord('your_case_table');
gr.addEncodedQuery('Your_query_means_resolved_case');
gr.query();
while (gr.next()) {
var firstDT = gr.resolved_at;
var scheduleID = gs.getProperty('24*5_Schedule');//You can change this with a sys_id of 24*5 schedule
var cdate = gs.nowDateTime();
var dc = new DurationCalculator();
dc.setSchedule(scheduleID);
var diff = dc.calcScheduleDuration(firstDT, cdate);
//gs.info("amu:"+diff+gr.number);
if(diff > 864000) //10 days==864000 seconds
{
gr.state = 3;//You can check your close value
gr.active = false;
gr.comments = 'Case automatically closed after 10 business days in the Resolved state';
gr.update();
}
}
}
☑️ Please mark responses as HELPFUL or ACCEPT SOLUTION to assist future users in finding the right solution....
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
03-22-2024 11:39 AM
ok, I did tested this out but do I need to change the default value for the below properties which is 7?
glide.ui.autoclose.time
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
04-01-2024 04:35 PM - edited 04-01-2024 04:48 PM
Hi,
Just an update..
I tested out with the code below and somehow it is not working as expected where the incidents are still getting closed based on the value of the system properties - glide.ui.autoclose.time which is 10 calendar days..
Anything else that I missed out?
// This script automatically closes incidents that are resolved
// and haven't been updated in the specified number of days.
// This number is a property in System Properties.
// To place a comment in the incident, uncomment the "gr.comments" line.
autoCloseIncidents();
function autoCloseIncidents() {
var ps = gs.getProperty('glide.ui.autoclose.time');
var pn = parseInt(ps);
var queryTime = new GlideDateTime();
queryTime.addDaysUTC(-pn);
var i = 0;
if (pn > 0) {
var sched = new GlideSchedule('090eecae0a0a0b260077e1dfa71da828');
var d = new GlideDateTime();
var daycount = 1;
var countday = 1;
d.setDisplayValue(gs.daysAgoStart(countday).toString());
do {
if (sched.isInSchedule(d)) {
gs.log(d.toString() + ' is in Schedule');
countday++;
daycount++;
} else {
gs.log(d.toString() + ' is not in Schedule');
countday++;
}
d.setDisplayValue(gs.daysAgoStart(countday).toString());
} while (!sched.isInSchedule(d) || daycount != pn);
gs.log('Number of calendar days since Incident ticket resolution: ' + countday);
gs.log('Date of resolved Incident tickets: ' + gs.daysAgoStart(countday));
var gr = new GlideRecord('incident');
gr.addQuery('state', '6');
gr.addQuery('resolved_at', '<', d);
if (gs.getProperty('com.snc.incident.autoclose.basedon.resolved_at', 'false') === 'true') {
gr.addQuery('resolved_at', '<', queryTime);
} else {
gr.addQuery('sys_updated_on', '<', queryTime);
}
if (pm.isActive('com.snc.incident.mim')) {
var mim = gr.addNullQuery('major_incident_state');
mim.addOrCondition('major_incident_state', '!=', new
sn_major_inc_mgmt.MajorIncidentTriggerRulesSNC().MAJOR_INCIDENT_STATE.ACCEPTED);
}
if (pm.isActive('com.sn_ot_inc_mgmt')) {
gr.addEncodedQuery('sys_class_nameNOT IN' + new TableUtils('sn_ot_incident').getAllExtensions().toArray().join());
}
gr.query();
while (gr.next()) {
i++;
gs.info('Incident closed: ' + gr.number);
gr.incident_state = IncidentState.CLOSED;
gr.state = IncidentState.CLOSED;
//gr.comments = 'Incident automatically closed after ' + pn + ' days in the Resolved state.';
gr.active = false;
gr.closed_by = gr.resolved_by;
gr.setWorkflow(false);
gr.update();
}
gs.log('Number of Incidents Closed:' + i);
}
}