When all the stories are closed then the demand is automatically closed using scheduled job

muneermajeed
Tera Contributor
Hi everyone,

I've created a scheduled job to automatically close Demands when all associated Stories are in a closed state. I'd like to get some feedback on the script, particularly regarding efficiency and best practices.

The script iterates through active Demands and checks the state of their related Stories. If all Stories are closed, the Demand is automatically closed and a closure note is added.

 

Here's the script 

    var demand = new GlideRecord('dmn_demand');
    demand.addActiveQuery(); 
    demand.query();

    while (demand.next()) {
        var demandSysId = demand.sys_id;

        var story = new GlideRecord('rm_story');
        story.addQuery('demand', demandSysId);
        story.query();

        var total = story.getRowCount();
        var close = 0;

        while (story.next()) {
            if (story.state == '3') {
                close++;
            }
        }

        if (total == close) {
            gs.log("All stories closed for demand: " + demand.number);
            demand.state = '9'; 
            demand.u_closure_note = 'All stories completed';
			demand.acceptance_criteria='All the stories of this demand is closed now ';
            demand.update();
        } else {
            gs.log(" open stories in demand: " + demand.number);
        }
    }
1 ACCEPTED SOLUTION

Ankur Bawiskar
Tera Patron
Tera Patron

@muneermajeed 

try this optimized version

1) use GlideAggregate to reduce nested queries

2) removed getRowCount()

3) use setWorkflow(false) and autoSysFields(false) to skip updating timestamp, disables business rules etc on update

4) use try catch block to handle exception

(function executeRule(current, previous) {
    var demandGr = new GlideRecord('dmn_demand');
    demandGr.addActiveQuery();
    demandGr.addQuery('state', '!=', '9'); // Skip already closed demands
    demandGr.query();

    while (demandGr.next()) {
        var storyAgg = new GlideAggregate('rm_story');
        storyAgg.addQuery('demand', demandGr.sys_id);
        storyAgg.addAggregate('COUNT');
        storyAgg.addQuery('state', '!=', '3'); // 3 = closed state
        storyAgg.query();

        if (storyAgg.next()) {
            var openStories = storyAgg.getAggregate('COUNT');
            if (openStories === 0) {
                closeDemand(demandGr);
            }
        }
    }

    function closeDemand(demand) {
        try {
            demand.setWorkflow(false); // Bypass workflows for bulk operations
            demand.autoSysFields(false); // Skip audit fields updates
            demand.state = '9';
            demand.u_closure_note = 'All stories completed';
            demand.acceptance_criteria = 'All stories for this demand are closed';
            demand.update();
            gs.info('[Demand Closure] Closed: ' + demand.number);
        } catch (e) {
            gs.error('[Demand Closure] Failed for ' + demand.number + ': ' + e);
        }
    }
})();

If my response helped please mark it correct and close the thread so that it benefits future readers.

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

View solution in original post

5 REPLIES 5

Ankur Bawiskar
Tera Patron
Tera Patron

@muneermajeed 

try this optimized version

1) use GlideAggregate to reduce nested queries

2) removed getRowCount()

3) use setWorkflow(false) and autoSysFields(false) to skip updating timestamp, disables business rules etc on update

4) use try catch block to handle exception

(function executeRule(current, previous) {
    var demandGr = new GlideRecord('dmn_demand');
    demandGr.addActiveQuery();
    demandGr.addQuery('state', '!=', '9'); // Skip already closed demands
    demandGr.query();

    while (demandGr.next()) {
        var storyAgg = new GlideAggregate('rm_story');
        storyAgg.addQuery('demand', demandGr.sys_id);
        storyAgg.addAggregate('COUNT');
        storyAgg.addQuery('state', '!=', '3'); // 3 = closed state
        storyAgg.query();

        if (storyAgg.next()) {
            var openStories = storyAgg.getAggregate('COUNT');
            if (openStories === 0) {
                closeDemand(demandGr);
            }
        }
    }

    function closeDemand(demand) {
        try {
            demand.setWorkflow(false); // Bypass workflows for bulk operations
            demand.autoSysFields(false); // Skip audit fields updates
            demand.state = '9';
            demand.u_closure_note = 'All stories completed';
            demand.acceptance_criteria = 'All stories for this demand are closed';
            demand.update();
            gs.info('[Demand Closure] Closed: ' + demand.number);
        } catch (e) {
            gs.error('[Demand Closure] Failed for ' + demand.number + ': ' + e);
        }
    }
})();

If my response helped please mark it correct and close the thread so that it benefits future readers.

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

Hello your solution is also fine but i think the solution which i was provided is easy to understand for the developer which have less knowledge of JavaScript (coding) but your solution is also fine thanks for your response 

@muneermajeed 

since you asked for optimized version, hence I shared the same.

I believe when the developer has good experience and knows what's the best practice, they should be able to understand the above code as well.

If my response helped please mark it correct and close the thread so that it benefits future readers.

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

Okay thanks brother 

bro please check the below i have face another issue related to the email notification please have a look and response if you have any idea 

https://www.servicenow.com/community/virtual-agent-forum/when-i-click-on-the-button-on-email-the-rec...