Skip to content

Commit 95f3a8c

Browse files
authored
Merge branch 'ServiceNowDevProgram:main' into main
2 parents d4cc613 + f284dab commit 95f3a8c

File tree

198 files changed

+5300
-266
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

198 files changed

+5300
-266
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
var ab=new GlideRecord('sysapproval_approver');
3+
ab.addQuery('sysapproval','<Approval_record_sys_id>');
4+
ab.query();
5+
if(ab.next())
6+
{
7+
ab.approver.setDisplayValue('<User_Display_Name>')';
8+
ab.update();
9+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Use the code to change approver for any record from background script
2+
Replace <Approval_record_sys_id> with sys_id of record for which approval is triggered
3+
Replace <User_Display_Name> with name of user who needs to be set as approver
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
function changeUpdateSetApplicationScope(updateSetName, currentApplicationScope, newApplicationScope) {
2+
3+
var newApplicationScopeSysId = getApplicationScopeSysId(newApplicationScope);
4+
5+
var updateSetGR = new GlideRecord("sys_update_set");
6+
updateSetGR.addQuery('name', updateSetName);
7+
updateSetGR.addQuery('application.name', currentApplicationScope);
8+
updateSetGR.query();
9+
10+
if (updateSetGR.next()) {
11+
updateSetGR.setValue('application', newApplicationScopeSysId);
12+
updateSetGR.update();
13+
}
14+
15+
}
16+
17+
function getApplicationScopeSysId(scopeName) {
18+
19+
var appGR = new GlideRecord('sys_app');
20+
appGR.addQuery('name', scopeName);
21+
appGR.query();
22+
if (appGR.next()) {
23+
return appGR.getValue('sys_id');
24+
}
25+
}
26+
27+
changeUpdateSetApplicationScope('updateSetName', 'currentApplicationScope', 'newApplicationScope');
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Change update set application scope
2+
In ServiceNow, there are instances where an update set is mistakenly created in the incorrect application scope. To rectify this, I've developed a background script that facilitates the alteration of the update set's application scope to the appropriate one.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
function cloneUser(currentUserId, newUserId) {
2+
3+
var newUserRecordSysId = createNewUserRecord(newUserId);
4+
cloneCurrentUserFields(currentUserId, newUserId);
5+
cloneUserRoles(currentUserId, newUserRecordSysId);
6+
cloneUserGroups(currentUserId, newUserRecordSysId);
7+
}
8+
9+
function cloneCurrentUserFields(currentUserId, newUserId) {
10+
11+
var currentUserGR = new GlideRecord("sys_user");
12+
currentUserGR.addQuery("user_name", currentUserId);
13+
currentUserGR.query();
14+
15+
if (currentUserGR.next()) {
16+
var newUserGR = new GlideRecord("sys_user");
17+
newUserGR.addQuery("user_name", newUserId);
18+
newUserGR.query();
19+
if (newUserGR.next()) {
20+
var userGRU = new GlideRecordUtil();
21+
var fieldList = userGRU.getFields(currentUserGR);
22+
for (var index = 0; index < fieldList.length; index++) {
23+
var fieldName = fieldList[index];
24+
if (!newUserGR.getValue(fieldName)) {
25+
newUserGR.setValue(fieldName, currentUserGR.getValue(fieldName));
26+
newUserGR.update();
27+
}
28+
};
29+
}
30+
}
31+
}
32+
33+
function createNewUserRecord(userId) {
34+
35+
var userGR = new GlideRecord("sys_user");
36+
userGR.initialize();
37+
userGR.setValue("user_name", userId);
38+
var sysId = userGR.insert();
39+
return sysId;
40+
}
41+
42+
function cloneUserRoles(currentUserId, newUserRecordSysId) {
43+
44+
var currentUserRoleGR = new GlideRecord("sys_user_has_role");
45+
currentUserRoleGR.addQuery('user.user_name', currentUserId);
46+
currentUserRoleGR.addQuery('inherited', 'false');
47+
currentUserRoleGR.query();
48+
49+
while (currentUserRoleGR.next()) {
50+
var newUserRoleGR = new GlideRecord("sys_user_has_role");
51+
newUserRoleGR.initialize();
52+
newUserRoleGR.setValue('user', newUserRecordSysId);
53+
newUserRoleGR.setValue('role', currentUserRoleGR.getValue('role'));
54+
newUserRoleGR.insert();
55+
}
56+
}
57+
58+
function cloneUserGroups(currentUserId, newUserRecordSysId) {
59+
60+
var currentUserGroupGR = new GlideRecord("sys_user_grmember");
61+
currentUserGroupGR.addQuery('user.user_name', currentUserId);
62+
currentUserGroupGR.query();
63+
64+
while (currentUserGroupGR.next()) {
65+
var newUserGroupGR = new GlideRecord("sys_user_grmember");
66+
newUserGroupGR.initialize();
67+
newUserGroupGR.setValue('user', newUserRecordSysId);
68+
newUserGroupGR.setValue('group', currentUserGroupGR.getValue('group'));
69+
newUserGroupGR.insert();
70+
}
71+
}
72+
73+
cloneUser('currentUserId', 'newUserId'); //currentUserId: Id of the you that we want to clone, newUserId: Id of the new user record.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Clone User with Roles and Groups
2+
I have created a script in ServiceNow to replicate a user's profile. This script not only duplicates the user's data but also replicates the roles and groups assigned to that user.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
Format currency values to your preferred locale and format.
2+
Examples are provided for EUR, HUF with English and Hungarian number format.
3+
4+
formatString values:
5+
Valid values:
6+
7+
%s: Replaced by the currency symbol associated with the country code specified in the format() call.
8+
%v: Replaced by the currency amount, such as 123.45.
9+
%c: Replaced by the ISO currency code specified in the format() call, such as USD or EUR.
10+
%l: Replaced with the passed in value, no formatting performed.
11+
%p: Replaced by the percent sign (%).
12+
For example, if the format string is '%s%v%c' and the value to format is 123.45 in US dollars, the returned formatted string is $123.45 USD. If the format string is '%s%l%c' and the value string to format is '56M' in Euros, the returned formatted string is €56M EUR.
13+
14+
setMaxFractionDigits:
15+
Maximum number of fraction digits to return. Does a rounding based on the closest right-most digit.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
var amount = '9123456.123456789';
2+
var currencyCode = 'EUR';
3+
var formatString = '%s%v %c';
4+
var exchangeValue = new sn_currency.GlideCurrencyFormatter(formatString);
5+
exchangeValue.setLocale("en", "EN"); // Language = en Country = EN
6+
7+
gs.info('Formatted currency: ' + exchangeValue.setMaxFractionDigits(1).format(amount, currencyCode));
8+
// expected output: Formatted currency: €9,123,456.1 EUR
9+
10+
amount = '9123456.127456789';
11+
currencyCode = 'HUF';
12+
formatString = '%v %c';
13+
exchangeValue = new sn_currency.GlideCurrencyFormatter(formatString);
14+
exchangeValue.setLocale("hu", "HU"); // Language = hu Country = HU
15+
16+
gs.info('Formatted currency: ' + exchangeValue.setMaxFractionDigits(2).format(amount, currencyCode));
17+
// expected output: Formatted currency: 9 123 456,13 HUF
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
var grSearchGroup = new GlideRecord('sn_codesearch_search_group');
2+
3+
grSearchGroup.query();
4+
5+
//iterate all code search groups
6+
while (grSearchGroup.next()) {
7+
var grDictionary = new GlideRecord('sys_dictionary');
8+
var strSearchGroupSysID = grSearchGroup.getValue('sys_id');
9+
var objArrayUtil = new ArrayUtil();
10+
11+
//determine all candidates for a code search from the dictionary
12+
grDictionary.addEncodedQuery(
13+
'internal_type.nameINscript,condition,condition_string,script_plain,XML,script_server' +
14+
'^ORelement=reference_qual' +
15+
'^ORelement=calculation' +
16+
'^NQelementSTARTSWITHscript' +
17+
'^ORelementLIKE_script' +
18+
'^internal_type.nameSTARTSWITHstring' +
19+
'^ORinternal_type.name=json' +
20+
'^NQname=sys_variable_value' +
21+
'^element=value'
22+
);
23+
24+
grDictionary.query();
25+
26+
while (grDictionary.next()) {
27+
var grCodeSearch = new GlideRecord('sn_codesearch_table');
28+
var strTable = grDictionary.getValue('name');
29+
var strField = grDictionary.getValue('element');
30+
31+
//load everything which is already registered as code search base
32+
grCodeSearch.addQuery('table', strTable);
33+
grCodeSearch.addQuery('search_group', strSearchGroupSysID);
34+
grCodeSearch.setLimit(1);
35+
grCodeSearch.query();
36+
37+
//for the respective table there is already a record available
38+
if (grCodeSearch.next()) {
39+
var arrFields = grCodeSearch.getValue('search_fields').split(',');
40+
41+
arrFields.push(strField);
42+
grCodeSearch.setValue('search_fields', objArrayUtil.unique(arrFields).join(','));
43+
grCodeSearch.update();
44+
}
45+
// create a new record at table "sn_codesearch_table"
46+
else {
47+
grCodeSearch.initialize();
48+
grCodeSearch.setValue('table', strTable);
49+
grCodeSearch.setValue('search_group', strSearchGroupSysID);
50+
grCodeSearch.setValue('search_fields', strField);
51+
grCodeSearch.insert();
52+
}
53+
}
54+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Description
2+
Over time, your code spreads across dozens of artifact types and it becomes very difficult to keep track of it all.
3+
4+
The whole thing is made more difficult by the fact that JavaScript code is not always contained in pure script fields but also, for example, in conditions or even in JSON payloads.
5+
6+
Fortunately, there is a code search - for example in the ServiceNow Studio, via the UI page "CodeSearchExampleUse" or with the help of the browser extension "SN Utils".
7+
8+
However in a baseline instance the code search covers about 31 tables and their fields only. If you want to search all available tables and script-related fields, you can execute my script `add_more_tables_to_code_search`. It determines in the dictionary all potential candidates that could hold JavaScript code and add them to the code search base.
9+
10+
# Involved tables
11+
12+
## `sn_codesearch_search_group`
13+
14+
A search group has a certain name and covers all tables and fields which can be searched when using that search group. Utilizing "SN Utils" browser extension you can select the preferred search group. Within ServiceNow Studio this is not possible and the search group "sn_devstudio.Studio" is leveraged automatically. For this reason my script adds all tables and fields to all search groups the same way.
15+
16+
## `sn_codesearch_table`
17+
18+
Each record in that table represent a table and their fields which are searchable. These records are added or complemented by my script.
19+

0 commit comments

Comments
 (0)