diff --git a/Server-Side Components/Script Includes/Prevent circular dependencies in task relationships./README.md b/Server-Side Components/Script Includes/Prevent circular dependencies in task relationships./README.md new file mode 100644 index 0000000000..10993d90f3 --- /dev/null +++ b/Server-Side Components/Script Includes/Prevent circular dependencies in task relationships./README.md @@ -0,0 +1,29 @@ +# Detect Circular Reference in Task Dependencies + + + +## Overview + +This Script Include helps identify **circular dependencies** in task relationships within ServiceNow. Circular references can cause workflow issues, reporting errors, and logic failures in project management or task tracking modules. + +## What It Does + +- Traverses task dependencies recursively. +- Detects if a task is indirectly dependent on itself. +- Returns `true` if a circular reference is found, `false` otherwise. + +## Use Case + +Imagine Task A depends on Task B, and Task B depends on Task A. This creates a circular loop that can break automation or cause infinite recursion. This script helps prevent such configurations. + +Tables and modules it would be usefull +It is used for Table: planned_task_rel_planned_task +This table is used to define task dependencies between project tasks in ServiceNow's Strategic Portfolio Management (SPM) or Project Portfolio Management (PPM) modules. It stores relationships such as: + +Predecessor Task +Successor Task +Dependency Type (e.g., Finish-to-Start) + + + + diff --git a/Server-Side Components/Script Includes/Prevent circular dependencies in task relationships./code.js b/Server-Side Components/Script Includes/Prevent circular dependencies in task relationships./code.js new file mode 100644 index 0000000000..960cef1ddb --- /dev/null +++ b/Server-Side Components/Script Includes/Prevent circular dependencies in task relationships./code.js @@ -0,0 +1,26 @@ +var DependencyChecker = Class.create(); +DependencyChecker.prototype = { + initialize: function() {}, + + hasCircularReference: function(taskId) { + var visited = {}; + return this._check(taskId, visited); + }, + + _check: function(taskId, visited) { + if (visited[taskId]) return true; + visited[taskId] = true; + + var gr = new GlideRecord('task_dependency'); + gr.addQuery('dependent_task', taskId); + gr.query(); + + while (gr.next()) { + if (this._check(gr.task.toString(), visited)) return true; + } + + return false; + }, + + type: 'DependencyChecker' +};