Skip to content

Commit 69bdfc6

Browse files
authored
Merge branch 'ServiceNowDevProgram:main' into main
2 parents 101697b + d84dcae commit 69bdfc6

File tree

19 files changed

+551
-0
lines changed

19 files changed

+551
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Show previous request ON requested for selection
2+
3+
This feature enhances the Service Catalog experience by displaying previous requests for the selected Requested For user. When a user selects the Requested For variable in a catalog item form, a confirmation message appears showing the last few requests created for that user.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
function onChange(control, oldValue, newValue, isLoading) {
2+
if (isLoading || newValue == '') return;
3+
4+
var ga = new GlideAjax('PreviousRequestsUtils');
5+
ga.addParam('sysparm_name', 'getPreviousRequests');
6+
ga.addParam('sysparm_requested_for', newValue);
7+
ga.getXMLAnswer(function(response) {
8+
var requests = JSON.parse(response);
9+
if (requests.length === 0) {
10+
alert('No previous requests found for this user.');
11+
} else {
12+
var message = 'Previous Requests:\n\n';
13+
requests.forEach(function(req) {
14+
message += 'Number: ' + req.number + ' | Item: ' + req.item + ' | Date: ' + req.date + '\n';
15+
});
16+
if (confirm(message + '\nDo you want to continue?')) {
17+
// User clicked OK
18+
} else {
19+
// User clicked Cancel
20+
g_form.setValue('requested_for', oldValue);
21+
}
22+
}
23+
});
24+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
var PreviousRequestsUtils = Class.create();
2+
PreviousRequestsUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {
3+
getPreviousRequests: function() {
4+
var requestedFor = this.getParameter('sysparm_requested_for');
5+
var result = [];
6+
var gr = new GlideRecord('sc_req_item');
7+
gr.addQuery('requested_for', requestedFor);
8+
gr.orderByDesc('sys_created_on');
9+
gr.setLimit(5); // Show last 5 requests
10+
gr.query();
11+
while (gr.next()) {
12+
result.push({
13+
number: gr.number.toString(),
14+
item: gr.cat_item.getDisplayValue(),
15+
date: gr.sys_created_on.getDisplayValue()
16+
});
17+
}
18+
return JSON.stringify(result);
19+
}
20+
});
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
README — Client Script: Validate Interaction Resolution
2+
📌 Purpose
3+
This Client Script ensures proper validation when resolving an Interaction record in ServiceNow.
4+
It prevents a user from marking an Interaction as Closed Complete without proper justification.
5+
6+
🎯 What It Does
7+
8+
When a user attempts to submit the form:
9+
✔ Allows submission only if:
10+
Interaction Type is "walkup"
11+
And Related Task Boolean is true
12+
13+
OR
14+
15+
✔ If work notes are provided for First Contact Resolution (FCR)
16+
❌ Prevents submission if:
17+
State = Closed Complete
18+
Work Notes are empty
19+
And no related task condition is met
20+
21+
🧠 Validations Performed
22+
Field Condition Action
23+
state closed_complete Trigger validation
24+
type walkup AND u_boolean_no_related_task = true Submission allowed ✅
25+
work_notes Must not be empty Show error & stop submission ❌
26+
🔔 User Feedback
27+
28+
If work notes are missing:
29+
Displays inline field message
30+
31+
Shows popup alert:
32+
"Provide Worknotes for FCR Interaction"
33+
34+
📍 Script Location
35+
36+
Client Script → Type: onSubmit()
37+
Applicable to Interaction table (interaction)
38+
39+
📌 Script Code
40+
//Client Script to validate an Interaction record is resolved with out any related record created.
41+
function onSubmit() {
42+
var relatedTask = g_form.getValue('u_boolean_no_related_task');
43+
var state = g_form.getValue('state');
44+
var type = g_form.getValue('type');
45+
var workNotes = g_form.getValue('work_notes'); // Get the value of work notes
46+
47+
// Clear previous field messages
48+
g_form.clearMessages();
49+
50+
// Check if state is changing to 'Closed Complete'
51+
if (state == 'closed_complete') {
52+
// Check additional conditions
53+
if (type == 'walkup' && relatedTask == 'true') {
54+
return true; // Allow form submission
55+
} else if (!workNotes) { // Check if work notes is empty
56+
g_form.showFieldMsg('work_notes', 'Provide Worknotes for FCR Interaction', 'error');
57+
alert('Provide Worknotes for FCR Interaction');
58+
return false; // Prevent form submission
59+
}
60+
}
61+
return true; // Allow form submission for other states
62+
}
63+
64+
✅ Benefits
65+
66+
Maintains consistent resolution standards
67+
Ensures justification/documentation for FCR interactions
68+
Reduces incorrect closure of requests without related actions
69+
70+
71+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//Client Script to validate an Interaction record is resolved with out any related record created.
2+
function onSubmit() {
3+
var relatedTask = g_form.getValue('u_boolean_no_related_task');
4+
var state = g_form.getValue('state');
5+
var type = g_form.getValue('type');
6+
var workNotes = g_form.getValue('work_notes'); // Get the value of work notes
7+
8+
// Clear previous field messages
9+
g_form.clearMessages();
10+
11+
// Check if state is changing to 'Closed Complete'
12+
if (state == 'closed_complete') {
13+
// Check additional conditions
14+
if (type == 'walkup' && relatedTask == 'true') {
15+
return true; // Allow form submission
16+
} else if (!workNotes) { // Check if work notes is empty
17+
g_form.showFieldMsg('work_notes', 'Provide Worknotes for FCR Interaction', 'error');
18+
alert('Provide Worknotes for FCR Interaction');
19+
return false; // Prevent form submission
20+
}
21+
}
22+
return true; // Allow form submission for other states
23+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# 🧩 ServiceNow Asset QR Code Generator (UI Action)
2+
3+
This repository contains a **ServiceNow UI Action** script that generates and displays a QR Code for an Asset record from list view.
4+
When the user selects a record and clicks the UI Action, a modal window pops up showing a dynamically generated QR Code that links to asset details.
5+
6+
7+
A supporting **Script Include** (server-side) is required in your ServiceNow instance but **is not included** in this repository.
8+
At the bottom of file , a sample Script Include Code is given , check for the reference.
9+
10+
---
11+
12+
## 🚀 Features
13+
14+
- Generates a QR Code for the selected Asset record.
15+
- Displays the QR Code inside a ServiceNow modal (`GlideModal`).
16+
- Uses **QrIckit API** for quick and free QR code generation.
17+
- Clean, modular client-side code that integrates seamlessly with UI Actions.
18+
- Includes a `qr-code-image` file showing example QR Code generated.
19+
20+
---
21+
22+
## 🧠 How It Works
23+
24+
1. The `onClickQR()` function is triggered when the user clicks a UI Action button.
25+
2. It calls `generateQRCodeForAsset(sys_id)` and passes the record’s `sys_id`.
26+
3. A `GlideAjax` request fetches asset data from a **Script Include** on the server.
27+
4. That data is encoded and sent to the **QrIckit** API to generate a QR Code image.
28+
5. A ServiceNow modal (`GlideModal`) displays the generated QR Code to the user.
29+
30+
---
31+
32+
33+
**Note :**
34+
1) As the UI action calls a Script Include , in this folder no script include is present
35+
2) You can modify script include part as required(i.e Which fields are to be shown when QR is scanned)
36+
3) A sample Client Callable Script-Include is given here.
37+
38+
``` Script Include Code
39+
var GenerateAssetQR = Class.create();
40+
GenerateAssetQR.prototype = Object.extendsObject(AbstractAjaxProcessor, {
41+
getAssetQRData: function() {
42+
var sys_id = this.getParameter('sysparm_sys_id');
43+
var asset = new GlideRecord('alm_asset');
44+
if (asset.get(sys_id)) {
45+
return 'Asset: ' + asset.name + ', Serial: ' + asset.serial_number;
46+
}
47+
return 'Invalid asset record.';
48+
}
49+
});
50+
```
87.7 KB
Loading
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
function onClickQR() {
2+
generateQRCodeForAsset(g_sysId);//get the sysid of selected record
3+
}
4+
5+
function generateQRCodeForAsset(sys_id) {
6+
var ga = new GlideAjax('GenerateAssetQR');//Script Include which stores data to be presented when QR-Code is Scanned
7+
ga.addParam('sysparm_name', 'getAssetQRData');
8+
ga.addParam('sysparm_sys_id', sys_id);
9+
10+
ga.getXMLAnswer(function(response) {
11+
var qrData = response;
12+
var qrURL = 'https://qrickit.com/api/qr.php?d=' + encodeURIComponent(qrData) + '&addtext=Get Asset Data';
13+
//QrIckit is a tool using which Customized QR-Codes can be generated
14+
var modalHTML = `
15+
<div style="text-align:center">
16+
<img id="qrCodeImage" src="${qrURL}" alt="QR Code" style="margin-bottom:10px;" />
17+
<p>Scan to view asset details</p>
18+
</div>
19+
`;
20+
21+
var gModal = new GlideModal("QR Code");
22+
gModal.setTitle('Asset QR Code');
23+
gModal.setWidth(500);
24+
gModal.renderWithContent(modalHTML);
25+
});
26+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
**Calculate the due date based on the Priority**
2+
3+
Script Type: UI Action, Table: incident, Form button: True, Show update: True, Condition: (current.due_date == '' && current.priority != '5'), OnClick: functionName()
4+
5+
Script Type: Script Include, Glide AJAX enabled: False
6+
7+
Schedule- Name: Holidays, Time Zone: GMT
8+
9+
Schedule Entry - Name: New Year's Day, Type: Exclude, Show as: Busy, When: 31-12-2024, To: 01-01-2025
10+
Schedule Entry - Name: Christmas Day, Type: Exclude, Show as: Busy, When: 24-12-2025, To: 25-12-2025
11+
Schedule Entry - Name: Thanksgiving Day, Type: Exclude, Show as: Busy, When: 26-11-2025, To: 27-11-2025
12+
Schedule Entry - Name: Diwali, Type: Exclude, Show as: Busy, When: 19-10-2025, To: 20-10-2025
13+
14+
**Goal:** To Calculate Due-Date based on Priority with some conditions.
15+
16+
**Walk through of code:** So in this use case the UI Action is been used and then Script Include for server calculate is used.So the main to calculate the due-date by the user trigger.
17+
18+
UI Action- So this button will check the priority and check the due date field is empty or not if not then will fetch the value of "Priority" and "Created date" and pass the data to the Script Include for calculation once it gets the response will populate the value to the due_date field in the incident table and then update it.
19+
20+
Script Include- The role of this is to get the "Priority" and "Created date" based on prioriy this will calculate the time and date by using th GlidDateTime API and the will do some additional changes based on each priorit which is mentioned below and then return the response back to the UI Action,
21+
22+
Schedule & Schedule Entry- It is used for the P3 and P4 Priority which is mentioned below for the use case.To exclude the Holidays.
23+
24+
These are the use case which the above functionality works,
25+
26+
**1-> P1** - add 4hrs to the Created date
27+
**2-> P2 **- add 4hrs to the Created date but if it's exceed the working hrs of of 5 PM the add to the next day or if the is before the working hours of 8 AM set 5 PM to the same Created date.
28+
**3-> P3 or P4** - Kind of low priority so add the due date to the next day but it should exclude the holidays and the weekend's and the populate the next business working day.
29+
**4-> P5 **- User manually will populate the due date based on the process.
30+
31+
The UI Action on the Incident Form
32+
<img width="815" height="382" alt="Button" src="https://github.com/user-attachments/assets/68876b10-e6e0-43b9-9ecf-f6eb95b7ef87" />
33+
34+
UI Action which will call the Script Include
35+
<img width="556" height="425" alt="UI Action" src="https://github.com/user-attachments/assets/2715232a-000b-4520-8b1a-f5bf72afdaa9" />
36+
37+
Script Include
38+
<img width="817" height="416" alt="SI" src="https://github.com/user-attachments/assets/5ddb332c-d23f-4746-b014-1a71acb59186" />
39+
40+
Schedules and Schedule Entry
41+
<img width="839" height="431" alt="Schedules" src="https://github.com/user-attachments/assets/f96ea4dc-e2d4-4d8f-87b7-67df66a2d8af" />
42+
<img width="917" height="370" alt="Schedule Entry" src="https://github.com/user-attachments/assets/c4fec5ce-8ee4-46cc-8673-2d22a27290f1" />
43+
44+
Output
45+
<img width="828" height="356" alt="Priority 1" src="https://github.com/user-attachments/assets/7f4049b6-294e-4064-bab1-e2d1ab938bfd" />
46+
<img width="817" height="416" alt="Priority 2" src="https://github.com/user-attachments/assets/37f0cffd-f05c-4f4d-bf35-36090f02ee3b" />
47+
<img width="815" height="334" alt="Priority 4" src="https://github.com/user-attachments/assets/0ab4ab27-4726-4ea7-b99e-7e35f9b0f4c7" />
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
3+
Input
4+
1. Created Date
5+
2. Priority
6+
7+
Output
8+
1. Due Date
9+
10+
Based on Priority equivalent due dates
11+
12+
P1 - add 4hrs to the Created date
13+
P2 - add 4hrs to the Created date but if it's exceed the working hrs of of 5 PM the add to the next day or if the is before the working hours of 8 AM set 5 PM to the same Created date.
14+
P3 or P4 - Kind of low priority so add the due date to the next day but it should exclude the holidays and the weekend's and the populate the next business working day.
15+
16+
*/
17+
18+
19+
// This SI findDueDate() function will help to calculate the duration based on the each priority.
20+
21+
var CalculateDueDates = Class.create();
22+
CalculateDueDates.prototype = {
23+
initialize: function() {},
24+
25+
findDueDate: function(priority, created) {
26+
var dueDateVal;
27+
28+
29+
// For the Priority 1 and adding 4 hours in reagrd less of 8-5 working hours and then holidays
30+
if (priority == 1) {
31+
var now = new GlideDateTime(created);
32+
now.addSeconds(60 * 60 * 4); // Add 4 hours
33+
dueDateVal = now;
34+
return dueDateVal;
35+
36+
}
37+
38+
// For the Priority 2 and adding the 4 hours if exceed the workin hours then add the next day before 5'o Clock
39+
else if (priority == 2) {
40+
var dueDate = new GlideDateTime(created);
41+
dueDate.addSeconds(60 * 60 * 4); // Add 4 hours
42+
dueDate = dueDate+'';
43+
var hours = Number((dueDate + '').slice(11, 13));
44+
45+
if (hours >= 0 && hours < 12) {
46+
gs.addInfoMessage('if Inside 8-5/7');
47+
dueDateVal = dueDate.slice(0, 10) + " 17:00:00";
48+
return dueDateVal;
49+
50+
} else if (hours >= 17 && hours <= 23) {
51+
var nextDate = new GlideDateTime(created);
52+
nextDate.addDaysUTC(1);
53+
var newDue = new GlideDateTime(nextDate.getDate().getValue() + " 17:00:00");
54+
dueDateVal = newDue;
55+
return dueDateVal;
56+
} else {
57+
dueDateVal = dueDate;
58+
return dueDateVal;
59+
}
60+
61+
}
62+
63+
// For the Priority 3 or 4 add the next day and then if the due date is holiday or weekend populate the next working day in a respective field
64+
else if (priority == 3 || priority == 4) {
65+
var schedule = new GlideSchedule();
66+
// cmn_schedule for the Holidays
67+
var scheduleId = 'bd6d74b2c3fc72104f7371edd40131b7';
68+
schedule.load(scheduleId);
69+
70+
var nextDay = new GlideDateTime(created);
71+
nextDay.addDaysUTC(1);
72+
73+
74+
//Checking for weekends
75+
var dayOfWeek = nextDay.getDayOfWeekUTC();
76+
77+
var isWeekend = (dayOfWeek == 6 || dayOfWeek == 7);
78+
79+
80+
// Loop until next working day (weekdays excluding holidays)
81+
while (schedule.isInSchedule(nextDay) || isWeekend) {
82+
nextDay.addDaysUTC(1);
83+
dayOfWeek = nextDay.getDayOfWeekUTC();
84+
isWeekend = (dayOfWeek == 6 || dayOfWeek == 7);
85+
}
86+
87+
// Set to 12:00 PM on that valid day
88+
var validDate = new GlideDateTime(nextDay.getDate().getValue() + " 17:00:00");
89+
return validDate;
90+
}
91+
},
92+
93+
type: 'CalculateDueDates'
94+
};

0 commit comments

Comments
 (0)