trying to update a custom field in a table that extends sc_cat_item

Renee-17
Tera Guru
  • Help!
  • I have a table that I will call x_product that extends sc_cat_item.  There is a custom field quantityonstock that exists on the x_product table in a scoped app. 
  • I have not been able to update the field using a script include. 
  • Currently, quantityonstock is successfully updated via a server side script that's part of a widget and also via a scheduled import and via a backend script. But I need to be able to update it via a script include.
  • I know that the code works as I have tested it via backend script.
  • I've looked into Application Access, Cross Scope Privileges, Restricted Caller Access, Read-Only on field, ACLs, Don't see any Data policies.  Not sure what I'm missing. 

___________________________________________________________________

Here's a little more detail with screen shots:

 

Ultimately, I want to be able to call the Script Include from UI Builder Experience Page via Data Transform Server Side Script.

 

Current setup is a Fix Script that calls a Script Include in WMS scope

Fix Script calling Script Include.png

 

The Script Include is in the same WMS scope but updates a table in another scope.  We'll call the scope ABC.

Script Include heading screenshot.png

 

Here's a snippet of the code:

var processInventoryUtility = Class.create();
processInventoryUtility.prototype = {

    initialize: function(productSysId, quantity) {
        this.qty = parseInt(quantity, 10);
        this.productId = productSysId;
    },

    //Retrieve Record
    _retreiveRecord: function() {
        var productGr = new GlideRecord('x_products');
        var results = {
            productcode: null,
            currentQty: null
        };
        if (productGr.get(this.productId)) {
            results = {
                productcode: productGr.getValue('productcode'),
                currentQty: parseInt(productGr.getValue('quantityonstock'), 10)
            };
            return results;
        }
        return results;
    },

    //Update Record
    _updateRecord: function(vnewQty) {
        var productGrUpd = new GlideRecord('x_products');
        if (productGrUpd.get(this.productId)) {
			gs.info('New value for productcode(' + productGrUpd.getValue('productcode') + ') = ' + vnewQty.toString());
            productGrUpd.setValue('quantityonstock', vnewQty.toString());
            var updResult = productGrUpd.update();
			gs.info('updResult: '+ updResult);
			gs.info('Updated the Record!');
        }
    },

    //Zero Out Quantity
    zeroOutQty: function() {
        var response = this._retreiveRecord();
        gs.info('response.currentQty =' + response.currentQty + ' for productcode ' + response.productcode);
        if (response.productcode) {
            const newQty = 0;
            this._updateRecord(newQty);
            return 'Record Found and Zeroed out for productcode ' + response.productcode;
        }
        return 'Record Not Found for sysid ' + this.productId;
    },

    type: 'processInventoryUtility'
};
  • After running the fix script, when I view the record in the x_product table, it is unchanged. 
  • x_product is in the ABC scope. 
  • Please note that I can update a different custom table in the scope. 
  • This x_product table is an extension of the sc_cat_item table, but the quantityonstock field is only in the x_product table as a custom string field.

 

I'm able to see that the record is found but the update statement returns null.  See updResult in the system log below.  There are not errors. 

Renee17_0-1767719028231.png

 

I can run the update portion of the script include with no problems from Background Scripts.  But my understanding is that security posture is not as tight when running scripts in background scripts.  I am running the script as WMS scope. (Below is a snippet of what I run in background script).  My understanding is that this loose security posture holds true for imports also, as our transform map is able to update quantityonstock  based on data provided in a file.

	var productGrUpd = new GlideRecord('x_products');
        if (productGrUpd.get('b829d27047d5ee50d56a0f6ba26d4346')) {
            productGrUpd.setValue('quantityonstock', '0');
            var updResult = productGrUpd.update();
			gs.info('updResult: '+ updResult);
			gs.info('Updated the Record!');
        }

 
Note:  I also can't update the field when viewing the list.  No matter if I am in WMS or ABC scope.

Renee17_1-1767720286508.png

 

I've also switched everything from WMS scope in terms of the script include and the fix script and created the same version of it under the ABC scope and still get the same results - No update happens.

 

  • The field is not read-only
  • I've checked business rules on both the x_products table and the table it extends sc_cat_item.  The only business rule I see is global is to prevent an update when the record is checked out.  We don't use this field and it is currently blank for all records in the x_products table.
  • I've performed the cross-scope privileges.  
  • I've checked that the table allows for accessibility from All application scopes where caller access is None and can read/create/update/delete are all checked.  Allow access to this table via web services and allow configuration are all checked.
  • I did find something interesting in Form Builder that I hadn't seen before and wondering if this is the culprit.  Attributes for the quantityonstock shows edge_encription_enabled=true.  However if you view the  Dictionary Entry for quantityonstock, it is empty under the attribute field.  I only see it when viewing it in Form Builder as show below.

Renee17_2-1767721577611.png

Renee17_0-1767723852491.png

 

Could the edge_ecryption_enabled=true be my issue or some other type of security attribute or something special about extending from sc_cat_item?  (NOTE: Don't think its related to edge_ecryption_enabled as we don't have it setup in our instance.)

 

Thanks in advance for your help on this topic!

3 ACCEPTED SOLUTIONS

Ankur Bawiskar
Tera Patron

@Renee-17 

script include is in which scope? if same then you should be able to update.

share some screenshots.

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

View solution in original post

Sandesh Powar
Tera Expert

Hey @Renee-17 ,

Thanks for all those detailed screenshots and info - that really helps! Based on everything you've shared, I think I've spotted your issue.

The Problem: You're getting null on the update, which in ServiceNow typically means the update was blocked by an ACL (Access Control List) specifically for write operations.

Here's what's interesting - you mentioned you can't update the field even from the list view, which is a dead giveaway that there's a write ACL blocking you.

Here's what to check:

  1. Field-Level ACLs - This is most likely your culprit:
    • Go to System Security > Access Control (ACL)
    • Filter by: Name = x_products.quantityonstock AND Operation = write
    • Check if there's an ACL that's denying write access
    • Look at the Condition and Script fields - there might be logic preventing updates
  2. Table-Level Write ACLs:
    • Also check for ACLs on x_products table with operation = write
    • And check the parent sc_cat_item table too since you're extending it
  3. The edge_encryption_enabled attribute - This is probably NOT your issue since you confirmed it's not configured, but it's worth noting that encrypted fields can sometimes behave oddly.

Quick Test to Confirm: Run this in Background Scripts with your WMS scope:

javascript
var gr = new GlideRecord('x_products');
if (gr.get('b829d27047d5ee50d56a0f6ba26d4346')) {
    gs.info('Can Write to table: ' + gr.canWrite());
    gs.info('Can Write to field: ' + gr.quantityonstock.canWrite());
}

If canWrite() returns false, you've confirmed it's an ACL issue.

The Fix: Once you find the blocking ACL, you'll need to either:

  • Modify the ACL condition to allow your use case
  • Add a role requirement and grant that role to the appropriate users/scripts
  • Create a new ACL with higher order that allows your specific scenario

The reason Background Scripts and imports work is because they run with elevated privileges that bypass normal ACLs. Your Script Include runs with normal security enforcement.

Let me know what you find when you check those ACLs - I'm betting that's where your answer is!


Hope this helps! If this resolves your issue, please mark it as the accepted answer so others with similar problems can find the solution easily.

Best regards!
Sandesh

View solution in original post

I was finally able to get the cross-scope update to occur.  For some reason as an admin user developing the app, when I tried to test the update, it fails.  However, if I log in as a test user that has access to the WMS App it can perform the cross-scope update.  I currently have two button set-up for testing. 

  1. One that calls a data transform server side script that calls the cross-scope script include
  2. and the other is a REST transform data broker that calls a Scripted REST Resource that calls the cross-scope script include that performs the update.

Both buttons work and perform the update for the test user account but not for my normal admin account that I'm using to develop the app, even though it contains the roles.  So there must be some ACL blocking me as an admin, but I can't figure it out.  I'm satisfied that at least I can perform the update via a test user account.

 

I did enable Debug mode and could see that the write operation was blocked but it was vague about what the ACL was.  I did update the ACL to include admin and the new rules associated with the wms app.  I ran the analyze access tool from the form view of one of the table records and saw that write and create operations are blocked by UpdateSetAccessHandler.  I'm not sure if this is related to why I can't test that piece of code with favorable results as the admin and developer.  I am able to perform other cross-scope updates without a problem, it was just this specific table.  I feel like it has something to do with the sc_cat_item table that it's extending... although it doesn't make since to me because the column I'm updating is a custom field only on the extended table.  I checked the business rules and acls on both the extended table and sc_cat_item.  

View solution in original post

12 REPLIES 12

Sandesh Powar
Tera Expert

Hey @Renee-17 ,

This is definitely a scope access issue since your code works everywhere else but not in the Script Include.

Here's what's happening: Your Script Include is probably running from a different scope than where your x_product table lives, and it doesn't have permission to write to that table.

The fix is pretty straightforward:

Go to your scoped app (the one with the x_product table) and set up Application Access:

  1. Open System Applications > All Available Applications and find your scoped app
  2. Click on the Application Access tab
  3. Create a new record with:
    • Operation: write
    • Status: Allowed
    • Source Scope: wherever your Script Include is running from (could be global or another scope)

That should do it! The reason your widget and backend scripts work is because they're either running in the right scope already or have elevated privileges that your Script Include doesn't get automatically.

If you're still stuck after trying this, let me know which scope your Script Include is in and I can give you more specific guidance.


Hope this helps! If this resolves your issue, please mark it as the accepted answer so others can find the solution easily.

Best regards!
Sandesh

 

Hi Sandesh,

 

Thank you for the info.  I've explored and tried this solution as well and it didn't solve the problem.  I did add some additional info to the original post with screenshots.  

Siddhesh Gawade
Mega Sage

@Renee-17 

 

How you are calling this script include to update the fields in scope app. make sure you are calling this script in same scope otherwise make the script include accessible from all scopes. and instead of using script name to call use API name. 

SiddheshGawade_0-1767673923147.png

 

 

Regards,

Siddhesh

Thanks for your response.

All application scope is set and their currently isn't an issue with calling the script include.  It just doesn't perform the update on a field within the script include.  (I added more info to the post with screenshots)