Skip to content

Commit b367407

Browse files
Merge duplicate user records automatically (#2002)
* Readme.md * script.js * Update Readme.md * Update script.js
1 parent cbc92bc commit b367407

File tree

2 files changed

+90
-0
lines changed
  • Server-Side Components/Background Scripts/Merge Duplicate User Records Automatically

2 files changed

+90
-0
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Merge Duplicate User Records Automatically
2+
3+
4+
Automatically detects and merges duplicate User records in ServiceNow based on the email address.
5+
6+
Ensures data integrity and prevents duplicate entries.
7+
8+
Reassigns related records (e.g., incidents) to a master record.
9+
10+
Deactivates duplicate users.
11+
12+
In this UseCase
13+
Multiple users exist with the same email address.
14+
15+
The first record found is treated as the master user.
16+
17+
All duplicates are: Reassigned in related records (e.g., tasks, incidents).
18+
19+
Marked inactive.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
(function() {
2+
3+
var userEmailMap = {};
4+
var userCreatedMap = {};
5+
var duplicatesFound = 0;
6+
7+
var userGR = new GlideRecord('sys_user');
8+
userGR.addNotNullQuery('email');
9+
userGR.addQuery('active', true);
10+
userGR.orderBy('email'); // Group by email
11+
userGR.query();
12+
13+
while (userGR.next()) {
14+
var email = userGR.email.toLowerCase();
15+
var createdOn = new GlideDateTime(userGR.sys_created_on).getNumericValue(); // Convert to timestamp
16+
17+
if (!userEmailMap[email]) {
18+
// First user found for this email temporarily mark as master
19+
userEmailMap[email] = userGR.sys_id.toString();
20+
userCreatedMap[email] = createdOn;
21+
} else {
22+
// Another user with same email found
23+
var masterSysId = userEmailMap[email];
24+
var masterCreatedOn = userCreatedMap[email];
25+
26+
var masterIsOlder = createdOn > masterCreatedOn ? true : false;
27+
28+
if (masterIsOlder) {
29+
// If this user was created later, we keep the existing master
30+
// earliest created record will be accepted
31+
mergeDuplicateUser(userGR, masterSysId);
32+
} else {
33+
// If this user was created earlier, this becomes the new master
34+
var oldMasterGR = new GlideRecord('sys_user');
35+
if (oldMasterGR.get(masterSysId)) {
36+
mergeDuplicateUser(oldMasterGR, userGR.sys_id); // merge old master into new master
37+
}
38+
// Update maps
39+
userEmailMap[email] = userGR.sys_id.toString();
40+
userCreatedMap[email] = createdOn;
41+
}
42+
43+
duplicatesFound++;
44+
}
45+
}
46+
47+
gs.info("Total duplicates merged: " + duplicatesFound);
48+
49+
50+
51+
function mergeDuplicateUser(duplicateGR, masterSysId) {
52+
// Reassign related incidents
53+
var incGR = new GlideRecord('incident');
54+
incGR.addQuery('caller_id', duplicateGR.sys_id);
55+
incGR.query();
56+
var count = 0;
57+
while (incGR.next()) {
58+
incGR.caller_id = masterSysId;
59+
incGR.update();
60+
count++;
61+
}
62+
63+
// Deactivate user
64+
duplicateGR.active = false;
65+
duplicateGR.u_merged_to = masterSysId; // optional custom field
66+
duplicateGR.update();
67+
68+
gs.info("Merged duplicate user '" + duplicateGR.name + "' → master: " + masterSysId + ". Reassigned " + count + " incidents.");
69+
}
70+
71+
})();

0 commit comments

Comments
 (0)