GlideSchedule.add() behaving inconsistently for identical off-schedule timestamps

Steve Martin
Giga Contributor

I am facing an issue with the following scheduled script execution code, where it runs fine for one case record but fails for other records. When I run the same script for the failing case record, it works fine. Failing means the script will move the cases that are in the 'Awaiting Info' state for more than 5 business days to the 'Resolved state'. Instead of moving after 5 days, it moved it within the 16 hours after the case was moved to 'Awaiting Info'.

Code:
======

// =============================================================
// Auto-Resolve "Awaiting Info" Cases After 5 Business Days
// Using 9-hour business day logic and schedule-based time
// NO timezone override, runs daily at 00:00
// =============================================================

var LOG = '[AutoResolve Awaiting Info] ';

// ================================
// Load system properties (OOB pattern)
// ================================
var scheduleID = gs.getProperty('csm.schedule.auto.close');
var testerSupport = gs.getProperty('csm.tester.support.group');
var testerSupportCE = gs.getProperty('csm.tester.support.group.ce');
var testerSupportIP = gs.getProperty('csm.tester.support.group.in.person');
var envAdmins = gs.getProperty('csm.env.admin.group');

// Validate schedule ID before continuing
if (!scheduleID)
    gs.error(LOG + 'System property csm.schedule.auto.close is not set. Job will continue but cannot resolve cases.');

// ================================
// Build list of the FOUR tester groups
// Only these groups are processed.
// ================================
var testerGroups = [];
if (testerSupport) testerGroups.push(testerSupport);
if (testerSupportCE) testerGroups.push(testerSupportCE);
if (testerSupportIP) testerGroups.push(testerSupportIP);
if (envAdmins) testerGroups.push(envAdmins);

// ================================
// Load schedule once (best practice)
// Do NOT set timezone in script.
// ================================
var schedule = new GlideSchedule();
schedule.load(scheduleID);

// ================================
// PRECOMPUTE DURATION (moved outside loop)
// 5 business days × 9 working hours → 45 working hours
// Converted to milliseconds → GlideDuration
// ================================
var days = 5;
var hours = 9;
var totalMs = days * hours * 60 * 60 * 1000;
var duration = new GlideDuration(totalMs);

// ================================
// Query cases in Awaiting Info (state=18)
// Only active cases with a timestamp
// ================================
var gr = new GlideRecord('sn_customerservice_case');
gr.addQuery('state', 18); // Awaiting Info
gr.addQuery('active', true);
gr.addNotNullQuery('u_awaiting_info_since'); // Must have tracking timestamp
gr.query();

var now = new GlideDateTime(); // Current UTC time
var processed = 0;
var resolvedCount = 0;

// ================================
// Resolution Notes Template
// "{name}" dynamically replaced with consumer display name
// ================================
/*var resolutionTemplate =
   "Hello {name},\n\n" +
    "We haven't heard back from you since our last reply, so we are now resolving this case due to inactivity.\n" +
    "If you still require assistance, please simply reply to this email! Replying will automatically reopen the case, and we will be happy to resume helping you.\n\n";
  "Thank you!\n" +
   "uTest Support Team";*/

// ================================
// MAIN PROCESSING LOOP
// ================================
while (gr.next()) {
    processed++;

    var groupId = String(gr.assignment_group);

    // Skip cases NOT belonging to the four tester groups
    var isTesterGroup = testerGroups.indexOf(groupId) !== -1;
    if (!isTesterGroup)
        continue;

    // Timestamp when case entered "Awaiting Info"
    var sinceValue = gr.getValue('u_awaiting_info_since');
    var sinceGdt = new GlideDateTime(sinceValue);

    // Compute due date based on schedule (respects holidays & working hours)
    var dueDate = schedule.add(sinceGdt, duration);

    // If due date has passed (or equals now) → auto-resolve
    if (dueDate.before(now) || dueDate.equals(now)) {

        // Set Resolution Code (choice value "8")
        gr.setValue('resolution_code', '8');

        // Personalize message using consumer's display name
        //var consumerName = gr.consumer ? gr.consumer.getDisplayValue() : "Tester";
        //var notes = resolutionTemplate.replace("{name}", consumerName);
        var notes = "We haven't heard back from you since our last reply, so we are now resolving this case due to inactivity.\n" +
            "If you still require assistance, please simply reply to this email! Replying will automatically reopen the case, and we will be happy to resume helping you.\n\n";
        gr.setValue('close_notes', notes);

        // Move state to Resolved (6)
        // OOB BR `mark_resolved` will update resolved_by and resolved_at
        gr.setValue('state', 6);

        // Add audit trail
        //gr.work_notes = '[AutoResolve] Case auto-resolved after 5 business days of no response.';

        gr.update();
        resolvedCount++;
    }
}

// Summary for system logs
gs.info(LOG + 'Execution complete. Processed=' + processed +
    ', Auto-resolved=' + resolvedCount);

 

0 REPLIES 0