Skip to content

Commit fbab8cb

Browse files
Merge branch 'ServiceNowDevProgram:main' into SNTips
2 parents 16ae590 + c71bf3f commit fbab8cb

File tree

34 files changed

+651
-0
lines changed

34 files changed

+651
-0
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
var obj ={};
2+
obj.name = 'Mohit Kaushik';
3+
obj.email ='[email protected]';
4+
obj.contact = '1234567890';
5+
6+
var str = JSON.stringify(obj,null,4);
7+
8+
var encryption = GlideStringUtil.base64Encode(str);
9+
gs.info(encryption);
10+
11+
var decrypt = GlideStringUtil.base64Decode(encryption);
12+
gs.info(JSON.stringify(decrypt,null,2));
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This code is an example to encrypt or decrypt the payload using base64Encode and decode methods of GlideStringUtil API.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
var myGroups = [];
2+
var grGroup = new GlideRecord("sys_user_group");
3+
grGroup.addActiveQuery();
4+
grGroup.query();
5+
while (grGroup.next()) {
6+
var gaGroupMember = new GlideAggregate("sys_user_grmember");
7+
gaGroupMember.addQuery("group",grGroup.sys_id.toString());
8+
gaGroupMember.addAggregate('COUNT');
9+
gaGroupMember.query();
10+
var gm = 0;
11+
if (gaGroupMember.next()) {
12+
gm = gaGroupMember.getAggregate('COUNT');
13+
if (gm == 0)
14+
myGroups.push(grGroup.name.toString());
15+
}
16+
}
17+
gs.print(myGroups);
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
**Initialize an Array:**
2+
var myGroups = [];
3+
4+
**Create a GlideRecord Object for User Groups:**
5+
var grGroup = new GlideRecord("sys_user_group");
6+
7+
**Add a Query for Active Groups:**
8+
grGroup.addActiveQuery();
9+
10+
**Execute the Query:**
11+
grGroup.query();
12+
13+
**Iterate Through Active Groups:**
14+
while (grGroup.next()) {
15+
16+
**Count Group Members:**
17+
var gaGroupMember = new GlideAggregate("sys_user_grmember");
18+
gaGroupMember.addQuery("group", grGroup.sys_id.toString());
19+
gaGroupMember.addAggregate('COUNT');
20+
gaGroupMember.query();
21+
22+
**Check Member Count:**
23+
var gm = 0;
24+
if (gaGroupMember.next()) {
25+
gm = gaGroupMember.getAggregate('COUNT');
26+
if (gm == 0)
27+
myGroups.push(grGroup.name.toString());
28+
}
29+
30+
**Print the Results:**
31+
gs.print(myGroups);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// In this before insert or update Business Rule, we are fetching a reference field value from higher-level parents in hierarchy when there is a field containing the parent record in the children and our use-case reference field is present in all the tables in hierarchy
2+
// I would be referring to "reference field name we want to populate" as "r1"
3+
// I would be referring to "reference field containing parent record" as "parent"
4+
5+
6+
(function executeRule(current, previous /*null when async*/ ) {
7+
if (current.r1 == "" && !JSUtil.nil(current.parent.r1)) // Populate 'use-case reference field' from parent's value for the reference field'
8+
current.r1 = current.parent.r1;
9+
else if (current.< reference field name we want to populate > == "" && !JSUtil.nil(current.parent.parent.r1)) // Populate 'use-case reference field' from 'parent of parent'
10+
current.r1 = current.parent.parent.r1;
11+
12+
})(current, previous);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
This is a "**before insert/update**" Business Rule
2+
We are fetching a reference field value from higher-level parents in hierarchy
3+
when there is a field containing the parent record in the children and
4+
our use-case reference field is present in all the tables in hierarchy
5+
6+
In the code, we are referring to "reference field name we want to populate" as "_r1_"
7+
In the code, we are referring to "reference field containing parent record" as "_parent_"
8+
9+
The "**JSUtil.nil**" is being used to check for empty/null value for the field.
10+
11+
12+
Through the code we are checking the empty value of the use-case reference field and dot walking to parents and fetching the value from them if it exists
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Scenario: You are wanting to send a notification to someone whenever they are added to a list of people.
2+
3+
Application: Create an event in the event registry. Then, create a business rule. Set the name and table, advanced = true.
4+
5+
When to run:
6+
When = after, update = true, conditions = watch list (replace with applicable field name) | changes
7+
8+
Advanced tab: insert the snippet
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
(function executeRule(current, previous /*null when async*/) {
2+
3+
// Ensure the 'watch_list' (replace with applicable field name) field has been modified
4+
if (current.watch_list != previous.watch_list) {
5+
6+
// Split the current and previous watch lists into arrays
7+
var newWatchers = current.watch_list.split(',');
8+
var oldWatchers = previous.watch_list ? previous.watch_list.split(',') : [];
9+
10+
// Identify the newly added users to the watch list
11+
var addedUsers = newWatchers.filter(function (user) {
12+
return oldWatchers.indexOf(user) === -1;
13+
});
14+
15+
// Loop through the added users to trigger the event for each
16+
addedUsers.forEach(function(userID) {
17+
var email;
18+
var firstName;
19+
20+
// Try to get the user record by user ID (sys_id)
21+
var userGr = new GlideRecord('sys_user');
22+
if (userGr.get(userID)) {
23+
firstName = userGr.first_name;
24+
email = userGr.email;
25+
} else {
26+
27+
// If no user record is found, assume the userID is an email address
28+
email = userID;
29+
firstName = "Team";
30+
}
31+
32+
// Trigger the event (replace "new_member") with the current case and user information
33+
gs.eventQueue('new_member', current, email, firstName);
34+
});
35+
}
36+
})(current, previous);
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Overview
2+
This script logs specific user actions (e.g: record updates and approvals) in ServiceNow into a custom table `u_user_activity_log`.
3+
4+
This provides audit capabilities and allowing developers to track user actions for compliance or analytics.
5+
6+
# How It Works
7+
The script is triggered by a Business Rule on record updates and checks for changes in specified critical fields (e.g., `state`, `approval`). When a change occurs, it logs relevant details in the `u_user_activity_log` table, including:
8+
- `u_user`: User ID
9+
- `u_action`: Type of action performed
10+
- `u_record_id`: ID of the updated record
11+
- `u_record_table`: Name of the table where the change occurred
12+
- `u_description`: Brief description of the action
13+
14+
# Implementation
15+
- Create Custom Table: Ensure `u_user_activity_log` table exists with fields like `u_user`, `u_action`, `u_record_id`, `u_record_table`, `u_description`, etc.
16+
- Configure Business Rule: Set the Business Rule to run on update and add conditions for monitoring fields (`state`, `approval`).
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Script to log user actions (updates, approvals) into a custom table
2+
(function executeRule(current, previous /*null when async*/) {
3+
// Check if key fields are modified (customize as needed)
4+
if (current.state.changes() || current.approval.changes()) {
5+
var logEntry = new GlideRecord('u_user_activity_log');
6+
logEntry.initialize();
7+
8+
// Populate log details
9+
logEntry.u_user = gs.getUserID();
10+
logEntry.u_action = current.state.changes() ? "State Change" : "Approval Change";
11+
logEntry.u_record_id = current.sys_id;
12+
logEntry.u_record_table = current.getTableName();
13+
logEntry.u_description = "User " + gs.getUserDisplayName() + " updated " + logEntry.u_action;
14+
15+
logEntry.insert();
16+
}
17+
})(current, previous);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
2+
if (isLoading || newValue == '') {
3+
return;
4+
}
5+
if (newValue == 'inquiry') { //Onchange of Category
6+
g_form.removeOption('impact', '1');
7+
g_form.removeOption('urgency', '1');
8+
}
9+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
**Purpose:**
2+
This onChange function automatically reacts when the "Category" field is changed. If the new category selected is "inquiry," the function removes the options for "Impact" and "Urgency" that have a value of 1.
3+
Whenever a user selects a new category, the script checks if it’s set to "inquiry." If so, it removes the specified options for "Impact" and "Urgency".
4+
**How to Use This Function**
5+
You can use this Onchange client script on any form and maanage your field choice options.
6+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Get the count of Incidents by Category and then by Priority.
2+
3+
var incCATGR = new GlideAggregate('incident');
4+
incCATGR.addAggregate('COUNT', 'category');
5+
incCATGR.orderBy('category');
6+
incCATGR.query();
7+
8+
while (incCATGR.next()) {
9+
var cat = incCATGR.category;
10+
gs.print("Category Name: " +incCATGR.category.getDisplayValue() + ' --> ' + incCATGR.getAggregate('COUNT', 'category'));
11+
var incPriorityGR = new GlideAggregate('incident');
12+
incPriorityGR.addQuery('category', incCATGR.category);
13+
incPriorityGR.addAggregate('COUNT', 'priority');
14+
incPriorityGR.orderBy('priority');
15+
incPriorityGR.query();
16+
17+
while(incPriorityGR.next()){
18+
gs.print("Priority-" +incPriorityGR.priority + " = " +incPriorityGR.getAggregate('COUNT', 'priority'));
19+
}
20+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
Purpose: This piece of code will be helpful to get the count of incidents by Priority under each Category.
2+
3+
Sample Output:
4+
==============
5+
*** Script: Category Name: --> 4
6+
*** Script: Priority-1 = 2
7+
*** Script: Priority-2 = 1
8+
*** Script: Priority-4 = 1
9+
*** Script: Category Name: Database --> 3
10+
*** Script: Priority-1 = 1
11+
*** Script: Priority-4 = 1
12+
*** Script: Priority-5 = 1
13+
*** Script: Category Name: Hardware --> 10
14+
*** Script: Priority-1 = 5
15+
*** Script: Priority-3 = 2
16+
*** Script: Priority-5 = 3
17+
*** Script: Category Name: Inquiry / Help --> 84
18+
*** Script: Priority-1 = 10
19+
*** Script: Priority-2 = 2
20+
*** Script: Priority-3 = 13
21+
*** Script: Priority-4 = 17
22+
*** Script: Priority-5 = 42
23+
*** Script: Category Name: Network --> 12
24+
*** Script: Priority-1 = 2
25+
*** Script: Priority-2 = 2
26+
*** Script: Priority-3 = 1
27+
*** Script: Priority-4 = 2
28+
*** Script: Priority-5 = 5
29+
*** Script: Category Name: Software --> 131
30+
*** Script: Priority-1 = 15
31+
*** Script: Priority-2 = 15
32+
*** Script: Priority-3 = 23
33+
*** Script: Priority-4 = 28
34+
*** Script: Priority-5 = 50
35+
36+
37+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
var grAppr = new GlideRecord("sysapproval_approver");
2+
grAppr.addEncodedQuery("sys_created_on<javascript:gs.beginningOfLast12Months()^state=requested");
3+
grAppr.query();
4+
while(grAppr.next()){
5+
grAppr.setValue('state', 'rejected');
6+
grAppr.update();
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
**Script Purpose:**
2+
This script helps you manage approval records in ServiceNow. It searches for approval requests in the sysapproval_approver table that were created more than 12 months ago and are currently marked as "requested." The script then updates these records to change their status to "rejected."
3+
4+
**How to Use This Script**
5+
Where to Run It: You can execute this script in a server-side context, such as a Scheduled Jobs, Script Include, or Background Script. Make sure you have the necessary permissions to access and update records in the sysapproval_approver table.
6+
7+
**Be Cautious:** The script will automatically find the relevant approval records and update all matching records, so double-check the criteria before executing it.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
var grApp = new GlideRecord("cmdb_ci_appl");
2+
grApp.addEncodedQuery("owned_by.active=false");
3+
grApp.query();
4+
while(grApp.next()){
5+
var managerSysId = grApp.owned_by.manager.toString(); // Get Manager SysId
6+
if (managerSysId) {
7+
grApp.owned_by = managerSysId;
8+
grApp.update();
9+
}
10+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
This code snippet will update the owner of application records in the cmdb_ci_appl table where the current owner is inactive. It specifically sets the owner to the manager of that inactive owner, ensuring that each application has an active owner assigned.
2+
3+
**GlideRecord Initialization:**
4+
var grApp = new GlideRecord("cmdb_ci_appl");
5+
6+
**Query for Inactive Owners:**
7+
grApp.addEncodedQuery("owned_by.active=false");
8+
9+
**Executing the Query:**
10+
grApp.query();
11+
12+
**Iterating Through Records:**
13+
while(grApp.next()){
14+
15+
**Getting the Manager’s Sys ID:**
16+
var managerSysId = grApp.owned_by.manager.toString();
17+
18+
**Updating the Owner:**
19+
if (managerSysId) {
20+
grApp.owned_by = managerSysId;
21+
grApp.update();
22+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Calendar Widget for ServiceNow Portal
2+
This widget creates a simple, interactive calendar for the ServiceNow portal, allowing users to navigate through months and view the current day highlighted. It displays the days of the month in a grid layout.
3+
4+
## Features
5+
Monthly Navigation: Buttons for navigating between months.
6+
Current Day Highlighting: The current date is highlighted in light blue.
7+
Responsive Layout: The calendar adjusts to fit within the widget container.
8+
9+
## Usage
10+
11+
HTML Structure: The main HTML structure displays month navigation buttons and the days in a grid layout.
12+
13+
CSS Styling: CSS styles define the appearance of the calendar, including a shadowed border, day alignment.
14+
15+
JavaScript Controller:
16+
17+
Defines the calendar's navigation functionality.
18+
Calculates and displays the days of the selected month.
19+
Highlights today’s date if it is within the selected month.
20+
21+
## Code Structure
22+
### Controller (api.controller):
23+
Initializes the month and year to display the current month.
24+
Provides functions to navigate to the previous and next month.
25+
Calculates the days of the selected month and highlights the current date.
26+
### CSS:
27+
.calendar-widget: The main container for the calendar.
28+
.calendar-header: Contains the month name and navigation buttons.
29+
30+
## Customization
31+
### Highlight Colors:
32+
Modify .current-day in the CSS to change the color for today’s date.
33+
Month Names and Day Names:
34+
Update the $scope.monthNames and $scope.dayNames arrays to localize or customize the labels.
35+
36+
### Example Usage
37+
In the ServiceNow portal, add this widget to display an interactive calendar. This can be embedded in any dashboard or custom page where date visualization is needed.
38+
39+
## Known Issues
40+
Initial Load: If dates do not display immediately, ensure the ng-init="loadCalendar()" directive is included in the main container.
41+
Date Accuracy: The calendar currently starts with today's date. If dates appear incorrect, check the $scope.loadCalendar() function for accurate month and day calculations.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<div class="calendar-widget" ng-init="loadCalendar()">
2+
<div class="calendar-header">
3+
<button ng-click="prevMonth()">&#9664;</button>
4+
<span>{{ monthNames[currentMonth] }} {{ currentYear }}</span>
5+
<button ng-click="nextMonth()">&#9654;</button>
6+
</div>
7+
8+
<div class="calendar-days">
9+
<div class="day-name" ng-repeat="day in dayNames">{{ day }}</div>
10+
<div
11+
class="day"
12+
ng-repeat="day in days track by $index"
13+
ng-class="{'current-day': isCurrentDay(day), 'weekend': isWeekend($index), 'regular-day': day}">
14+
{{ day }}
15+
</div>
16+
</div>
17+
</div>

0 commit comments

Comments
 (0)