Inline Scripting in Workflow Studio

neil_b
Tera Guru

Hi,

 

I am in the workflow studio, and I have a Look Up Records step. I want to retrieve the data from the Look Up Records step and pass it into my flow variable (set up as type: String) as a comma separated list. Can someone help me with my inline script and let me know why my script isn't working? I want the comma separated list because I am trying to get a list of serial numbers separated by commas to include on a notification that gets triggered using an event to a user group for machines with expired licenses. Once I am able to populate my flow variable with a comma separated list, I intend to pass it to my event as parm 2. 

 

var gr = fd_data._10__look_up_records.records;
var count = fd_data._10__look_up_records.count;
var serialNumberList = [];
if(count > 0 & !gr.hasNext()){
    gr = new GlideRecord(gr.getTableName());
	gr.addEncodedQuery(gr.getEncodedQuery());
	gr.query();
}
  while(gr.next()){
	serialNumberList.push(gr.getValue('u_serial_number'));
 }
  var serialNumberList_array = serialNumberList.join();

return "serialNumberListIN"+serialNumberList_array+"";

 

Here is my flow:

flow.png

1 ACCEPTED SOLUTION

@neil_b 
Sorry the error you are getting now is because I'm crossing up traditional workflows and Workflow Designer. Because we are in workflow designer you don't have scratchpad because it has Flow Variables. We can use dot walking to access the flow variable directly, this is also why current.u_serial_number didn't work.

Try this script:

var currentSN = fd_data._9__for_each.item.u_serial_number; 

var gr = new GlideRecord('asset_report_table');
gr.addEncodedQuery('sys_created_onBETWEENjavascript:gs.beginningOfThisMonth()@javascript:gs.endOfThisMonth()^asset_report_table.u_serial_number='+currentSN);
gr.query();

if(!gr.hasNext()) {
     var snList = fd_data.flowVariables.variableName; //replace variableName with the name of your flow variable
     if (!gs.nil(snList)) {
          fd_data.flowVariables.variableName = snList +"," + currentSN;
     } else {
          fd_data.flowVariables.variableName = currentSN;
     }
}

 

Given that we are now setting the flow variable as part of the script your Set Flow Variable step is no longer necessary.

With regard to how you are sending emails it might be easiest to actually create a grouped array of the serial numbers. Then you could perform a for each loop on the groups and the serial numbers under the group in the array would already be aligned with the proper user. I haven't specifically used this method with a flow variable.

You could try this:
Make sure you flow variable is of type JSON then try this script:

var snListArray = {};
var currentSN = fd_data._9__for_each.item.u_serial_number;

var gr = new GlideRecord('asset_report_table');
gr.addEncodedQuery('sys_created_onBETWEENjavascript:gs.beginningOfThisMonth()@javascript:gs.endOfThisMonth()^asset_report_table.u_serial_number='+currentSN);
gr.query();

while (gr.next()) {
     var responsibleUser = fd_data._9__for_each.item.getDisplayValue('responsibleUser'); // update this to reference the correct attribute, it may be something like fd_data._9__for_each.item.location.getDisplayValue('responsibleUser') if the responsible user isn't directly associated with the record in the loop
     if (!snListArray[responsibleUser]) {
          snListArray[responsibleUser] = [];
     }
     snListArray[responsibleUser].push(currentSN);
}

fd_data.flowVariables.variableName = snListArray; // I haven't done this specifically before so you may have to use JSON.stringify(snListArray)


This would then set your flow variable to a JSON array which you could then use as a grouped array where the responsible user is the group name. Again I've never applied this method in the way you are using it I've only used it inside scripts. If you are able to figure out how to use the grouped array in a for each item I'd appreciate sharing how (might work better if you use a flow variable type of array.object but not sure if the script would change in that case).

Editing to add an additional thought: If you used the responsible users email address as the group name rather than the display value as in my example script that would allow you to reference it directly when generating the email which might save you the complication of having to look it up in that step. If you need more than one attribute of the responsible user such as using their name for a Hello Name! start to the email then using the responsible users sys_id could also simplify the process of retrieving the full user record as you could use it in a .get() or lookup record step.

View solution in original post

21 REPLIES 21

John Gilmore
Giga Guru

I think you just need to be using "&&" in your if condition. The "" may also be unecessary at the end.

var gr = fd_data._1__look_up_records.records;
var count = fd_data._1__look_up_records.count;
var serialNumberList = [];

if (count > 0 && !gr.hasNext()) {
gr = new GlideRecord(gr.getTableName());
gr.addEncodedQuery(gr.getEncodedQuery());
gr.query();
}

while (gr.next()) {
serialNumberList.push(gr.getValue('u_serial_number'));
}

var serialNumberList_array = serialNumberList.join();
return "serialNumberListIN" + serialNumberList_array;

John Gilmore
Giga Guru

@neil_b It may also be that the gr.getTableName() and/or gr.getEncodedQuery() aren't available on the fd_data._1__look_up_records.records object.

You can us a typeof method check this and output a string to indicate if this is the case. The following code would replace your existing if statement.

var hasTableName = typeof gr.getTableName === "function";
var hasEncodedQuery = typeof gr.getEncodedQuery === "function";
var needsRequery = (count > 0 && (!gr.hasNext() || !hasTableName || !hasEncodedQuery));

if (needsRequery) {
    if (hasTableName && hasEncodedQuery) {
        gr = new GlideRecord(gr.getTableName());
        gr.addEncodedQuery(gr.getEncodedQuery());
        gr.query();
    } else {
        gs.warn('gr object does not support getTableName() or getEncodedQuery()');
        return "serialNumberListIN";
    }
}


It would be helpful to see the flow from the look up records step through the script, you may simply be referencing the look up records output incorrectly but we have no way of knowing with the information provided.

@John Gilmore I appreciate your feedback. I have included a screenshot of the flow and added it to my original post above for everyone to see.
flow.png

 

To explain how the flow is setup, I am first doing a Look Up in the cmn_location table to find the correct location. After finding the correct location, I'm doing a For Each to grab every single Serial Number in that location. Then I do another Look Up in our requests table to see if a Serial Number has been reported on a request for license renewal. If it doesn't have any requests submitted within the last 30 days, then set flow variables. This is where my script starts, to assign a flow variable a list of Serial Numbers that have not been reported on recently. 

 

I don't know if I need to do the Lookup from step 8, or step 10 within the script. I think my challenge is that the Lookup from step 10 returns 0 records, so I need to be able to somehow get the script to do a Lookup in step 8, compare if there is a matching record in the Lookup in step 10, and if not, add the Serial Number to the variable.

 

Does this make sense?

Zach N
Tera Guru

Hello!

The Look Up Records action returns a collection of GlideRecord objects as documented here. This means you shouldn't need to perform a lookup or query, you can just move straight to gr.next(). Here is an updated script:

 

var gr = fd_data._1__look_up_records.records;
var serialNumberList = [];

while (gr.next()) {

    serialNumberList.push(gr.getValue('u_serial_number')):
}

return 'serialNumberListIN' + serialNumberList.join(',');

 

I've also removed the count if statement, as I'd highly recommend that you move it to your top level flow, otherwise it can become confusing when if logic is obfuscated by scripts in your flow.

Hope that helps! See attached of examples performing this same process but using incidents and incident numbers.

Hi @Zach N I appreciate the suggestion! After further review, I think my issue is that my Lookup returns 0 records. Please see my flow below:

flow.png

I am first doing a Look Up in the cmn_location table to find the correct location. After finding the correct location, I'm doing a For Each to grab every single Serial Number in that location. Then I do another Look Up in our requests table to see if a Serial Number has been reported on a request for license renewal. If it doesn't have any requests submitted within the last 30 days, then set flow variables. This is where my script starts, to assign a flow variable a list of Serial Numbers that have not been reported on recently. 

 

I don't know if I need to do the Lookup from step 8, or step 10 within the script. I think my challenge is that the Lookup from step 10 returns 0 records, so I need to be able to somehow get the script to do a Lookup in step 8, compare if there is a matching record in the Lookup in step 10, and if not, add the Serial Number to the variable.