relation, populate service from CI, cmdb_rel_ci

Pastupe
Mega Guru

Im sorry to ask again but need help and also need to learn how to script this demand.

I can find way how to populate service on incident form if SD user select last appllication on the image below - 3

I havent luck to buil onchange client script - Im able to build script which returns me only direct relation ( from 3 to 2 ) but not what we need   ( from 3 to X)

would somebody give me a lesson here please ? Please note that I need onchange solution, so service is prefilled always when suer change CI

My system fields are

cmdb_ci   -- for apps

u_service_ci -- for service

thank you

/Petr

1a.jpg

1 ACCEPTED SOLUTION

Hi Petr,



Nice work on the GlideAjax script.   I do have a few recommendations that can improve your script and hopefully help you learn a little more about GlideAjax in the process (you can also check out my infographic on GlideAjax for additional info: Demystifying GlideAjax).



So first, the scripts (please bear in mind I haven't fully tested these yet so they may need some tweaks):



Client Script



function onChange(control, oldValue, newValue, isLoading, isTemplate) {


  if (isLoading || newValue == '') {


      return;


  }


 


  var ooo = g_form.getValue('cmdb_ci'); // this is the sys id of CI entered by user


  var ga = new GlideAjax('BusinessServiceFinder');


  ga.addParam('sysparm_name', 'getServiceForCI');


  ga.addParam('sysparm_ci_sys_id', ooo); // passing CI sys_id to script include


  ga.getXML(setBusinessService);


 


  function setBusinessService(response) {


      var answer = response.responseXML.documentElement.getAttribute('answer');


      g_form.setValue('u_service_ci', answer); // get answer from Script Include and set Service CI field


      alert(answer);


  }


}



Script Include



var BusinessServiceFinder = Class.create();


BusinessServiceFinder.prototype = Object.extendsObject(AbstractAjaxProcessor, {


  getServiceForCI: function() {


  var this_is_variable_from_form = this.getParameter('sysparm_ci_sys_id') + '';


  return this._getParentRelationship(this_is_variable_from_form);


  },



  _getParentRelationship: function(ciSysId) {


  var o = new GlideRecord('cmdb_rel_ci');


  o.addQuery('child', ciSysId);


  o.query();


  if (o.next()) {


  if (o.parent.sys_class_name == 'cmdb_ci_service') {


  return o.getValue('parent'); // return the CI's sys_id


  }


  else {


  return this._getParentRelationship(o.getValue('parent')); // recursively execute the function for the parent's sys_id


  }


  }


  else {


  return 'There is no direct relation to service';


  }


  },



  type: 'BusinessServiceFinder'


})



Changes



1. You will notice that I changed the names of the Script Include and its function.   You can change these names as you desire, but with GlideAjax there is a convention that you must follow:


        - The name of the Script Include (BusinessServiceFinder) must be included inside the parenthesis of the GlideAjax call as shown on line 7 of the Client Script.   This tells GlideAjax which Script Include to use.


        - The name of the Script Include's function (getServiceForCI) must be included in the Client Script by setting it as the sysparm_name parameter as shown on line 8 of the Client Script.



2.   You will also notice that I added a private function _getParentRelationship and changed the getServiceForCI function to use it.   The _getParentRelationship is a recursive function that calls itself.   This eliminates the need for the nested if statements and reduces the duplicated code.   Basically, the _getParentRelationship function will keep calling itself by passing the parent CI in the relationship until it finds a Business Service or is unable to find a relationship.   The advantage in this script is that it will work for any sized relationship tree depth.   If you were to at some point in the future link relationships 6 nodes from the Business Service, this script will still work.



I hope this helps.   And thank you deepak.ingale for looping me in!



Kind regards,



Travis



EDIT: A few typos, missing punctuation, wrong punctuation, and other miscellaneous errors later, this script has now been tested.   Thanks guys!


View solution in original post

36 REPLIES 36

Ok thanks   Kalai


Thanks, sorry about that.   I have fixed the missing semicolon in my original response.


Untitled.png



I Travis, thank you for the reply....i added the sever "linuxvm2" as the affected CI in the incident form...but instead of getting "ITSM" or its sys_d in alert i got NULL



is this use case in alignment with the script here or am i off the track??


Hi Mathew,



I have gone through and fixed the Script Include and edited my original script above.   It is now working for me and your use case should work.   The key mistakes I made were:



1.   Used a comma on line 4 of the Script Include instead of a semi-colon as you discovered


2.   Misspelled the _getParentRelationship function call on line 5 as _getParentReplationship... don't ask


3.   Line 14 and 17 of the Script Include had a call to o.parent.getValue() but that was not working, so I switched to o.getValue('parent')



Please let me know if this works out for you.



Kind regards,



Travis


Hi Travis, its working now Thanks! ....one request though



in many scenarios a low level   CI (server) will be associated to more that one business services , how can we fetch all the associated Business services



Currently i think we get only Business server...i started with creating an array any thoughts on this




var arraystring = arr[0] + arr[1]


return arraystring