Help needed with below script

dvelloriy
Kilo Sage

Hello Community,

I need some help with below code.

Requirement: Populate Due date on SC Task records from delivery time (in Business days) specified on catalog item.

 

I have created below script, it is working as expected however i need to account for just business days.

So if a request is created today for "Ask a Question" item with delivery date (5 business days), due date on task should be July 16th.

 

Before insert >> Condition - Item.delivery_time is not empty

 

Script: 

var intDuration = current.cat_item.delivery_time.dateNumericValue();

var gdtDueDate = new GlideDateTime();

gdtDueDate.add(intDuration);

current.due_date = gdtDueDate;

current.update();

 

 

Please advise,

1 ACCEPTED SOLUTION

Hello @dvelloriy ,

Here is the updated code. Give it a try.

(function executeRule(current, previous /*null when async*/ ) {

    // Add your code here
    var duration = parseInt(current.cat_item.delivery_time.getDisplayValue());
    var todayDate = new GlideDateTime();
    var dueDate = addDays(todayDate, duration);
    current.due_date = dueDate;

    function addDays(todayDate, duration) {
        var count = 0;
        var gdt = new GlideDateTime(todayDate);
        while (count < duration) {
            gdt.addDaysLocalTime(1);
            var dayWeek = gdt.getDayOfWeekLocalTime();
            if (dayWeek != 6 && dayWeek != 7) { // 6 = Saturday, 7 = Sunday
                count++;
            }
        }
        return gdt;
    }
})(current, previous);

 

If this response resolves your query, kindly mark it as both helpful and correct.

Thanks,

Alka

View solution in original post

8 REPLIES 8

Alka_Chaudhary
Mega Sage
Mega Sage

Hello @dvelloriy ,

 

Please try the code below in your script. It will add the delivery time (business days only) to today's date.

 

(function executeRule(current, previous /*null when async*/) {

// Add your code here
	var days = parseInt(current.cat_item.delivery_time.getDisplayValue());
	var getDueDate = new GlideDateTime();
	var duration = new GlideDuration(1000*60*60*8*days);
	var schedule = new GlideSchedule('08fcd0830a0a0b2600079f56b1adb9ae');//8-5 weekdays Schedule sys id
	var dueDate = schedule.add(getDueDate,duration);
	current.due_date = dueDate;

})(current, previous);

 

If this response resolves your query, kindly mark it as both helpful and correct.

Thanks,

Alka

Hi Alka,

Results are better now but not accurate.

I just created a request with catalog item having delivery time of 2 business days.

due date on task came as 07/11/2024 16:10:54 

Ideally if its 2 business days, and i am creating the request now,

it should come as 07/12/2024 9:10:54

Please advise. i think we might have to update the schedule..

Hello @dvelloriy ,

Here is the updated code. Give it a try.

(function executeRule(current, previous /*null when async*/ ) {

    // Add your code here
    var duration = parseInt(current.cat_item.delivery_time.getDisplayValue());
    var todayDate = new GlideDateTime();
    var dueDate = addDays(todayDate, duration);
    current.due_date = dueDate;

    function addDays(todayDate, duration) {
        var count = 0;
        var gdt = new GlideDateTime(todayDate);
        while (count < duration) {
            gdt.addDaysLocalTime(1);
            var dayWeek = gdt.getDayOfWeekLocalTime();
            if (dayWeek != 6 && dayWeek != 7) { // 6 = Saturday, 7 = Sunday
                count++;
            }
        }
        return gdt;
    }
})(current, previous);

 

If this response resolves your query, kindly mark it as both helpful and correct.

Thanks,

Alka

MackI
Kilo Sage

 

// Calculate due date (same logic as before)
var intDuration = current.cat_item.delivery_time.dateNumericValue();
var gdtDueDate = new GlideDateTime();
var businessDaysToAdd = Math.ceil(intDuration / (1000 * 60 * 60 * 24));

while (businessDaysToAdd > 0) {
gdtDueDate.addDays(1);
if (!gs.isWeekday(gdtDueDate)) {
continue;
}
businessDaysToAdd--;
}

// Consider holidays (if applicable)
var holidaySchedule = 'your_holiday_schedule_name';
while (new GlideSchedule(holidaySchedule).isInSchedule(gdtDueDate)) {
gdtDueDate.addDays(1);
}

// Set workflow to false before updating
current.setWorkflow(false);
current.due_date = gdtDueDate;

// Update the task record
current.update();

 

 

 

 

 

Explanation
1. Get Delivery Time: Same as before, we get the delivery time in milliseconds.
2. Convert to Business Days:
* Divide the milliseconds by the number of milliseconds in a day to get the total number of days.
* Use Math.ceil() to round up to the nearest whole number, ensuring we count partial days as full business days.
3. Iterate and Skip Weekends:
* Use a while loop to keep adding days until we've accounted for the required number of business days.
* Inside the loop:
* Add one day to the current gdtDueDate.
* Use gs.isWeekday(gdtDueDate) to check if the new date is a weekend.
* If it's a weekend, continue skips to the next iteration of the loop without decrementing businessDaysToAdd.
4. Account for Holidays (Optional):
* Replace 'your_holiday_schedule_name' with the name of the schedule you've created in ServiceNow to define your organization's holidays.
* Use a while loop and isInSchedule() to check if the date falls on a holiday. If it does, increment the date until it's not a holiday.
5. Set Due Date: Assign the final calculated gdtDueDate to the current.due_date field and update the record.

 


Explanation of Changes


The only change made in this script is the addition of the line current.setWorkflow(false); right before the current.update() line.


Here's why this is important:


Isolates Update: By setting current.setWorkflow(false), we ensure that the subsequent update (current.update()) is performed in isolation from the workflow context.
Prevents Conflicts: This prevents the update from triggering any other business rules or workflows that might be associated with the task table.
Ensures Accuracy: It guarantees that the calculated due date is set correctly without interference from other processes.
Optimizes Performance: It's more efficient to make a single update after setting the due date and disabling the workflow, rather than updating multiple times within the workflow context.
Key Points to Remember


Scope: The setWorkflow(false) method only affects the current update operation. Subsequent actions in the script or workflow will operate normally.
Order: It's crucial to place current.setWorkflow(false) immediately before the current.update() line to ensure that the update itself is the only action performed outside the workflow context.
Completeness: If you need to make multiple changes to the record, do so before calling current.update(). Once the record is updated, the workflow context is restored, and subsequent updates will trigger business rules and workflows.

MackI | ServiceNow Developer | 2 *Mainline Certification | LinkedIn Top IT Operation Voice 2023 | Sydney,Australia