- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
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?
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
@Rishabh_N - did you check?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
@Rishabh_N Custom table is not necessary, what is important here is that someone take care of dependencies before deleting/deactivating the group.
What you did is absolutely fine and will work in real time as well.
One more thing you need to add in your catalog task description or maybe variable is that anyone who is working on the task should reassign the task based record( inc/prb/change/sc_task) or any other module you are using to some active group or get these records closed before deactivating. This step can also be automated in your workflow with simple glide on task table and querying open records with existing group and replacing that, but its totally upto your wish , how you want to implement this.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Thanks a lot for your detailed reply @RaghavSh. That makes sense , i will definitely try out your suggestion.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
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');
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
@Rishabh_N - did you check?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
hi Chavan
I copied this script include and executed the background script.
It is very interesting and kudus to the effort you put in!
For a Yokohama PDI instance, the following changes need to be done.
1. In the function _checkWorkFlows, the script checks if active is true - there is no field "active" in wf_activity. So, the line "gr.addQuery('active', true)" throws invalid query.
QueryEventLogger: Invalid query detected, please check logs for details [Unknown field active in table wf_activity]
2. When the script checks for existence of table and fields using GlideTableDescriptor API, I get error for using the methods "