diff --git a/Specialized Areas/CMDB/CMDB CI Deduplication Task Generator/CI Deduplication Tasks Generation with UI Action.js b/Specialized Areas/CMDB/CMDB CI Deduplication Task Generator/CI Deduplication Tasks Generation with UI Action.js new file mode 100644 index 0000000000..440d3acc7c --- /dev/null +++ b/Specialized Areas/CMDB/CMDB CI Deduplication Task Generator/CI Deduplication Tasks Generation with UI Action.js @@ -0,0 +1,50 @@ +//UI Action for Create De-duplicate Tasks +//Onclick showConfirmationDialog + +function showConfirmationDialog() { +var entries = g_list.getChecked(); +var sysIDs = entries.split(','); + +var con1 = confirm('Total number of Selected CIs ' + sysIDs.length + '. Click OK to create De-duplicate task'); + +if (con1) { +alert(sysIDs); +var ga = new GlideAjax('createDuplicateCITask'); +ga.addParam('sysparm_name', 'createDeDupTask'); +ga.addParam('sysparm_entry_ids', entries); +ga.getXML(getDupTasks); +} + +function getDupTasks(response) { + +var answer = response.responseXML.documentElement.getAttribute("answer"); +if (answer == null) { +alert('Failed to create Remediate Duplicate Task. Selected CIs are already part of an open Remediate Duplicate Task'); +} else { +var url1 = 'reconcile_duplicate_task.do?sys_id=' + answer; +var con = confirm('The De-duplicate task is created. Click OK to redirect to De-duplicate task record'); +if (con) { +location.href = url1; +} +} +} +} + +//Script Include + +var createDuplicateCITask = Class.create(); +createDuplicateCITask.prototype = Object.extendsObject(AbstractAjaxProcessor, { +createDeDupTask: function() { +var entries = this.getParameter('sysparm_entry_ids'); + +var dupTaskUtil = new CMDBDuplicateTaskUtils(); +var deDupTaskID = dupTaskUtil.createDuplicateTask(entries); + +return deDupTaskID; + +}, + +type: 'createDuplicateCITask' +}); + + diff --git a/Specialized Areas/CMDB/CMDB CI Deduplication Task Generator/CI Deduplication Tasks Generation.js b/Specialized Areas/CMDB/CMDB CI Deduplication Task Generator/CI Deduplication Tasks Generation.js deleted file mode 100644 index 212f6ae3cc..0000000000 --- a/Specialized Areas/CMDB/CMDB CI Deduplication Task Generator/CI Deduplication Tasks Generation.js +++ /dev/null @@ -1,74 +0,0 @@ -/** - * This script re-checks all duplicate hardware CIs by serial number and creates - * a de-duplication task for any group that does not already have an open task. - * It leverages the global.CMDBDuplicateTaskUtils Script Include. - */ - -(function() { - - var ciTable = 'cmdb_ci_hardware'; //Change to any CI table of your choosing - - var groupsFound = 0; - var tasksCreated = 0; - var groupsSkipped = 0; - - - var taskUtil = new global.CMDBDuplicateTaskUtils(); - - // Find all serial numbers that have duplicates using GlideAggregate. - var ga = new GlideAggregate(ciTable); - ga.addNotNullQuery('serial_number'); - ga.addQuery('serial_number', '!=', ''); - ga.addAggregate('COUNT', 'serial_number'); - ga.groupBy('serial_number'); - ga.addHaving('COUNT', '>', 1); - ga.query(); - - gs.info('Starting check for duplicate CIs by serial number...'); - - while (ga.next()) { - groupsFound++; - var serialNumber = ga.getValue('serial_number'); - var sysIdArray = []; - var taskExists = false; - - // For each duplicate serial number, get all associated CI sys_ids. - var ciGr = new GlideRecord('cmdb_ci_hardware'); - ciGr.addQuery('serial_number', serialNumber); - ciGr.query(); - while (ciGr.next()) { - sysIdArray.push(ciGr.getUniqueValue()); - } - - // Check if ANY of the CIs in the group are already in an open task. - for (var i = 0; i < sysIdArray.length; i++) { - if (!taskUtil.hasNoOpenDuplicateTasks(sysIdArray[i])) { - taskExists = true; - break; // Found an open task, no need to check the others. - } - } - - // If no open task exists for this group, create one. - if (taskExists) { - groupsSkipped++; - gs.info('--> Skipping Serial Number "' + serialNumber + '". It is already part of an open task.'); - } else { - var sysIdString = sysIdArray.join(','); - var newTaskId = taskUtil.createDuplicateTask(sysIdString); - if (newTaskId) { - tasksCreated++; - gs.info('==> Successfully created task ' + newTaskId + ' for Serial Number "' + serialNumber + '".'); - } else { - gs.error('==> FAILED to create task for Serial Number "' + serialNumber + '".'); - } - } - } - - // --- Final Summary --- - gs.info('--- Re-check Complete ---'); - gs.info('Total Duplicate Groups Found: ' + groupsFound); - gs.info('New Remediation Tasks Created: ' + tasksCreated); - gs.info('Groups Skipped (Already in an open task): ' + groupsSkipped); - gs.info('--------------------------'); - -})(); diff --git a/Specialized Areas/CMDB/CMDB CI Deduplication Task Generator/README.md b/Specialized Areas/CMDB/CMDB CI Deduplication Task Generator/README.md index 22457b59ee..894128dd21 100644 --- a/Specialized Areas/CMDB/CMDB CI Deduplication Task Generator/README.md +++ b/Specialized Areas/CMDB/CMDB CI Deduplication Task Generator/README.md @@ -1,16 +1,17 @@ # CI Deduplication Task Generator -This script rechecks the cmdb_ci_hardware table for duplicates by serial number and creates a De-Duplication Task if needed (for records that didn't run through the IRE). +This repository contains a ServiceNow customization that enables users to create De-Duplicate Tasks for selected Configuration Items (CIs) directly from a list view using a UI Action. -### How It Works - -1. Finds all serial numbers that are used on more than one hardware CI. +When executed, the UI Action confirms the number of selected CIs, calls a Script Include via GlideAjax, and creates a Remediate Duplicate Task using CMDBDuplicateTaskUtils -2. For each group of duplicates, it checks if any of the CIs are already part of an open de-duplication task. +### How It Works -3. If no open task exists, it creates a new one linking all CIs in the group. +* Allows users to select multiple CIs and trigger de-duplication in one click +* Automatically creates a De-Duplicate Task record using backend logic +* Displays confirmation dialogs for task creation and redirection +* Prevents duplicate task creation for CIs already linked to an open task +* Redirects to the created De-Duplicate Task record for quick review -4. Logs a summary of actions taken (tasks created, groups skipped). ### Dependencies @@ -18,30 +19,4 @@ This script requires the `global.CMDBDuplicateTaskUtils` Script Include to be ac ### Configuration & Use -This script is meant to be run as a **Scheduled Job** or as a **Background Script**. - -Before you run it, you must set the target table. - -``` -// Change this line in the script! -var ciTable = "cmdb_ci_hardware" - - -``` - -Change `"cmdb_ci_hardware"` to the table you want to run the script against. - -### Example Log Output - -``` -Starting check for duplicate CIs by serial number... -==> Successfully created task RITM0010123 for Serial Number "VMW-50-81-7A-C9-23-44". ---> Skipping Serial Number "SGH814X025". It is already part of an open task. ---- Re-check Complete --- -Total Duplicate Groups Found: 2 -New Remediation Tasks Created: 1 -Groups Skipped (Already in an open task): 1 --------------------------- - - -``` +Creation of UI Action and asking confirmation of selected Records from List View by using GlideAjax diff --git a/Specialized Areas/ITOM/Discovery/PrePost Processing Script of Pattern.README.md b/Specialized Areas/ITOM/Discovery/PrePost Processing Script of Pattern.README.md new file mode 100644 index 0000000000..63dc742286 --- /dev/null +++ b/Specialized Areas/ITOM/Discovery/PrePost Processing Script of Pattern.README.md @@ -0,0 +1,69 @@ +# ServiceNow Discovery Pre Sensor Script: IP Router Association + +This script is a **ServiceNow Discovery Pre Sensor Script** designed to enrich discovery payload data before it reaches the **Identification and Reconciliation Engine (IRE)**. + +It focuses on linking **Interface Cards (`cmdb_ci_interface_card`)** to their parent **IP Routers (`cmdb_ci_ip_router`)** by resolving the router name to its corresponding `sys_id` in the CMDB. + + +## Overview + +When ServiceNow Discovery runs a pattern that identifies multiple components (e.g., routers and their interface cards), some payload items may contain **router names instead of sys_ids**. +The IRE requires sys_ids for accurate relationship building. + +This script ensures that: +- The `u_configuration_item` field on interface cards is replaced with the actual `sys_id` of the corresponding router. +- The router’s `managed_by_group` field is also copied to the interface card record. +- Payload is properly formatted and ready for IRE ingestion. + +## Script Logic + +### Step-by-step Flow +1. **Parse Payload:** + Converts the input payload JSON string into an object for processing. + +2. **Iterate Items:** + Loops through each payload item and filters those with `className = cmdb_ci_interface_card`. + +3. **Router Resolution:** + For each interface card: + - Reads the router name from `u_configuration_item`. + - Searches for a matching router record in `cmdb_ci_ip_router`. + - If found: + - Replaces the router name with its `sys_id`. + - Copies the router’s `managed_by_group` value. + +4. **Return Updated Payload:** + Returns the modified payload back to Discovery for further processing by the IRE. + +--- + +## Example Behavior + +### **Before Script Execution** +```json +{ + "items": [ + { + "className": "cmdb_ci_interface_card", + "values": { + "name": "Router-1/Gigabit0/1", + "u_configuration_item": "Router-1" + } + } + ] +} + +### **After Script Execution** +{ + "items": [ + { + "className": "cmdb_ci_interface_card", + "values": { + "name": "Router-1/Gigabit0/1", + "u_configuration_item": "1b23cdef6f3123006a12ff3b8b3ee490", + "managed_by_group": "287ebd7da9fe198100f92cc8d1d2154e" + } + } + ] +} + diff --git a/Specialized Areas/ITOM/Discovery/PrePost Processing Script.js b/Specialized Areas/ITOM/Discovery/PrePost Processing Script.js new file mode 100644 index 0000000000..0b0c12ea87 --- /dev/null +++ b/Specialized Areas/ITOM/Discovery/PrePost Processing Script.js @@ -0,0 +1,70 @@ +/* + * Pre sensor: You can change payload before it will be proccesed by Identification Engine. + * Use IEJsonUtility in order to add relevant information to the payload + * Input parameters in Pre sensor mode: payload, patternIds + */ + + +var rtrn = {}; + +// parsing the json string to a json object +var payloadObj = JSON.parse(payload); + +// Clearing payload string to save memory +payload = null; + +// Put your business logic here +var handlegrIpRouterdata = function() { + + gs.info('PD: handlegrIpRouter'); + + var ipRouterName = ''; + + var payloadItems = payloadObj.items; + + for (var i = 0; i < payloadItems.length; i++) { + + if (payloadItems[i].className === 'cmdb_ci_interface_card') { //Get Child class data + + var currentItem = payloadItems[i]; + + ipRouterName = currentItem.values.u_configuration_item; + + + + if (ipRouterName && ipRouterName.length) { + + var grIpRouter = new GlideRecord('cmdb_ci_ip_router'); + + if (grIpRouter.get('name', ipRouterName)) { + + + + currentItem.values.u_configuration_item = grIpRouter.sys_id + ''; + currentItem.values.managed_by_group = grIpRouter.managed_by_group + ''; + + } + + + + } + + } + + } + +}; +handlegrIpRouterdata(); +// For node logger, please use: prePostNodeLogger.info\warn\error\debug(prePostLogPrefix + '') + +// You can return a message and a status, on top of the input variables that you MUST return. +// Returning the payload as a Json String is mandatory in case of a pre sensor script, and optional in case of post sensor script. +// If you want to terminate the payload processing due to your business logic - you can set isSuccess to false. +rtrn = { + 'status': { + 'message': 'Enter your message here', + 'isSuccess' :true + }, + 'patternId': patternId, + 'payload': JSON.stringify(payloadObj) +};