Skip to content

Commit 351f987

Browse files
authored
Merge branch 'ServiceNowDevProgram:main' into feature/bookmarklet/show-user-info/bookmarklet
2 parents 57a2d82 + a6ec3f5 commit 351f987

File tree

22 files changed

+499
-109
lines changed

22 files changed

+499
-109
lines changed

CONTRIBUTING.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,25 @@ If you plan to submit another pull request while your original is still pending,
3131
- **Descriptive Pull Request Titles**: Your pull request must have explicit and descriptive titles that accurately represent the changes made.
3232
- **Scope Adherence**: Changes that fall outside the described scope will result in the entire pull request being rejected.
3333
- **Quality Over Quantity**: Low-effort or spam pull requests will be marked accordingly.
34-
- **Expanded Snippets**: Code snippets reused from the [ServiceNow Documentation](https://docs.servicenow.com/) or [API References](https://developer.servicenow.com/dev.do#!/reference/) are acceptable only if they are expanded in a meaningful way (e.g., with additional context, documentation, or variations). Remember: *QUANTITY IS FUN, QUALITY IS KEY.*
34+
- **Expanded Snippets**: Code snippets reused from the [ServiceNow Documentation](https://docs.servicenow.com/) or [API References](https://developer.servicenow.com/dev.do#!/reference/) are acceptable only if they are expanded in a meaningful way (e.g., with additional context, documentation, or variations). Remember: *"QUANTITY IS FUN, QUALITY IS KEY."*
3535
- **Relevance**: Code should be relevant to ServiceNow Developers.
3636
- **ES2021 Compatibility**: While ES2021 is allowed, we encourage you to disclose if your code is using ES2021 features, as not everyone may be working with ES2021-enabled applications.
3737

38+
## Core Documentation File Changes
39+
40+
**IMPORTANT**: For changes to core documentation files (README.md, CONTRIBUTING.md, LICENSE, etc.), contributors must:
41+
42+
1. **Submit an Issue First**: Before making any changes to core documentation files, create an issue describing:
43+
- What you intend to edit
44+
- Why the change is needed
45+
- Your proposed approach
46+
47+
2. **Get Assignment**: Wait to be assigned to the issue by a maintainer before submitting a PR.
48+
49+
3. **Reference the Issue**: Include the issue number in your PR title and description.
50+
51+
This process helps prevent merge conflicts when multiple contributors want to update the same documentation files and ensures all changes align with the project's direction.
52+
3853
## Repository Structure
3954

4055
**IMPORTANT**: The repository has been reorganized into major categories. All new contributions MUST follow this structure for PR approval.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
## Overview
2+
This script retrieves incidents that were opened more than X days ago using **GlideDateTime** and **GlideRecord**.
3+
Useful for reporting, escalations, notifications, and cleanup tasks.
4+
5+
## Table and Field
6+
- **Table:** `incident`
7+
- **Field:** `opened_at`
8+
9+
## Parameters
10+
- **X (number of days):** Defines the threshold for old incidents (e.g., 30 days).
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
(function() {
2+
var days = 30; // Change this to your required number of days
3+
4+
// Calculate the date X days ago
5+
var cutoffDate = new GlideDateTime();
6+
cutoffDate.addDaysUTC(-days);
7+
8+
// Query incidents opened before the cutoff date
9+
var gr = new GlideRecord('incident');
10+
gr.addQuery('opened_at', '<', cutoffDate);
11+
gr.query();
12+
13+
gs.info('Incidents opened more than ' + days + ' days ago:');
14+
15+
while (gr.next()) {
16+
gs.info('Incident Number: ' + gr.number + ', Opened At: ' + gr.opened_at.getDisplayValue());
17+
}
18+
})();
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Querying JSON with JSONPath to extract values
2+
3+
GlideJsonPath is a class which can be used to use JSONPath in ServiceNow. It can be useful when working with JSON Payloads, especially highly nested or in general complex structures.
4+
5+
References:
6+
- [RFC 9535: JSONPath: Query Expressions for JSON](https://datatracker.ietf.org/doc/rfc9535/)
7+
- [Play with JSONPath outside of ServiceNow](https://jsonpath.com/)
8+
- [Good Examples to start with](https://restfulapi.net/json-jsonpath/)
9+
- [ServiceNow API Documentation](https://www.servicenow.com/docs/bundle/zurich-api-reference/page/app-store/dev_portal/API_reference/GlideJsonPath/concept/GlideJsonPathAPI.html)
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Run in background script
2+
var json = {
3+
"store":
4+
{
5+
"book": [
6+
{
7+
"category": "reference",
8+
"author": "Nigel Rees",
9+
"title": "Sayings of the Century",
10+
"price": 8.95
11+
},
12+
{
13+
"category": "fiction",
14+
"author": "Evelyn Waugh",
15+
"title": "Sword of Honour",
16+
"price": 12.99
17+
},
18+
{
19+
"category": "fiction",
20+
"author": "Herman Melville",
21+
"title": "Moby Dick",
22+
"isbn": "0-553-21311-3",
23+
"price": 8.99
24+
},
25+
{
26+
"category": "fiction",
27+
"author": "J. R. R. Tolkien",
28+
"title": "The Lord of the Rings",
29+
"isbn": "0-395-19395-8",
30+
"price": 22.99
31+
}
32+
],
33+
"bicycle": {
34+
"color": "red",
35+
"price": 19.95
36+
}
37+
}
38+
};
39+
40+
var path1 = 'store.book[0].author'; // The author of the first book
41+
var path2 = 'store.book[*].author'; // All authors
42+
var path3 = 'store..price'; // All prices
43+
var path4 = '$..book[?(@.price<10)]'; // All books cheaper than 10
44+
var path5 = '$..book[?(@.isbn)]'; // All books with an ISBN number
45+
var path6 = '$..*'; // All members of JSON structure
46+
47+
var gjp = new GlideJsonPath(JSON.stringify(json));
48+
gs.info('Path: ' + path1 + ' Result: ' + gjp.read(path1));
49+
gs.info('Path: ' + path2 + ' Result: ' + gjp.read(path2));
50+
gs.info('Path: ' + path3 + ' Result: ' + gjp.read(path3));
51+
gs.info('Path: ' + path4 + ' Result: ' + gjp.read(path4));
52+
gs.info('Path: ' + path5 + ' Result: ' + gjp.read(path5));
53+
gs.info('Path: ' + path6 + ' Result: ' + gjp.read(path6));
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
The script retrieves the top-level manager for the currently logged-in user by traversing the manager hierarchy in the sys_user table.
2+
3+
It starts from the current user and moves up through each manager until it reaches a user who does not have a manager.
4+
5+
The script starts with the current user (e.g., Employee).
6+
7+
It checks if the user has a manager.
8+
9+
If yes, it moves up the hierarchy to the manager.
10+
11+
It repeats this process until it reaches a user who does not have a manager.
12+
13+
That user is considered the Top-Level Manager.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
var currentUser = gs.getUser(); // Current logged-in user
2+
var userGR = new GlideRecord('sys_user');
3+
var maxLevels = 7;
4+
var currentLevel = 0;
5+
6+
if (userGR.get(currentUser.getID())) {
7+
8+
// Loop until we find a user who has no manager or reach max level
9+
while (userGR.manager && currentLevel < maxLevels) {
10+
var managerID = userGR.getValue('manager');
11+
var managerGR = new GlideRecord('sys_user');
12+
13+
if (managerGR.get(managerID)) {
14+
userGR = managerGR; // Move up one level
15+
currentLevel++;
16+
// gs.print(" Level " + currentLevel + " Manager: " + userGR.getDisplayValue('name'));
17+
} else {
18+
break; // Manager record not found
19+
}
20+
}
21+
22+
gs.print("Top-level (or Level " + currentLevel + ") Manager: " + userGR.getDisplayValue('name'));
23+
} else {
24+
gs.print("User not found.");
25+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
This script tracks the time it took to assign a task (like an Incident, Change, etc.) by calculating the difference
2+
between when the record was created and when it was assigned (assigned_to was set).
3+
It checks if the assigned_to field has changed and is not empty.
4+
If it's the first time the record is being assigned (u_assignment_time is empty), it captures the current time.
5+
It then calculates the time difference between when the record was created and when it was assigned.
6+
This time difference (in minutes) is stored in a custom field u_time_to_assign.
7+
The goal is to track how long it took for the record to be assigned after creation
8+
9+
10+
## While this is possible to do via Metrics in ServiceNow (https://www.servicenow.com/docs/bundle/xanadu-platform-administration/page/use/reporting/concept/c_SampleFieldValueDurationScript.html),
11+
## the script is being provided to potentially solve some edge cases.
12+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
(function executeRule(current, previous /*null when async*/) {
2+
3+
// Only proceed if assigned_to changed AND is not empty/null
4+
if (current.assigned_to.changes() && !gs.nil(current.assigned_to)) {
5+
6+
gs.info("Assigned_to changed and assigned_to is: " + current.assigned_to);
7+
8+
// Only set u_assigned_time if empty
9+
if (!current.u_assigned_time) {
10+
11+
var assignedTime = new GlideDateTime();
12+
current.u_assigned_time = assignedTime;
13+
14+
var createdTime = new GlideDateTime(current.sys_created_on);
15+
16+
var diffMillis = assignedTime.getNumericValue() - createdTime.getNumericValue();
17+
var diffMinutes = diffMillis / (1000 * 60);
18+
19+
gs.info("Time difference in minutes: " + diffMinutes);
20+
21+
// Assuming u_time_to_assign is a string field
22+
current.u_time_to_assign = diffMinutes.toFixed(2) + " minutes";
23+
24+
gs.info("Set u_time_to_assign to: " + current.u_time_to_assign);
25+
} else {
26+
gs.info("u_assigned_time already set: " + current.u_assigned_time);
27+
}
28+
} else {
29+
gs.info("Assigned_to not changed or is empty.");
30+
}
31+
32+
})(current, previous);
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
UseCase -
2+
3+
4+
5+
When a new Incident is created, the system should automatically assign it to the next available member of the assignment group — in a Round Robin fashion (i.e., distributing incidents evenly among all group members).
6+
7+
It will also work for New addition of new user. and distribute the incident equally to all the users.
8+

0 commit comments

Comments
 (0)