Setting RITM fields using Cart API

javis
Giga Expert

Hi all,

I was wondering if there is a way to populate fields (not variables) on RITM forms? Everything I've read talks about populating variables but I'd like to have the fields set as well based on what users send to SN via emails. Any help or suggestions is greatly appreciated. Thanks again,

22 REPLIES 22

Nigel Bell
ServiceNow Employee
ServiceNow Employee

Hi James,



Your current approach for matching the fields/values found in the email with the fields in the target record should still work, and combining that with the advice from Brad and Abhinay you can get this working in your inbound action.



Here's some sample script that combines some of the scripts you've already pasted but I think should achieve what you want.



  var cat_id='';


  if(email.body.item != undefined && email.body.item!='') {


  var cat_item=email.body.item.trim();


  var gr= new GlideRecord('sc_cat_item');


  gr.get('name',cat_item);


  cat_id=gr.getValue('sys_id');



  var cart = new Cart();


  var item=cart.addItem(cat_id);


  var user = new GlideRecord('sys_user');


  if(user.get('email',email.from.toString())){


  // set requested for


  //Set Variables in your Cart Item


  cart.setVariable(item, 'requested_for', user.getValue('sys_id'));


  }


  var cartmsg = "received from: " + email.origemail + "\n\n" + email.body_text;


  cart.setVariable(item,'comments',cartmsg);


  var rc = cart.placeOrder();



  var ritm= new GlideRecord('sc_req_item');


  ritm.addQuery('request',rc.sys_id);


  ritm.query();



  var labelData = getLabels(ritm);



  while (ritm.next()) {


  for (var fieldName in email.body) {


  if (labelData[fieldName]) {


  var label = labelData[fieldName];


  var fieldValue = email.body[fieldName];


  if (label.isReference)


  ritm[label.column].setDisplayValue(fieldValue);


  else


  ritm[label.column] = fieldValue;


  }


  }


  ritm.update();


  }


  }



  function getLabels(gr) {


  var labelData = {};



  if (!gr)


  return labelData;



  var elements = gr.getElements();



  for (var i = 0; i < elements.size(); i++) {


  var element = elements.get(i);


  var columnName = element.getName();


  var columnLabel = element.getLabel();


  var ed = elements.get(i).getED();


  var isReference = (ed == null ? false : ed.isReference());



  var name = cleanLabel(columnLabel);


  labelData[name] = {column: columnName, isReference: isReference};


  }



  return labelData;


  }



  function cleanLabel(label) {


  var name = label.toLowerCase().replace(/[^a-zA-Z0-9_]/g, '_');



  // Compact any multiple sequential underscores


  while (name.indexOf("__") != -1)


  name = name.replace(/__/g, "_");



  // Replace any trailing underscores


  while (name != '' && name.charAt(name.length - 1) == '_')


  name = name.substring(0, name.length - 1);



  return name;


  }


It'll need amending for the extra blackilist/whitelist logic that you have and some testing for whether the user can write to the fields being updated (e.g.   ritm[fieldName].canWrite() ).


I've tested this on my ServiceNow instance and it worked ok.



Hope that helps.



Regards


Nigel



P.S.   Just noticed that what I've written could be done more efficiently by working out the fields to be updated on the Requested Item once rather than for each requested item that has been created for the Request so if you are likely to be creating multiple items per request you could consider re-working this a bit.


Hi Nigel,



Thank you for taking the time to look into this, I truly appreciate it. I tried your code and it did not fill the RITMs fields as said in the email. To give you some context, we send an email to SN in this format (below) and the the associated fields get set to the info in the email. The code mentioned above set a dynamic inbound action and I've been trying to merge the cart api request code and set the fields the way we do now. Again, thank you for all your help!



Accountable: Nigel Bell        


Active: False


Activity due: 01:01:2017


Actual effort: 01:02


Additional assignee list: Nigel Bell


Additional comments: Testing full RITM input


Approval: requested


Approval history: Some Approval History


Approval set: 01:03:2017


Assigned to: Nigel Bell


Assigned user: Nigel Bell


Assignment Department: Servicenow


Assignment Division: Applications Development


Assignment group: Auxiliary Services


Assignment Organization: Administration


Assignment Team: Admin


Nigel Bell
ServiceNow Employee
ServiceNow Employee

Hi,



Disappointing it didn't work on your instance.   From the code you posted (which does a nice job of deriving the matching fields in the target record from the text in the email) I thought I'd provided something similar which would use the fields from the email to match with fields on the Requested Item.   An example of the email I was processing on my instance:



Item:Request_by_email


Quantity:999


Configuration item:DP00349


Another user:Nigel Bell


Short description:my description for this item




Then taking the "Another user:..." line as an example, the inbound action script would then look for a field on Requested Item that has a label that matches this name (but with the appropriate replacing spaces with underscore and changing to lowercase).   In my case I had added a custom reference field to Req Item with the label   "Another user" and the underlying column name of "u_a_user".



From your last update it sounds like you're happy to work on getting your own scripts combined but if you want to try and add some debugging to what I sent you just let me know.



Regards,


Nigel


I am confused from your code;


  1. var labelData = getLabels(ritm);  
  2.  
  3.   while (ritm.next()) {  
  4.   for (var fieldName in email.body) {  
  5.   if (labelData[fieldName]) {  
  6.   var label = labelData[fieldName];  
  7.   var fieldValue = email.body[fieldName];  
  8.   if (label.isReference)  
  9.   ritm[label.column].setDisplayValue(fieldValue);  
  10.   else  
  11.   ritm[label.column] = fieldValue;  
  12.   }  
  13.   }  
  14.   ritm.update();  
  15.   }  
  16.   }    

what is the difference of fieldName and fieldValue?


Nigel Bell
ServiceNow Employee
ServiceNow Employee

Hi James,



Taking a snippet from the kind of email you send into your SNC instance, if your email body contained:



Accountable: Nigel Bell    


Active: False


Activity due: 01:01:2017



then the line "for (var fieldName in email.body)" would loop over the field names from the email body and set the fieldName to the appropriate value (i.e. "accountable", "active", "activity_due").



The line "var fieldValue = email.body[fieldName];" will then set fieldValue to the value after the ":" of each fieldName - so when fieldName is "accountable", fieldValue will be set to "Nigel Bell".



Does that make sense?



Regards,


Nigel