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

Script help to find duplicates and create only if no duplicate found?

Shane J
Tera Guru

I have a Scheduled Job that runs weekly to create a custom Time Sheet record, and Time Cards underneath it.   If the job gets run more than once during a week, everything gets duplicated.   I'd like the script to check for an existing Time Sheet and canceling if there is one.

Scripts of this size usually scare answers off unfortunately, but it's really the portion in bold I think needs work:

var usr = [];

var usrITIL = new GlideRecord('sys_user_has_role');

usrITIL.addEncodedQuery('user.u_time_card_exempt=false^role.nameSTARTSWITHitil^user.active=true');

usrITIL.query();

while (usrITIL.next()) {

usr.push(usrITIL.user+'');

}

var cleanUSR = dedup(usr);

var today = new GlideDateTime();

var dtUtil = new DateTimeUtils();

var firstDay = gs.getProperty("com.snc.time_card.start_day", 7);

var start = dtUtil.getWeekStart(today, firstDay);

var startdisplay = start.getDisplayValue();

for(var i = 0; i < cleanUSR.length; i++){

//Don't create a dupe Time Sheet record

var dupe_sheet = new GlideRecord('u_time_sheet');

dupe_sheet.addQuery('u_user', cleanUSR[i]);

dupe_sheet.addQuery('u_week_starts_on', start);

if (dupe_sheet.next()){

dupe_sheet.setAbortAction(true);

}

//Create a Time Sheet for the week

var time_sheet = new GlideRecord('u_time_sheet');

time_sheet.initialize();

time_sheet.u_user = cleanUSR[i];

var sheet_id = time_sheet.insert();

//Create an 'Admin' Time Card under the Time Sheet

var time_card = new GlideRecord('time_card');

time_card.initialize();

time_card.user = cleanUSR[i];

time_card.category = 'admin';

time_card.u_time_sheet = sheet_id;

time_card.insert();

//find only active Tasks assigned to the user

var Task = new GlideRecord("task");

Task.addQuery('active', true);

Task.addQuery('state', '!=', '6');

Task.addQuery('assigned_to', cleanUSR[i]);

Task.query();

while (Task.next()) {

// create time cards

var timeCardt = new GlideRecord("time_card");

timeCardt.initialize();

timeCardt.user = cleanUSR[i];

timeCardt.task = Task.sys_id;

timeCardt.u_time_sheet = sheet_id;

if (Task.sys_class_name == 'pm_project' || Task.sys_class_name == 'pm_project_task' || Task.sys_class_name == 'rm_defect')

{

timeCardt.category = 'Project Work';

}

else if (Task.sys_class_name == 'sc_task'){

timeCardt.category = 'Request';

}

else {

timeCardt.category = 'Incident';

}

timeCardt.insert();

}

//find only active Projects where the user is a Project Manager

var PM = new GlideRecord("pm_project");

PM.addQuery('active', true);

PM.addQuery('project_manager', cleanUSR[i]);

PM.query();

while (PM.next()) {

// create time cards

var timeCardp = new GlideRecord("time_card");

timeCardp.initialize();

timeCardp.user = cleanUSR[i];

timeCardp.task = PM.sys_id;

timeCardp.u_time_sheet = sheet_id;

timeCardp.category = 'Project Work';

timeCardp.insert();

}

}

function dedup(arr){

var tmp = [];

for(var i = 0; i < arr.length; i++){

if(tmp.indexOf(arr[i]) == -1){

tmp.push(arr[i]);

}

}

return tmp;

}

1 ACCEPTED SOLUTION

Dave Smith1
ServiceNow Employee
ServiceNow Employee

That's what a "unique" database constraint is used for - add a composite unique constraint on the two columns u_user and u_week_starts_on to prevent duplicates.



If you select the table in the Tables and Columns module, you can add an index for it.



There is also a related list of indexes on the table record.   In the screenshot, a table of fruit owners has an index on the fruit and the owner - meaning there cannot be two records where Harambe owns a banana:



find_real_file.png



Note: adding these things will cause an overhead on inserts and updates so shouldn't be added to high-transaction tables!



(credit to the database whizz that is davidpeters for the index info)


View solution in original post

10 REPLIES 10

Dave Smith1
ServiceNow Employee
ServiceNow Employee

Rather than create a script... why not just make a specific identifier field unique so that the database prevents duplicates?  



You'll get errors, sure - but that's the purpose of database constraints: to safeguard data integrity.


I'm not sure how that applies in this case?   Each week a Time Sheet is created for each person with the itil role.


Dave Smith1
ServiceNow Employee
ServiceNow Employee

When you say "everything gets duplicated"... what fields can you use to identify that the record is a duplicate?


u_user and u_week_starts_on - the combo of those two should be unique each week.