The CreatorCon Call for Content is officially open! Get started here.

Please help with Transform Map Script.

Meera_P
Tera Expert

Hello,

This is the Transform Map onBefore script. The code compares each user in the user table against the source to determine if they have a ServiceNow account. If not, it skips creating an incident and sends an email to the support team for those users who do not have an account in SN. Currently, it sends separate emails for each ignored user.

 

Given my limited experience in JavaScript, could someone please assist me in modifying it to send just one email listing all the users without ServiceNow accounts?  Thanks to all.

 

(function runTransformScript(source, map, log, target /*undefined onStart*/ ) {
    var ignoredUsers = [];
    // Query the source table
    var gr_source = new GlideRecord('u_import_data_incident');
    gr_source.query();
    if (gr_source.next()) {
        var senderName = getUserByEmail(source.u_email);
        if (senderName && source.u_email == senderName) { // Check if the email matches the senderName
            target.caller_id = senderName;
            target.description += "USER NAME: " + source.u_caller_id;
            target.assignment_group = '57b33d19db1f14107c425638dc9619fd';
        } else {
            ignore = true; // Ignore the record creation
			
            ignoredUsers.push(gr_source.u_email); //If no match is found, adds it to the array
			
            gs.log("Email does not match the sender name. Ignoring record creation: " + source.u_email);

            if (ignoredUsers.length > 0) {
				
                // Prepare email body
                var notFoundUser = 'User Name: ' + source.u_caller_id + '\n' + source.u_email;

                // Send email notification
                sendEmailNotification('CyberSecurity@ABC.com', notFoundUser);
            }
        }
    }
})(source, map, log, target);

// Function to get user ID by email from the sys_user table
function getUserByEmail(email) {
    var userGR = new GlideRecord('sys_user');
    if (userGR.get('email', email)) {
        return userGR.getValue('user_name'); // Assuming 'user_name' is the sender name
    } else {
        gs.info("Unable to find user with email: " + email);
        return null;
    }
}

// Function to send an email notification
function sendEmailNotification(email, notFoundUser) {
    gs.eventQueue('import.data.user.not.found', source, email, notFoundUser);
}

 

 

1 ACCEPTED SOLUTION

Hi, I don't think there is a lot of complicated javascript involved, and now might be the ideal time to improve your skills; AQlso if you break it down into small pieces it instantly becomes way less complicated.
Start by adding an onStart script that instantiates an array based on the details in the linked threads. IE
this.myArray = [];
If this saves without error, then in the start script push any value into it.

this.myArray.push('test');

 

Then see if you can read\log the results in a before script eg

log.info('myArray | before ' + this.myArray[0].toString()); // this might be gs.info and not log.info


Hopefully at this point when you import and transform a record, you see 'myArray | before test' in your system log for each row in your import.

 

If you do, then add an onComplete script

log.info('myArray | complete ' + this.myArray[0].toString()); // this might be gs.info and not log.info

and try again, hopefully you see 1 'compete' log entry?

if yes, go back to your before script and try pushing a value into element 1 IE

this.myArray.push('Element1');

(if importing more than 1 row this would add a new element to the array for each row)

 

Then update the onComplete script to see if element 1 is populated 

log.info('myArray | complete ' + this.myArray[1].toString());

 

At this point you have hopefully proved that you can create an array in the start script, populate it in the before script and read it in the complete script.

 

Then all you need do is update your before script so that you push the invalid user details into the array.
And finally update your complete script so that it creates the sysevent add populates the list of impacted email addresses and you will get a comma separated list using this.myArray.toString();

Give it a try, and see how you get on
Any issues or questions you can update this thread and the community can assist\advise.

View solution in original post

8 REPLIES 8

Tony Chatfield1
Kilo Patron

Hi, unfortunately your script is as bit unclear, I suspect that 'u_import_data_incident' is the table that this transform is running against? Assuming yes then I think that your current solution is trying to query the table\record that is available directly via 'source' and I think you can simplify your script to something like this

(function runTransformScript(source, map, log, target /*undefined onStart*/ ) {
    // Query the user table
	var myUser = source.u_email;
	var userCheck = new GlideRecord('sys_user');
	if(userCheck.get('email', myUser)) {
		//Do something becuase there is a match
		target.caller_id = userCheck.sys_id;
		target.description += "USER NAME: " + source.u_caller_id; //should this be userCheck.name ?
		target.assignment_group = '57b33d19db1f14107c425638dc9619fd';	
	} else {
		//Do something else as there is not a match.
		ignore = true;
		// Prepare email body
		var notFoundUser = 'User Name: ' + source.u_caller_id + '\n' + myUser;
		// Send email notification
		gs.eventQueue('import.data.user.not.found', source, 'CyberSecurity@ABC.com', notFoundUser);
	}
}

 

Hello @Tony Chatfield1 

Thank you for simplifying the code; your revisions have made it shorter, much easier to follow and understand. In Figure #1 of the email log, it's evident that separate emails are being sent for each ignored user.

Figure #1

Meera_P_0-1716787040132.png

 

Could the code be modified to send a single email listing all users without ServiceNow accounts? as an example shown in Figure #2?

Figure #2

Meera_P_1-1716787405251.png

Currently, the recipients contains both emails. The recipients should be limited to just the team email address CyberSecurity@ABC.com.

 

Meera_P_2-1716787537278.png

 

Notification:

Meera_P_3-1716787846915.png

 

 

 

Hi, onBefore transform scripts run for each row\record in your transform, so to have a combined result you would need to run the sys_user check in the onBefore script so that you can continue to ignore records where there is no user match. You would then also need to run an onStart or onComplete script to parse your payload and create your list of 'non' users.
Based on this community thread
Solved: Setting and Reusing Variables During Import Transf... - ServiceNow Community
You may be able to remove the need for a separate query of your rows import rows, by declaring an array variable in an onStart script using this.arrayName format, pushing values to the array in your onBefore script (per row) and then using an onComplete to trigger your email notification passing in your array content.

Hi @Tony Chatfield1 

Thank you for the detailed explanation. It seems quite complex, but I will revisit it once I've improved my JavaScript skills. Your exceptional work is truly appreciated, and your willingness to share it with the community is admirable.

I sincerely thank you for your time and effort.