Help with before business rule

VirendraKuD
Tera Contributor

Hi Team, 

 

I have requirement where I have two tables, custom table "XYZ Data" and another table "Asset (alm_asset)". I have a reference field on "XYZ Data" called Asset Name which is referenced to Asset table. I want to restrict users to map single record in XYZ data to single asset.

 

If Asset Name in XYZ Data record 1 is mapped to Asset 1 in asset table. Then system should restrict users from mapping XYZ data record 2 to Asset 1.

 

I have written this Before Business rule ( Insert and Update):

(function executeRule(current, previous /*null when async*/) {
    // Log the current asset sys_id
    gs.info('Business Rule triggered for asset: ' + current.u_asset_name);

    var existing = new GlideRecord('x_xyz_data');
    existing.addEncodedQuery('u_asset_name=' + current.u_asset_name + '^sys_id!=' + current.sys_id);
    existing.query();

    if (existing.next()) {
        gs.info('Duplicate mapping found for asset: ' + existing.u_asset_name);
        gs.addErrorMessage('This asset is already mapped to another XYZ data.');
        current.setAbortAction(true);
    } else {
        gs.info('No duplicate mapping found. Proceeding with save.');
    }
})();

 

 

 

I am undefined in gs.info - gs.info('Business Rule triggered for asset: ' + current.u_carear_product_name);

I am not getting values from fields into Before BR.

 

Thanks in advance

1 ACCEPTED SOLUTION

Ankur Bawiskar
Tera Patron
Tera Patron

@VirendraKuD 

this should work in before insert & update BR provided your field name is correct

I am using GlideAggregate for optimization

Note: you should use correct table name and field

(function executeRule(current, previous /*null when async*/) {
    // Log the sys_id of asset reference
    gs.info('Business Rule triggered for asset sys_id: ' + current.u_asset_name);

    // Use GlideAggregate to count how many records already map this asset excluding current record (for update)
    var ga = new GlideAggregate('x_xyz_data');
    ga.addQuery('u_asset_name', current.u_asset_name);
    ga.addQuery('sys_id', '!=', current.sys_id);
    ga.addAggregate('COUNT');
    ga.query();

    if (ga.next()) {
        var count = parseInt(ga.getAggregate('COUNT'), 10);
        if (count > 0) {
            gs.info('Duplicate mapping found for asset sys_id: ' + current.u_asset_name);
            gs.addErrorMessage('This asset is already mapped to another XYZ data.');
            current.setAbortAction(true);
        } else {
            gs.info('No duplicate mapping found. Proceeding with save.');
        }
    }
})(current, previous);

If my response helped please mark it correct and close the thread so that it benefits future readers.

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

View solution in original post

9 REPLIES 9

Hi @Ankur Bawiskar ,

 

I am getting this error message : 

gs.addErrorMessage('This asset is already mapped to another XYZ data.');

But, asset field got populated. That means current.setAbortAction is not working.

current.setAbortAction(true);

 

Thanks in advance..

@VirendraKuD 

Business rule should be before insert & update

it means the script I shared is working fine.

the business rule should be in same scope as that of custom table

Example: if custom table is in global scope then BR should be global scope

Same for scoped app

If my response helped please mark it correct and close the thread so that it benefits future readers.

Regards,
Ankur
Certified Technical Architect  ||  9x ServiceNow MVP  ||  ServiceNow Community Leader

kaushal_snow
Mega Sage

Hi @VirendraKuD ,

 

It appears you're encountering an issue where the current.u_asset_name field is returning undefined in your Before Business Rule. This is typically due to one of the following reasons:

 

Field Name Mismatch: Ensure that u_asset_name is the correct field name. In ServiceNow, field names are case sensitive and must match exactly.

 

Incorrect Table Reference: Verify that the u_asset_name field exists on the x_xyz_data table and is not a reference field to another table. If it's a reference field, you might need to access its sys_id or other properties...

 

check this code:

(function executeRule(current, previous /*null when async*/) {
    // Ensure the field exists and has a value
    if (current.u_asset_name) {
        gs.info('Business Rule triggered for asset: ' + current.u_asset_name);
    } else {
        gs.info('Asset Name is not set or is empty.');
    }

    // Check for existing records with the same asset
    var existing = new GlideRecord('x_xyz_data');
    existing.addEncodedQuery('u_asset_name=' + current.u_asset_name + '^sys_id!=' + current.sys_id);
    existing.query();

    if (existing.next()) {
        gs.info('Duplicate mapping found for asset: ' + existing.u_asset_name);
        gs.addErrorMessage('This asset is already mapped to another XYZ data.');
        current.setAbortAction(true);
    } else {
        gs.info('No duplicate mapping found. Proceeding with save.');
    }
})(current, previous);

 

If you found my response helpful, please mark it as ‘Accept as Solution’ and ‘Helpful’. This helps other community members find the right answer more easily and supports the community.

 

Thanks and Regards,
Kaushal Kumar Jha - ServiceNow Consultant - Lets connect on Linkedin: https://www.linkedin.com/in/kaushalkrjha/

Ankita_Patil
Tera Contributor

Hi @VirendraKuD ,

 

Can you please check the below Things :

 

1.    Field API Name Check
      Ensure you are using the correct API name of the reference field on your custom table x_xyz_data.

      For example, if your field label is Asset Name, the API name could be u_asset_name or something else like        u_asset.

      Check this by going to your table schema in ServiceNow Studio or Dictionary.

 

2.  Reference Field Value in Business Rule
    If the field is a reference, current.u_asset_name will hold the sys_id of the asset, not the name itself.

    To log the display value (name) of the reference field, you can use current.u_asset_name.getDisplayValue().

    To use the sys_id for your query, use current.u_asset_name (which is sys_id).

 

3. Encoded Query
    Your encoded query syntax should put quotes around the sys_id because it’s a string.
   
   For example:

   existing.addEncodedQuery('u_asset_name=' + current.u_asset_name + '^sys_id!=' + current.sys_id);


  Should be:

  existing.addEncodedQuery("u_asset_name='" + current.u_asset_name + "'^sys_id!='" + current.sys_id + "'");


4.  Business Rule Setup

     Before Business Rule

     On Insert and Update

     Table: x_xyz_data

 

devidt45678
Kilo Contributor

Hi,

Since this is a before business rule, keep in mind the values may not be fully updated yet when the script runs. Could you share the exact condition and what you want the rule to do—validate, update, or just log values? That’ll help in narrowing down why it’s not working as expected.