how to call script include in email script

Prasnajeet1
Giga Guru

Hi All

I need an urgent help in scrip include script.

I have written 3 email script to fetch data and populate in the email notification. All the below script is working fine. However all these 3 email script are performing almost same job, so i got instruction to write a single script include and use them in the email script. I am not good at scripting so need someone who can help me with the script include to achieve this.

 

Output of the below email script i have highlighted in bold and italic.

Laptop is assigned to Name is due for a refresh this quarter. Name is currently using a Old Asset and has requested to upgrade to a New Asset.

EMAIL SCRIPT1:

 
    var refreshMasterId = current.variables.refresh_master;
    var assetID = "";

    var grRefreshMaster = new GlideRecord('u_refresh_master');
    grRefreshMaster.addQuery('sys_id', refreshMasterId);
    grRefreshMaster.query();
   
    if (grRefreshMaster.next()) {
        assetID = grRefreshMaster.u_new_asset_type;
    }
    template.print(assetID.getDisplayValue());
 
EMAIL SCRIPT2:
     var refreshMasterId = current.variables.refresh_master;
    var assetID = "";

    var grRefreshMaster = new GlideRecord('u_refresh_master');
    grRefreshMaster.addQuery('sys_id', refreshMasterId);
    grRefreshMaster.query();

    if (grRefreshMaster.next()) {
        assetID = grRefreshMaster.u_asset;
    }
    if (!assetID) {
        return;
    }
    var grHardware = new GlideRecord('alm_hardware');
    grHardware.addQuery('sys_id', assetID);
    grHardware.query();
    if (grHardware.next()) {
        template.print(grHardware.u_asset_type.getDisplayValue());
    }
EMAIL SCRIPT3:
 
var refreshMasterId = current.variables.refresh_master;
    var assetID = "";

    var grRefreshMaster = new GlideRecord('u_refresh_master');
    grRefreshMaster.addQuery('sys_id', refreshMasterId);
    grRefreshMaster.query();
    if (grRefreshMaster.next()) {
        assetID = grRefreshMaster.u_asset;
    }
    if (!assetID) {
        return;
    }
    var grHardware = new GlideRecord('alm_hardware');
    grHardware.addQuery('sys_id', assetID);
    grHardware.query();
    if (grHardware.next()) {
        template.print(grHardware.assigned_to.getDisplayValue());
    }
4 REPLIES 4

Weird
Mega Sage

Go to the script includes table and open any (none client callable ones) and see how they've been structured and use that as example.

But the system does a lot for you. If you create a new one and add a name, you'll have the body ready.
Here's an example where I've added a function:

var EmailScriptUtil = Class.create();
EmailScriptUtil.prototype = {
    initialize: function() {
    },

	getRefreshMaster: function(masterId){
		//Do something and return something
		return "";
	},

    type: 'EmailScriptUtil'
};

In your email script you could call the script include and function using something like

var master = new EmailScriptUtil().getRefreshMaster(current.variables.refresh_master);


Now with script includes and functions in general, you should always return something. In this case you could make separate functions for everything you need or return the manager GR or a simplified object with the values that you need.

For example:

var EmailScriptUtil = Class.create();
EmailScriptUtil.prototype = {
    initialize: function() {},

    getRefreshMaster: function(masterId) {
        var masterObj = {};
        var grRefreshMaster = new GlideRecord('u_refresh_master');
        grRefreshMaster.get(masterId);
        if (grRefreshMaster.isValidRecord()) {
            masterObj.assetType = grRefreshMaster.u_new_asset_type;
            masterObj.assetId = grRefreshMaster.u_asset;
            return JSON.stringify(masterObj);
        }
        return "";
    },

    type: 'EmailScriptUtil'
};


Now when you call this it should return you a string that's an object containing assetType and assetId.
You can turn them into an object in your email script:

var master = new EmailScriptUtil().getRefreshMaster(current.variables.refresh_master);
var masterObj = JSON.parse(master);


Now depending on which email script you're on, you can set the template with the required value like:

template.print(master.assetId);



There's really no limit with script includes when considering the attributes used in the function call, so if you wanted to, you could specify which fields you want to get in the object in the call as well.
Also, you can also do the hardware query in that single function or create another function that is only used for the hardware call. This way the hardware query is only done when it's required and not for every email script.

Hi 

Thank you for your response.

As I mention earlier am not good in script so need more clarity in this. What i understood is I should write the script include as you have mention, and what are the changes I have to do in my email script.

 

Shall I just put the 3 line like you have mention.

var master = new EmailScriptUtil().getRefreshMaster(current.variables.refresh_master);
var master = new EmailScriptUtil().getRefreshMaster(current.variables.refresh_master);
var masterObj = JSON.parse(master);
template.print(master.assetId);

Is this going to resolve email script no 3. 

Please respond

Well let me help with clarifying how the scripts work.
So a Script Include in Servicenow is basically the same as class in Javascript, so it works in the same way and you can read javascript tutorials about those to get an idea how they really work.

You can define functions directly to your script or as part of a class. In class they're called methods, but basically the same thing.
Functions are used to avoid writing the same code over and over again to do the same task.
Imagine you have a script where you have 5 places were you need to do a complex math calculation.
It's easier to have a function with the code and you just provide the required numbers into it and it returns the answer. So instead of repeating 20 lines of code you just repeat 1 which is for example calculateEarningAfterTax(earnings, tax);

Now your email script uses different pieces of script that are similar, so they can be combined into functions.
Now your script include could look like this:

var EmailScriptUtil = Class.create();
EmailScriptUtil.prototype = {
    initialize: function() {
    },

	getRefreshMaster: function(masterId) {
    var masterObj = {};
    var grRefreshMaster = new GlideRecord('u_refresh_master');
    grRefreshMaster.get(masterId);
    if (grRefreshMaster.isValidRecord()) {
        masterObj.assetType = grRefreshMaster.u_new_asset_type;
        masterObj.assetID = grRefreshMaster.u_asset;

        if (masterObj.assetID) {
            var grHardware = new GlideRecord('alm_hardware');
			grHardware.get(masterObj.assetID);
			if(grHardware.isValidRecord()){
				masterObj.hardwareAssignedTo = grHardware.assigned_to.getDisplayValue();
			}
        }
    }
    return masterObj;
},

    type: 'EmailScriptUtil'
};

What we did is we created a variable with object type. Objects allow us a bit more freedom in defining content of the variable. A string would be a regular text like "hello". Array allows you to contain multiple values as separate ["Hello", "Bye"]. Array can contain any type and is pretty great when you need to loop through many values. An object can contain nested values, so you can kinda have multiple variables in the same object. GlideRecord is basically an object. You know that current.assigned_to.name works since the current object has a field assigned_to and that in turn has its own fields like name.
You can't add fields to a gliderecord object, but you can do so on a regular object, so you don't need to define variables. You can just add new elements like "masterObj.newVariable = "newValue"" when you need to. Just remember to check if that element existst in the object.

The script include expects a parameter which in this case is the refresh master variable, so in your email script call the script like so:

var master = new EmailScriptUtil().getRefreshMaster(current.variables.refresh_master);

Now this should return the value from script include as an object as we defined it as so, but if it doesn't work, you can add "JSON.stringify(masterObj)" to the script include to replace masterObj in return.
Then similarly add JSON.parse(); around the new EmailScriptUtil()... call.

var master = JSON.parse(new EmailScriptUtil().getRefreshMaster(current.variables.refresh_master));

You shouldn't need to do that however as the script include should return it as an object.

Now all you have left is setting the values.
So just make sure your object has the value you need and print it:

if(master.assetID){
template.print(master.assetID);
}

It's a good idea to make sure there's a value in your object before printing as otherwise your email might end up printing values like "undefined" or "NULL".

Now in each of your email scripts you can just write

var master = new EmailScriptUtil().getRefreshMaster(current.variables.refresh_master);
template.print(master.theValueYouNeed);


You could even get rid of the other email scripts if you have some kind of value that you can use to recognize which value you need from the script. A notification could have an event associated with it, or you could use some value from the current record related to the notification.

Hope these helps. I'm in a bit of a hurry and wrote these hastily, so hopefully they make some sense.

Amit Verma
Kilo Patron
Kilo Patron

Hi @Prasnajeet1 

 

You can create functions for your individual email scripts in a Script Include. Once the Script Include is ready, refer below posts to call it in your email script :

https://www.servicenow.com/community/csm-forum/sample-of-using-script-include-in-email-notification/...

https://www.servicenow.com/community/developer-forum/how-to-call-script-include-from-email-script-an...

 

Thanks & Regards

Amit Verma


Please mark this response as correct and helpful if it assisted you with your question.