catalog item

Rishabh_N
Tera Contributor

Hi everyone,

I have a catalog item for group retirement. Before retiring a group, I need to check its dependencies.
I created a Script Include to check dependencies (like Business Rules, ACLs, UI Actions, Client Scripts, etc.) and used it in a workflow Run Script activity  it works fine, but it’s hardcoded and limited.

My question is if a group has a lot of dependencies (some that we don’t even know), how can we identify them dynamically? Since we can’t write individual methods for each dependency in the Script Include, what’s the best approach or best practice in real-time projects?

2 REPLIES 2

RaghavSh
Kilo Patron

So it has to be checked individually and it gets complex with flows being used in workflow/ flow designer.

 

But refer https://www.servicenow.com/community/developer-articles/checking-group-dependency-before-deactivatin...  

this article is quite detailed and will be helpful.


Raghav
MVP 2023

Chavan AP
Tera Guru

Hello Rishabh, here is the script include that can cover all possible scenario, if you find any new scenario just add new check in the same:

 

var SimpleGroupChecker = Class.create();
SimpleGroupChecker.prototype = {
    
    checkGroupDependencies: function(groupSysId) {
        var dependencies = [];
        var groupName = this._getGroupName(groupSysId);
        
        if (!groupName) {
            return { success: false, message: 'Group not found' };
        }
        
        // Step 1: Check direct reference fields
        this._checkDirectReferences(groupSysId, dependencies);
        
        // Step 2: Check script content
        this._checkScriptReferences(groupSysId, groupName, dependencies);
        
        // Step 3: Check workflows
        this._checkWorkflows(groupSysId, groupName, dependencies);
        
        return {
            success: true,
            groupName: groupName,
            canRetire: dependencies.length === 0,
            totalDependencies: dependencies.length,
            dependencies: dependencies
        };
    },
    
    // Check common tables with assignment_group fields
    _checkDirectReferences: function(groupSysId, dependencies) {
        var tablesToCheck = [
            'incident', 'change_request', 'sc_request', 'sc_task',
            'problem', 'sys_user_grmember', 'cmn_schedule'
        ];
        
        for (var i = 0; i < tablesToCheck.length; i++) {
            var tableName = tablesToCheck[i];
            
            if (this._tableExists(tableName)) {
                var gr = new GlideRecord(tableName);
                
                // Try assignment_group field first
                if (this._fieldExists(tableName, 'assignment_group')) {
                    gr.addQuery('assignment_group', groupSysId);
                }
                // For group membership table
                else if (tableName === 'sys_user_grmember') {
                    gr.addQuery('group', groupSysId);
                }
                // For schedule table
                else if (tableName === 'cmn_schedule') {
                    gr.addQuery('group', groupSysId);
                }
                
                gr.setLimit(5); // Limit results for performance
                gr.query();
                
                while (gr.next()) {
                    dependencies.push({
                        table: tableName,
                        record: gr.getDisplayValue(),
                        type: this._getTableType(tableName),
                        link: gr.getLink()
                    });
                }
            }
        }
    },
    
    // Check scripts for group references
    _checkScriptReferences: function(groupSysId, groupName, dependencies) {
        var scriptTables = [
            'sys_script',        // Business Rules
            'sys_script_client', // Client Scripts
            'sys_ui_action',     // UI Actions
            'sys_security_acl'   // ACLs
        ];
        
        for (var i = 0; i < scriptTables.length; i++) {
            var tableName = scriptTables[i];
            
            if (this._tableExists(tableName)) {
                var gr = new GlideRecord(tableName);
                gr.addQuery('active', true);
                
                // Search in script field for group sys_id or name
                var query = 'scriptCONTAINS' + groupSysId + '^ORscriptCONTAINS' + groupName;
                if (tableName === 'sys_security_acl') {
                    query += '^ORconditionCONTAINS' + groupSysId + '^ORconditionCONTAINS' + groupName;
                }
                
                gr.addEncodedQuery(query);
                gr.setLimit(3);
                gr.query();
                
                while (gr.next()) {
                    dependencies.push({
                        table: tableName,
                        record: gr.getDisplayValue(),
                        type: this._getTableType(tableName),
                        link: gr.getLink()
                    });
                }
            }
        }
    },
    
    // Check workflows
    _checkWorkflows: function(groupSysId, groupName, dependencies) {
        if (this._tableExists('wf_activity')) {
            var gr = new GlideRecord('wf_activity');
            gr.addQuery('active', true);
            gr.addEncodedQuery('varsCONTAINS' + groupSysId + '^ORvarsCONTAINS' + groupName);
            gr.setLimit(3);
            gr.query();
            
            while (gr.next()) {
                dependencies.push({
                    table: 'wf_activity',
                    record: gr.getDisplayValue(),
                    type: 'Workflow',
                    link: gr.getLink()
                });
            }
        }
    },
    
    // Helper functions
    _getGroupName: function(groupSysId) {
        var gr = new GlideRecord('sys_user_group');
        if (gr.get(groupSysId)) {
            return gr.getValue('name');
        }
        return null;
    },
    
    _tableExists: function(tableName) {
        return GlideTableDescriptor.tableExists(tableName);
    },
    
    _fieldExists: function(tableName, fieldName) {
        return GlideTableDescriptor.fieldExists(tableName, fieldName);
    },
    
    _getTableType: function(tableName) {
        var types = {
            'incident': 'Incident',
            'change_request': 'Change Request',
            'sc_request': 'Service Request',
            'sc_task': 'Catalog Task',
            'problem': 'Problem',
            'sys_user_grmember': 'Group Member',
            'cmn_schedule': 'Schedule',
            'sys_script': 'Business Rule',
            'sys_script_client': 'Client Script',
            'sys_ui_action': 'UI Action',
            'sys_security_acl': 'Access Control',
            'wf_activity': 'Workflow'
        };
        return types[tableName] || tableName;
    },
    
    type: 'SimpleGroupChecker'
};

 

Now run below script in Background script for specific group:

 

// Test a specific group by name
var groupName = 'IT Support'; // Change this to your group name

var groupGR = new GlideRecord('sys_user_group');
if (groupGR.get('name', groupName)) {
    
    // Call the Script Include
    var checker = new SimpleGroupChecker();
    var result = checker.checkGroupDependencies(groupGR.getUniqueValue());
    
    // Simple output
    gs.print('Group: ' + groupName);
    gs.print('Can retire: ' + (result.canRetire ? 'YES' : 'NO'));
    
    if (!result.canRetire) {
        gs.print('Reason: ' + result.totalDependencies + ' dependencies found');
        
        // List first 3 dependencies
        for (var i = 0; i < Math.min(3, result.dependencies.length); i++) {
            gs.print('- ' + result.dependencies[i].type + ': ' + result.dependencies[i].record);
        }
    }
} else {
    gs.print('Group "' + groupName + '" not found');
}

 

Chavan AP
[ Architect | Certified Professional]

Was this response helpful? If so, please mark it as Helpful and Accept as Solution to help others find answers.