1
0
-1

Hi

I'm kinda struggling to get an array from sc_item_option_mtom table since it looks like nodeHelper doesn't return an array but a fist item in the list

E.g consider the following code

if (entity.tableName.toString().equalsIgnoreCase('sc_task')) {


    Wrappers.MapWrapper variables = nodeHelper.getReference('sc_item_option_mtom', 'request_item', entity.request_item.display_value)
}

Now if you try to execute variables.entrySet().forEach you won't be able to get all the variables, only the first one and forEach will simply allow you to iterate over properties in that first variable only

How do I get all variables for a given request item ID?


Thanks in advance


    CommentAdd your comment...

    1 answer

    1.  
      1
      0
      -1

      Alex Fernandez

      I had some time to dive into this one, and most of the time was spent on understanding how ServiceNow is handling this data.  

      Assume you want to transfer the variables of a Request Item  to Jira






      First step is to collect the variables from the request item, and then format it into the description (or do whatever is appropriate)



      To collect the variables, check out in the  Retrieve Catalog Variables  snippet, the function 'buildVariablesMap' which will iterate over all the options related to the requestItem, and retrieve both the question and the associated answer.

      This can be added to the replica by a statement like

      replica.variables = buildVariablesMap(entity.key)

      (The retrieve catalog variables snippet has an example outgoing sync)



      Exalate will transport this list to the other side (in this case Jira)

      The code to build the table as shown in the screenshot is pretty straightforward, leaning on the wiki rendering function of the description field.

      Build a table
      /*
      ** build a table from the variables
      */
      
      String result = "\n||Question||Value||\n"
      replica.variables?.each {
          result += "|${it.key}|${it.value}|\n"
      }
      
      issue.description  = result


      Given that the variables are a map, you can use it in many different ways

      Next up is - how to write the variables ...

      1. Francis Martens (iDalko)

        Added an 'UpdateVariables.groovy' logic which allows to update the variables.

        The method takes a request item number and a map.
        It checks for each option associated to the request item, if the question is in the map (key), and if the value of the option is different.  In case of a difference - it will update the request item option.


        if (entity.tableName == "sc_req_item") {
            def varMap = ["What was the original phone number?":"1234567" ]
            
            updateVariables(entity.key, varMap)
            
        }
      2. Alexander Lukashov

        Hi Francis


        Many thanks, that's exactly I was looking for

        Just few things I want to mention

        • For sc_item_option which contains a reference to a user in a value attribute you still need to implement a custom logic to resolve this reference otherwise you'll get a guid instead of display name
        • My tests showed that retrial of variables is kinda slow so I changed the method to have only one API call using tables join in ServiceNow table API. Maybe somebody will find it useful
        Map<String, String> buildVariablesMap(String entityNumber) {
            def Map<String, Object> result = [:]
        
        
            // lookup all options associated to this number
        
            def optionList = httpClient.get("/api/now/table/sc_item_option?sysparm_query=^!JOINsc_item_option.sys_id=sc_item_option_mtom.sc_item_option!^JOINsc_item_option_mtom.request_item=sc_req_item.sys_id!sys_id=e6f7defedb5e2010073c6693ca961940&sysparm_display_value=true&sysparam_fields=item_option_new,value")
            if (!optionList || !optionList.result) return null  // ignore if there are no results
        
        
            // For each of the options, lookup corresponding question and add to the result map
            optionList.result.each {
                if(it.value.toString().isEmpty()) return
        
                result.put(it.item_option_new.display_value, it.value)
            }
        
            return result
        
        }
      3. Francis Martens (iDalko)

        Nice - I was not aware of that capability.  Need to learn about join

      4. Alexander Lukashov

        Yeah, I wasn't aware about that as well (I'm completely new to ServiceNow), found it on some of the servicenow forums by accident

      5. Karen Jennings

        I kept running into a problem using outgoing example from here: Retrieve Catalog Variables.

        It was trying to pull ALL of the variables from all of the forms. By tweaking the ServiceNow outgoing script a little, and building the table in Jira to see the values, I was able to get it to pull ONLY those variables on the form submitted. 

        Once I narrowed it down, it was easy to look at both the table and the payload to figure out the syntax to map those variables to specific field in Jira. 


        Here is what I used for the ServiceNow outgoing sync:

        Map<String, String> buildVariablesMap(String request_item_number) {
            def Map<String, Object> result = [:]
         
           
            // lookup all options associated to this number
           
            def optionList = httpClient.get("/api/now/table/sc_item_option_mtom?sysparm_query=request_item.numberSTARTSWITH${request_item_number}")
            if (!optionList || !optionList.result) return null // ignore if there are no results

      6. Ariel Aguilar

        Hi Karen have you tried?:

        Map<String, String> buildVariablesMap(String requestItemNumber) {
            def Map<String, Object> result = [:]
         
           
            // lookup all options associated to this number
           
            def optionList = httpClient.get("/api/now/table/sc_item_option_mtom?sysparm_query=request_item.numberSTARTSWITH${requestItemNumber}")
            if (!optionList || !optionList.result) return null // ignore if there are no results

        Kind regards,

        Ariel

      7. Francis Martens (iDalko)


        For new readers looking for this solution 


        Make sure that the query which retrieves the variables is properly limiting the number of entries.
        One of our customers used a query which downloaded the whole table ...



      CommentAdd your comment...