Wait for condition - is not proceeding with the work flow

Lavi Buchnik
Giga Contributor

Hi,

I'm working on a work flow which basically do this:

- Create a change

- Wait for condition, waits till change status is "implemented" (manually by a user)

- Once "implemented" should run a task 

The problem is that "wait for condition" script is getting the right value (answer = true) but not proceeding to the task.

Wait for condition script is this:

// This script check for if the change was implemented
answer = ifScript();

function ifScript() {
    var gr = new GlideRecord('change_request');
    gr.addQuery('number', workflow.scratchpad.chgNumber);
    gr.query();
    while (gr.next()) {
        if (gr.state == -1) {
            answer = true;
        } else {
            answer = false;
        }
    }
}

Tracing for the work flow and code, "wait for condition" is finished to run. the code gets to "answer = true" line.

but not clear why the flow is not proceeding. 

Also, inside the "Wait for condition" "When to run" part, the "Condition" is "Standard" type and its value is: 

activity.result == 'true'

On documentation: https://docs.servicenow.com/bundle/paris-servicenow-platform/page/administer/workflow-activities/reference/r_WaitForCondition.html#d2183351e150

It says this: 

States: The activity state tells the workflow engine what to do with the activity.

Which seems like what I'm missing, but not clear to me how to implement "States".

Thanks in advance,

Lavi

1 ACCEPTED SOLUTION

Hi Lavi,

I think the "Wait for condition" condition script is incorrect. Please modify it as below:

answer = ifScript();

function ifScript() {
    var chgGR = new GlideRecord('change_request');
    chgGR.addQuery('number', workflow.scratchpad.chgNumber);
    chgGR.query();
    if (chgGR.next()) {
        if (chgGR.getValue('state') == -1) {
            return true;
        } else {
            return false;
        }
    }
}

In your original code you are setting answer = true or false with in the if script, but the function does not return anything, so answer variable is getting set to undefined and the true value is overwritten.


Also please check if wait for condition, always condition is defined like this.
find_real_file.png

Let us try a different way of writing the business rule.

find_real_file.png

find_real_file.png

(function executeRule(current, previous /*null when async*/ ) {
    var wkfw = new Workflow();
    var context = wkfw.getContexts(current.parent);
    while (context.next()) {
        if (context.getValue('state') == 'executing') {
            new Workflow().broadcastEvent(context.getValue('sys_id'), 'update');
        }
    }
})(current, previous);

 

Hopefully this helps!

 

--

Thanks and regards,

Subrahmanyam

View solution in original post

11 REPLIES 11

Lavi Buchnik
Giga Contributor

Hi,

So I tested it as follows:

- Added a BR under change_request table

    - The BR is running "After" (I also tested before and sync) an "Update"

    - The Filter Conditions is: State "changes to" "Implement"

    - Under "Advanced" I used your script as is, as it make sense for what I need (my RITM is linked to the same work flow table).

  - But still, the Wait for condition is still getting the right "state", but not moving on with the workflow to the running task.

- I also tried to manually change some data in the request Item itself, but it didn't push forward the workflow.

Not clear why.

Thanks,

Lavi

 

Hi Lavi,

If you use the script provided by Sam as is, it will not work for you as mentioned by Sam already. He just provided it as an example for you to understand.
In your case, an update on change_request table should nudge the workflow running on a particular request item.

In the example BR script provided by Sam (which you are utilizing as is), you need to modify below line.

 grRitm.get('sys_id', current.request_item);

 

You need to check how the change_request and and request item are linked in your case.
Are you populating parent field in change_request with the sys_id of the RITM on which workflow is running while creating a change? If this is the case, then you should use, current.getValue("parent") instead of "current.request_item".

If you are creating the relationship in a different manner or using a different field, you need to modify the BR accordingly as per your scenario.

If you are just creating a change in RITM workflow, but not not relating change_request and RITM in any manner, you cannot nudge the RITM workflow after change moves to implement state.

 

If this is helpful and works for you, mark Sams reply as solution and kindly mark my comment as helpful.

 

Thanks and regards,

Subrahmanyam Satti





 

Hello Subrahmanyam Satti,

 

I understand what you are saying. but it is not clear to me for what is the exact link between the change request to the request item.

This is the task that create the change request (not a code that I wrote), if you can help to understand the RITM link here:

var standard_change_template= new GlideRecord('std_change_record_producer');
standard_change_template.addQuery('name', 'Firewall Rules [Create, Update]');
standard_change_template.query();
if (standard_change_template.next())
 {
 task.std_change_producer_version=standard_change_template.current_version;
 }
task.applyTemplate('Firewall Rules [Create, Update]');
task.cmdb_ci = current.cmdb_ci; // copy the Configuration item if exists
task.business_service = current.variables.change_id;
task.type = 'standard';
task.assignment_group = current.assignment_group;
//task.assigned_to = current.opened_by;
task.description = 'Tufin - open request automation';
task.short_description = current.short_description + ' to ' + current.variables.customer_code; current.variables.customer_code;
task.parent = current.sys_id;
task.u_customer_downtime = 2;
task.u_disable_monitoring_alerts = 2;
task.state = -2;
/*var gdt = new GlideDateTime(gs.nowDateTime());
task.start_date = gdt;
var ed = new GlideDateTime(gdt);
ed.addDays(14);
task.end_date = ed;
task.assigned_to =current.opened_by;*/

// Create Variables dynamically according to items variables
var item_vars = new GlideRecord('sc_item_option_mtom');
item_vars.addQuery('request_item', current.sys_id);
item_vars.query();
while (item_vars.next()) {
var q_a = new GlideRecord('question_answer');
q_a.initialize();
q_a.table_name = 'change_request';
q_a.table_sys_id = task.sys_id;
q_a.question = item_vars.sc_item_option.item_option_new;
q_a.value = item_vars.sc_item_option.value;
q_a.order = item_vars.sc_item_option.order;
q_a.insert();
}

task.update();

workflow.scratchpad.chgNumber = workflow.info(task.number);
// additions to get change status
//workflow.scratchpad.taskID = task.setNewGuid();

//Create Change Request now


I tested (just in case) the change you suggested (current.getValue("parent") instead of "current.request_item") but it didn't work.

Thanks,
Lavi

Hi Lavi,

I looked into the your initial post too to see if we missed anything..
The problem you are facing is because of the Always condition code you have given.
In the "Wait for condition" activity, go to the "Always" condition, and then in the "When to run" section, for condition type "standard", the condition should be given as just "true" (without quotes i.e true).

Reason: "Wait for condition" activity never sets the result after it executes. That is why the result will always be empty and and you will not go past the wait for condition activity. System shows that it executed the activity, but the transition to next activity will not happen.

Also in the after update business rule written on the change request table, please include below code. Do not use get() method to do force updates directly. [Due to the nature of get method, you could create some unintended blank records]

(function executeRule(current, previous /*null when async*/ ) {
    // Force update of RITM when change moves to implement state
    var grRitm = new GlideRecord('sc_req_item');
    grRitm.addQuery('sys_id', current.getValue("parent"));
    grRitm.query();
    if(grRitm.next()){
        grRitm.setForceUpdate(true);
        grRitm.update();
    }
})(current, previous);

Also I noticed that, in the script block given by you, you have below line.

workflow.scratchpad.chgNumber = workflow.info(task.number);

The workflow.info() method records the information messages in the workflow context records workflow log tab. In prod, if you want to limit info message logging, just change the line to 

workflow.scratchpad.chgNumber = task.number;

 

After doing these changes, test the workflow and after RITM workflow generate change request, go to change request form and move it to implement state manually.

And then go to the tab where you opened workflow context diagram for the existing RITM and refresh it, you should see that it proceeds and move further.

 

Thanks and regards,

Subrahmanyam Satti

Hi Subrahmanyam Satti,

First, thanks a lot for your time examining my problem.

I did all the changes you suggested:

1. Wait for condition --> When to run: I changed it to: activity.result == true (also tested just with true)

2. I changed the BR code with what you provided.

3. I updated workflow.info(task.number) to task.number

I tested it like 3 times, but still the workflow is not going forward. I also tested a manual change on the request item (which the BR is doing by forcing an update), and still the workflow is not proceeding.

Seems like there is something else missing or need a change.

Note that if (in my workflow) I'm connecting the "Create Task" which create the change, directly to the "Run script" (skipping "Wait for condition"), the "Run Script" is working fine. this just to test that there is no issue with the "Run script" part.

I know we are close to solve this puzzle, if you want to have an online session. please let me know when (really appreciate your efforts).

my email is: lavi.buchnik@exlibrisgroup.com

Thanks,

Lavi