While loop query + iteration

David Post
Kilo Expert

I'm putting together a script include to look up user IDs as part of new user creation. I want to look up records on the sys_user table for matches on the user_name attribute equal to the default format.

That's not a problem:

	validateEmail: function() {
		var firstname = this.getParameter("sysparam_firstname");
		var lastname = this.getParameter("sysparam_lastname");
		var username = firstname+'.'+lastname; //nice little string here
		var validate = new GlideRecord('sys_user');
		validate.addQuery('user_name', username);
		validate.query();

Note: domain is being used for another part

Where I get into trouble is when there's a match - which will happen. It's at this point I [think that I] need to do a while loop, but i'm unsure of what context the query is returning. I believe it is returning a record, but it might be Boolean. Either way, I need to set up a while loop that:

  1. runs until a record is NOT found, but also
  2. iterates through my naming convention until the condition is met
		while (validate.next()) {
			var suffix = 1;
			var username = user_name+'.'+suffix;
			var validate = new GlideRecord('sys_user');
			validate.addQuery('user_name', username);
			validate.query();
			suffix++;
		}

think this adds '.1' to the end of the user name (john.smith.1), and iterates onwards (john.smith.2) until it fails to find a match, at which point the  'username' variable will have been set to the value that isn't matched against the sys_user table.

Then we return the username variable as a string (added the '') at the end, forcing a string format.

		return username+'';

If all that works, we're going to parse the returned data and fill out the field on the catalog item:

function validateEmail(response) {
		var username = response.responseXML.documentElement.getAttribute("username");
		g_form.setValue('username', username);
	}

...and use that data to set the email address as well.

	g_form.getValue(company); //the value of the variable is actually the domain info
	g_form.setValue('email_address', username+'@'+company);
	g_form.setReadOnly(username);
	g_form.setReadOnly(email_address);

 

Lacking a team, I need a code review. Tell me where I'm crazy!

Client script:

function onChange(control, oldValue, newValue, isLoading) {
   if (isLoading || newValue == '') {
      return;
   }
	
	g_form.addInfoMessage("Identifying available username and email.");
	
	var first = g_form.getValue(first_name);
	var last = g_form.getValue(last_name);
	
	var ga = new GlideAjax('newUserUtils');
	ga.addParam('sysparam_name','validateEmail');
	ga.addParam('sysparam_firstname', first);
	ga.addParam('sysparam_lastname', last);
	ga.getXML(newUserUtils);
	
	function validateEmail(response) {
		var username = response.responseXML.documentElement.getAttribute("username");
		g_form.setValue('username', username);
	}
	g_form.getValue(company); //the value of the variable is actually the domain info
	g_form.setValue('email_address', username+'@'+company);
	g_form.setReadOnly(username);
	g_form.setReadOnly(email_address);
   
}

Script include: 

var newUserUtils = Class.create();
newUserUtils.prototype = {
    initialize: function() {
    },
	
	//Identify the most desireable email address available for the new user
	validateEmail: function() {
		var firstname = this.getParameter("sysparam_firstname");
		var lastname = this.getParameter("sysparam_lastname");
		var username = firstname+'.'+lastname; //nice little string here
		var validate = new GlideRecord('sys_user');
		validate.addQuery('user_name', username);
		validate.query();
		//try (email.next()) 
		while (validate.next()) {
			var suffix = 1;
			var username = user_name+'.'+suffix;
			var validate = new GlideRecord('sys_user');
			validate.addQuery('user_name', username);
			validate.query();
			suffix++;
		}
		
		return username+'';
		
	}
	
    type: 'newUserUtils'
};

 

THANK YOU all for checking this out!

1 ACCEPTED SOLUTION

Remember to correct 

		if (COUNT > 0) {

to 

		if (userCount > 0) {

And I can spot that your Script include is not "Client callable". The first part should look something similar to this: 

var newUserUtils = Class.create();
newUserUtils .prototype = Object.extendsObject(AbstractAjaxProcessor, {

 

It is achieved by making "client callable" to true on the script include! It needs this to work with GlideAjax 🙂  

That is the first step, else it can't be called from the client side! 🙂

 

I would also move all your g_form action just after 

		g_form.setValue('username', answer);

 

So you make sure that everything runs the same time, and after getting the answer from the server!


Best regards,
Sebastian Laursen

View solution in original post

7 REPLIES 7

Sebastian L
Mega Sage

Hi, 

So another way is basically to count the number of records currently present that fulfils your query of first name +'.' +last name..

var usrCheck = new GlideAggregate('sys_user');
usrCheck.addQuery('user_name', 'STARTSWITH', username);
usrCheck.addAggregate('COUNT');
usrCheck.query();
usrCheck.next();
var userCount = usrCheck.getAggregate('COUNT');

//So if there already is one user this would display John.Smith.1 - if to users present it would display John.Smith.2 

//It of course requires that a user is allowed with having the John.Smith without a suffix, else you can add +1 to the count. 

gs.info(username+'.'+userCount); 

So the username+'.'userCount should give you your next iteration of the user_name. Hope it makes sense 😄 


Best regards,
Sebastian Laursen

@Sebastian Laursen - so does that end up making the while loop look like this, or am I overthinking it?

validateEmail: function() {
        var firstname = this.getParameter("sysparam_firstname");
        var lastname = this.getParameter("sysparam_lastname");
        var username = firstname+'.'+lastname;
        var validate = new GlideRecord('sys_user');
        validate.addQuery('user_name', username);
        validate.query();
        //try (email.next()) 
        while (validate.next()) {
            var usrCheck = new GlideAggregate('sys_user');
			usrCheck.addQuery('user_name', 'STARTSWITH', username);
			usrCheck.addAggregate('COUNT');
			usrCheck.query();
			usrCheck.next();
			var userCount = usrCheck.getAggregate('COUNT');
			
			var username = username+'.'+userCount;
        }
        
        return username+'';
        
    }

 

 

or would the code you posted above replace the bulk of both the client script and script include?

It means you would not have to do a while loop, but you can just look up the amount of record present matching the user name, and by getting that number you can set the suffix or you can return the actual username. Does it make sense? I would not change your client logic, if you are getting the value from the script include that is 🙂

       var firstname = this.getParameter("sysparam_firstname");
        var lastname = this.getParameter("sysparam_lastname");
        var username = firstname+'.'+lastname;
        //try (email.next()) 
            var usrCheck = new GlideAggregate('sys_user');
			usrCheck.addQuery('user_name', 'STARTSWITH', username);
			usrCheck.addAggregate('COUNT');
			usrCheck.query();
			usrCheck.next();
			var userCount = usrCheck.getAggregate('COUNT');
			
if(userCount > 0) { //We also need to check if there is none.. then your normal username is actually fine;
			username = username+'.'+userCount;
}
        }
        
        return username+'';

Best regards,
Sebastian Laursen

if(count > 0) { //We also need to check if there is none.. then your normal username is actually fine;
			username = username+'.'+userCount;
}

 

That's the part I wasn't seeing. When I read your first response, it seemed like if it found no records it would create 'John.Smith.0' which we can't do. With the addition of the if(count > 0) { username = username+'.'+userCount;} it makes much more sense!

Thank you again!