Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

Restrict duplicate entries

shaik17
Tera Contributor

Hi all,

i have a requirement when a record is updated in sc_item_variables_task table (MRVS) it is creating duplicates here is the script they used after insert business rule

 

(function executeRule(current, previous /*null when async*/) {

 

var qList = [];

//get variable sets related to item
var vsr = new GlideRecord('io_set_item');
vsr.addQuery('sc_cat_item', current.request_item.cat_item.sys_id);
vsr.query();
//get variables for each set
while(vsr.next()){
var vs = new GlideRecord('item_option_new');
vs.addQuery('variable_set', vsr.variable_set);
vs.addQuery('active', true);
vs.addQuery('global', false);
vs.query();
while(vs.next()){
var id = vs.sys_id.toString();
qList.push(id);
}
}

//push Vatiable Task record for each variable set
for (var i = 0; i < qList.length; i++) {
var ivt = new GlideRecord('sc_item_variables_task');
ivt.task = current.sys_id;
ivt.variable = qList[i];
ivt.insert();
}
}

})(current, previous);
 
shaik17_0-1709879244269.png

 

Pls help,

Thanks.

1 ACCEPTED SOLUTION

Amit Pandey
Kilo Sage

Hi @shaik17 

 

Can you try the following BR-

 

(function executeRule(current, previous /*null when async*/) {

    var qList = [];

    // Get variable sets related to the item
    var vsr = new GlideRecord('io_set_item');
    vsr.addQuery('sc_cat_item', current.request_item.cat_item.sys_id);
    vsr.query();

    // Get variables for each set
    while(vsr.next()) {
        var vs = new GlideRecord('item_option_new');
        vs.addQuery('variable_set', vsr.variable_set);
        vs.addQuery('active', true);
        vs.addQuery('global', false);
        vs.query();
        while(vs.next()) {
            var id = vs.sys_id.toString();
            qList.push(id);
        }
    }

    // Check if a record with the same task and variable already exists
    for (var i = 0; i < qList.length; i++) {
        var variableId = qList[i];
        var existingRecord = new GlideRecord('sc_item_variables_task');
        existingRecord.addQuery('task', current.sys_id);
        existingRecord.addQuery('variable', variableId);
        existingRecord.query();
        if (!existingRecord.next()) { // If no existing record found, insert a new one
            var ivt = new GlideRecord('sc_item_variables_task');
            ivt.task = current.sys_id;
            ivt.variable = variableId;
            ivt.insert();
        }
    }
})(current, previous);

View solution in original post

2 REPLIES 2

Aravind2799
Giga Expert

Here's a breakdown of the script and potential causes for duplicate records:

1. Querying Variable Sets:

  • The script correctly queries for variable sets related to the catalog item using io_set_item.

2. Retrieving Variables:

  • It fetches variables for each variable set using item_option_new.
  • It filters for active and non-global variables.

3. Creating sc_item_variables_task Records:

  • It iterates through the list of variable sys_ids (qList).
  • For each variable, it creates a new sc_item_variables_task record with:
    • task: The current task sys_id.
    • variable: The variable sys_id from qList.
    • It inserts the record.

Potential Causes for Duplicates:

  1. Multiple Executions:

    • Check if the business rule is configured to run "after update" as well. If so, it would execute on both insert and update events, creating duplicates.
    • Ensure it only runs "after insert" or find a way to prevent multiple executions.
  2. Lack of Unique Constraint:

    • If there's no unique constraint on the combination of task and variable fields in sc_item_variables_task, duplicates could exist.
    • Consider adding a unique constraint to prevent this.
  3. Existing Record Check:

    • The script doesn't check if a record already exists with the same task and variable combination before inserting.
    • Add a check to only insert if a matching record doesn't exist.

 

(function executeRule(current, previous) {
  var qList = [];

  // ... (variable set retrieval logic remains the same) ...

  // Check for existing records and insert only if not found
  for (var i = 0; i < qList.length; i++) {
    var ivt = new GlideRecord('sc_item_variables_task');
    ivt.addQuery('task', current.sys_id);
    ivt.addQuery('variable', qList[i]);
    ivt.query();
    if (!ivt.next()) {
      ivt.insert(); // Insert only if not found
    }
  }
})(current, previous);

 

Additional Considerations:

  • Review the business rule configuration to ensure it runs only on the intended events.
  • Consider adding a unique constraint to sc_item_variables_task for the task and variable fields.
  • If duplicates still occur, thoroughly debug the script's execution flow and data context for further analysis.

Thanks

Aravind Panchanathan

Amit Pandey
Kilo Sage

Hi @shaik17 

 

Can you try the following BR-

 

(function executeRule(current, previous /*null when async*/) {

    var qList = [];

    // Get variable sets related to the item
    var vsr = new GlideRecord('io_set_item');
    vsr.addQuery('sc_cat_item', current.request_item.cat_item.sys_id);
    vsr.query();

    // Get variables for each set
    while(vsr.next()) {
        var vs = new GlideRecord('item_option_new');
        vs.addQuery('variable_set', vsr.variable_set);
        vs.addQuery('active', true);
        vs.addQuery('global', false);
        vs.query();
        while(vs.next()) {
            var id = vs.sys_id.toString();
            qList.push(id);
        }
    }

    // Check if a record with the same task and variable already exists
    for (var i = 0; i < qList.length; i++) {
        var variableId = qList[i];
        var existingRecord = new GlideRecord('sc_item_variables_task');
        existingRecord.addQuery('task', current.sys_id);
        existingRecord.addQuery('variable', variableId);
        existingRecord.query();
        if (!existingRecord.next()) { // If no existing record found, insert a new one
            var ivt = new GlideRecord('sc_item_variables_task');
            ivt.task = current.sys_id;
            ivt.variable = variableId;
            ivt.insert();
        }
    }
})(current, previous);