Graphical workflow Archives - ServiceNow Guru https://servicenowguru.com/tag/graphical-workflow/ ServiceNow Consulting Scripting Administration Development Tue, 28 May 2024 20:50:57 +0000 en-US hourly 1 https://wordpress.org/?v=6.8.2 https://servicenowguru.com/wp-content/uploads/2024/05/cropped-SNGuru-Icon-32x32.png Graphical workflow Archives - ServiceNow Guru https://servicenowguru.com/tag/graphical-workflow/ 32 32 Prevent Redundant Approval Requests in ServiceNow https://servicenowguru.com/business-rules-scripting/prevent-redundant-approval-requests-servicenow/ https://servicenowguru.com/business-rules-scripting/prevent-redundant-approval-requests-servicenow/#comments Tue, 17 Dec 2013 13:18:45 +0000 https://servicenowguru.wpengine.com/?p=5084 If you’re like many of the customers I’ve worked with, you may have dealt with the frustration of having excess or redundant approval requests come to you from ServiceNow. This happens very often simply because the same user may be responsible for various different tasks in the system. For example, on a change request, I

The post Prevent Redundant Approval Requests in ServiceNow appeared first on ServiceNow Guru.

]]>
If you’re like many of the customers I’ve worked with, you may have dealt with the frustration of having excess or redundant approval requests come to you from ServiceNow. This happens very often simply because the same user may be responsible for various different tasks in the system. For example, on a change request, I may be asked to approve as the ‘Requested by’ person’s manager, then again because I own one of the affected CIs, and then again because I’m a member of the Change Advisory Board! While this behavior may be desirable in certain situations, most of the time it’s completely redundant and annoying to end users. If I’ve already indicated my approval on a change as a manager, why should I be asked to approve again later? I’ve come up with what I think is a pretty effective solution to this problem that I’ll share here in this article.

Redundant Approvals

The Solution…

At least in my mind, in order for this solution to be successful, it needs to meet a few criteria…

  1. First and foremost, the user should not be notified of an approval request if they’ve already approved a record.
  2. We need to maintain the history of the approval record for audit purposes and accurately reflect what happened to the redundant approval requests. This means that deleting or aborting record insertion is out of the question!
  3. We cannot negatively impact the approval workflow by interrupting the normal approval process.

The first two criteria need to be met at the same time. Preventing the approval request could be done in a couple of different ways. One way would be to somehow manipulate the workflow activity to check if the user has previously approved. The drawback to this approach is that it requires hacking the workflow approval activities…which would be a significant upgrade risk, or adding custom code to every single approval activity in every single workflow…which would be a maintenance nightmare.

That leaves us with intercepting the creation/update of the approval records in a business rule. Using a ‘before’ insert/update business rule we can evaluate every ‘requested’ approval record, run a script to determine if the approval is for a user that has already approved this item, and then adjust the approval record by setting the approval state to ‘No Longer Required’…all before we trigger any update or notification to the approving user. We can also add some approval comments so that we can accurately reflect why the approval isn’t required anymore. Adding the following business rule to the ‘Approval [sysapproval_approver]’ table accomplishes that for us.

‘Duplicate Approval Requests Not Required’ Business Rule
Name: Duplicate Approval Requests Not Required
Table: Approval [sysapproval_approver] When: Before
Insert/Update: true
Condition: current.state.changesTo(‘requested’)
Script:

//Check to see if user has previously approved
approveDuplicateApproval();function approveDuplicateApproval(){
//Must have link to record being approved
if(current.document_id || current.sysapproval){
//Query for approval records for this user/record
var app = new GlideRecord('sysapproval_approver');
//Handle empty document_id and sysapproval fields
if(!current.document_id.nil()){
app.addQuery('document_id', current.document_id);
}
else if(!current.sysapproval.nil()){
app.addQuery('sysapproval', current.sysapproval);
}
app.addQuery('approver', current.approver);
app.addQuery('state', 'approved');
//Optionally restrict to current workflow
//app.addQuery('wf_activity.workflow_version', current.wf_activity.workflow_version);
app.query();
if(app.next()){
//If previous approval is found set this approval to 'approved'
current.state = 'not_required';
current.comments = "Approval marked by system as 'Not Longer Required' due to a previous approval on the same record by the same user.";
}
}
}

While the above script works great in manipulating the approval records on its own, it fails in the third criteria mentioned above…it can negatively impact the workflow in certain situations. This is because the workflow processing that happens after an approval status is changed isn’t seeing the true value of the approval request to process the workflow approval activity correctly. In my testing this couldn’t be done in a ‘before’ or ‘after’ business rule due to the timing of the updates. What is needed is to run the workflow checks one more time, and ensure that it happens after all of the above manipulation happens. The best way I could find to do this is through a separate ‘async’ business rule. The only downside to this async business rule is that it may not process immediately depending on the load on your system. Generally it should process within a few seconds though so for all practical intents and purposes it’s a non-issue.

‘Run parent workflows (Not Required)’ Business Rule
Name: Run parent workflows (Not Required)
Table: Approval [sysapproval_approver] When: async
Priority: 200 (This is important to be set to something greater than 100 to ensure that this runs ASAP!)
Insert/Update: true
Condition: current.state == ‘not_required’
Script:

// Run any workflows for our parent so they can check the approval states
runWorkflow_userApprove();function runWorkflow_userApprove() {
var id = current.sysapproval.nil() ? current.document_id : current.getValue('sysapproval');
var table = current.source_table.nil() ? 'task' : current.source_table;
if (id != null && table != null ) {
var gr = new GlideRecord(table);
if (gr.get(id)) {
new Workflow().runFlows(gr, 'update');
}
}
}

With the above solution in place, you should have created a very effective way to prevent the issue of redundant approval requests for the same user against the same record in ServiceNow.

The post Prevent Redundant Approval Requests in ServiceNow appeared first on ServiceNow Guru.

]]>
https://servicenowguru.com/business-rules-scripting/prevent-redundant-approval-requests-servicenow/feed/ 29
Percentage or Majority-based Workflow Approvals https://servicenowguru.com/graphical-workflow/approval-percentage/ https://servicenowguru.com/graphical-workflow/approval-percentage/#comments Thu, 31 Jan 2013 19:12:58 +0000 https://servicenowguru.wpengine.com/?p=4697 One very common service request or change request approval requirement is to ask for a percentage or majority-based approval. This is something that ServiceNow workflow can do, but it requires a bit of scripting. In the following article, I’ll show you how you can set up some simple scripts in your graphical workflow ‘Approval’ activities

The post Percentage or Majority-based Workflow Approvals appeared first on ServiceNow Guru.

]]>
One very common service request or change request approval requirement is to ask for a percentage or majority-based approval. This is something that ServiceNow workflow can do, but it requires a bit of scripting. In the following article, I’ll show you how you can set up some simple scripts in your graphical workflow ‘Approval’ activities to handle these scenarios for any percentage you choose.

ServiceNow Majority Approval

Looking for other approval script examples? Check out this article about change management approval scripts!

 

The following example scripts are designed to be placed directly in the ‘Approval Script’ field on a workflow ‘Approval’ activity as shown in the screenshot above. The ‘Approval Script’ field is only visible if you select ‘Condition based on script’ from the ‘Wait for’ field. Once you paste the script in, just adjust the ‘approvePercent’ variable for the specific approval percentage needed.

Percentage-based approval with an ‘Approval – User’ activity

This first example assumes you’ve got a group of users grouped into a single workflow activity. These users could all be members of a single group. In fact, this is how I typically do majority approvals for the Change Advisory Board. Regardless of whether the users come from a group or are added individually, they are all combined together when evaluating counts in an ‘Approval – User’ activity.

//Approve based on percentage indicated
var approvePercent = 50;
if((counts.approved/counts.total)*100 >= approvePercent){
answer = 'approved';
}
if((counts.rejected/counts.total)*100 > (100 - approvePercent)){
answer = 'rejected';
}

Percentage-based approval with an ‘Approval – Group’ activity

It is also possible (albeit a bit more complex) to do percentage-based approvals with an ‘Approval – Group’ activity. The primary difference here is that you can require a certain percentage from multiple groups. In the example given, each individual group must meet the 50% approval threshold before the activity will return ‘Approved’ and tell the workflow to advance. Any single group not meeting the 50% mark will force a rejection for the entire activity. This took me way more time than it should have to figure out :). Hopefully it saves you a bit of time.

//Approve based on percentage from each group
var approvePercent = 50;
var approveCount = 0;
for(var id in groups){
var group = groups[id];
if((group.approved/group.total)*100 >= approvePercent){
//Mark the group approval record 'Approved'
var groupApproval = new GlideRecord('sysapproval_group');
groupApproval.get(id);
groupApproval.approval = 'approved';
groupApproval.update();
approveCount++;
}
if((group.rejected/group.total)*100 > (100 - approvePercent)){
answer = 'rejected';
break;
}
}
//Ensure all groups have approved
if(approveCount == counts.total){
answer = 'approved';
}

The post Percentage or Majority-based Workflow Approvals appeared first on ServiceNow Guru.

]]>
https://servicenowguru.com/graphical-workflow/approval-percentage/feed/ 12
Show a Task Workflow Timeline https://servicenowguru.com/ui-actions-system-ui/show-task-workflow-timeline/ https://servicenowguru.com/ui-actions-system-ui/show-task-workflow-timeline/#comments Wed, 16 May 2012 11:04:29 +0000 https://servicenowguru.wpengine.com/?p=4420 Having a blast from Knowledge 12 this week! It’s been fun this year being able to relax a little bit more and take some more time to talk with people. I look forward to meeting more of you over the next couple of days. Today, I’m writing in response to a user on the ServiceNow

The post Show a Task Workflow Timeline appeared first on ServiceNow Guru.

]]>
Having a blast from Knowledge 12 this week! It’s been fun this year being able to relax a little bit more and take some more time to talk with people. I look forward to meeting more of you over the next couple of days.

Today, I’m writing in response to a user on the ServiceNow community, and a few users in the advanced admin course I was observing earlier in the week. In the advanced admin class, they show how you can click a UI action on the change form to show a workflow in progress. They also show you how you can view a timeline for a workflow context. These UI actions (and corresponding popups) can provide valuable information to both administrators and technicians to determine the status and process of a particular workflow. The only problem (in the case of the timeline) is that it can’t be accessed from the change directly. You have to navigate to the workflow context record first.

In this post I’ll show you how to create a UI action script to display a workflow timeline popup directly from any task form in the system.

Change Request Timeline

If you’re familiar with the default UI action in the system, the code below should look familiar. It is initiated from the client, gets the sys_id of the workflow context, constructs a URL to the timeline, and then pops a new window up showing the timeline. The real trick in this case is getting the correct sys_id from the workflow context record. You should be able to create the following as a UI action on your task table. It will display for any itil user on a task that has an associated workflow.

‘Show Workflow Timeline’ UI Action
Name: Show Workflow Timeline
Table: Task
Order: 200
Show Insert: False
Client: True
OnClick: showTimeline();
Form link: True
Condition: !current.isNewRecord() && (new Workflow().hasWorkflow(current)) && gs.hasRole(‘itil’)
Script:

function showTimeline() {
var wf = new GlideRecord('wf_context');
wf.addQuery('id', g_form.getUniqueValue());
wf.query();
if(wf.next()){
var url = new GlideURL('show_schedule_page.do');
url.addParam('sysparm_stack', 'no');
url.addParam('sysparm_page_schedule_type', 'workflow_context');
url.addParam('sysparm_timeline_history', wf.sys_id);
var w = getTopWindow();
w.popupOpenFocus(url.getURL(), 'show_workflow_timeline', 950, 700, '', false, false);
}
}

The post Show a Task Workflow Timeline appeared first on ServiceNow Guru.

]]>
https://servicenowguru.com/ui-actions-system-ui/show-task-workflow-timeline/feed/ 4
Edit a Workflow Directly from a Task https://servicenowguru.com/ui-actions-system-ui/edit-workflow-ui-action/ https://servicenowguru.com/ui-actions-system-ui/edit-workflow-ui-action/#comments Wed, 22 Feb 2012 15:57:57 +0000 https://servicenowguru.wpengine.com/?p=4274 A couple of weeks ago, I saw a great idea from Alex Yupanqui, who works for ServiceNow, to create UI actions to allow users to directly edit a graphical workflow from the associated record. I’ve taken this idea and cleaned things up a bit to make it usable and secure throughout the system. You’re probably

The post Edit a Workflow Directly from a Task appeared first on ServiceNow Guru.

]]>
A couple of weeks ago, I saw a great idea from Alex Yupanqui, who works for ServiceNow, to create UI actions to allow users to directly edit a graphical workflow from the associated record. I’ve taken this idea and cleaned things up a bit to make it usable and secure throughout the system.

You’re probably already familiar with the ‘Show Workflow’ and ‘Workflow Context’ UI action links that show up on task records when a workflow gets associated to it. These UI actions are extremely useful for identifying the state of the workflow as it relates to the task. As an administrator or consultant, you’re often trying to troubleshoot or fix an issue with the workflow, which requires the workflow editor. Unfortunately, this means you have to navigate to the module in the left nav and try to find the correct workflow to edit. The purpose of this solution is to cut out all of those extra steps to allow you to edit the workflow directly from the record it is bound to.

Edit Workflow

Here’s the UI action code. Notice that it’s set on the ‘Global’ table so that it will be available as a link on every form in the system. You’ll also notice that the ‘Condition’ field is set to allow access to only the ‘workflow_admin’ role, and to only display the link when a record has a workflow associated to it.

‘Edit Workflow’ UI Action
Name: Edit Workflow
Table: Global
Action name: show_workflow_editor
Order: 205
Form link: True
Client: True
Onclick: showWorkflowEditor()
Condition: gs.hasRole(‘workflow_admin’) && new Workflow().hasWorkflow(current)
Script:

function showWorkflowEditor(){
//Open the workflow editor in a new window
var wf = new GlideRecord('wf_context');
wf.addQuery('id', g_form.getUniqueValue());
wf.query();
if(wf.next()){
getTopWindow().popupOpenFocus('workflow_ide.do?sysparm_sys_id=' + wf.workflow_version, 'show_workflow_version', 950, 700, '', false, false);
}
}

If you’ve set this global UI action up correctly, clicking the ‘Edit Workflow’ link will take you directly to the workflow editor for that specific workflow just as if you would have navigated through the module in the left nav.

Bonus UI Action

Here’s another UI action that you can use on the ‘wf_context’ table so that you have a quick link to edit the workflow when viewing a given workflow context. The basic ideas are the same, but the script and condition are a little bit different because we’re initiating the UI action from a specific table in this case.

‘Edit Workflow’ UI Action
Name: Edit Workflow
Table: Global
Action name: show_workflow_editor
Order: 105
Form link: True
Client: True
Onclick: showWorkflowEditor()
Condition: gs.hasRole(‘workflow_admin’)
Script:

function showWorkflowEditor(){
//Open the workflow editor in a new window
var id = g_form.getValue('workflow_version');
getTopWindow().popupOpenFocus('workflow_ide.do?sysparm_sys_id=' + id, 'show_workflow_version', 950, 700, '', false, false);
}

The post Edit a Workflow Directly from a Task appeared first on ServiceNow Guru.

]]>
https://servicenowguru.com/ui-actions-system-ui/edit-workflow-ui-action/feed/ 2
Control the Execution Order of Request Items in an Order Guide https://servicenowguru.com/system-definition/order-request-items-order-guide/ https://servicenowguru.com/system-definition/order-request-items-order-guide/#comments Tue, 23 Aug 2011 12:43:18 +0000 https://servicenowguru.wpengine.com/?p=3952 Lately I’ve been doing some service catalog work for a couple of clients and I’ve come across a requirement that I really haven’t had to address before. The requirement deals with order guides…specifically with the ability to control the execution order of individual items within an order guide. You’re probably aware that ServiceNow provides complete

The post Control the Execution Order of Request Items in an Order Guide appeared first on ServiceNow Guru.

]]>
Lately I’ve been doing some service catalog work for a couple of clients and I’ve come across a requirement that I really haven’t had to address before. The requirement deals with order guides…specifically with the ability to control the execution order of individual items within an order guide. You’re probably aware that ServiceNow provides complete control over the ordering of tasks within a catalog item, but what do you do with an order guide that needs to have one item complete before the next 2 items can start? There’s not a simple way to control this behavior by default so I came up with a way and I’ll share it here.

Initial setup

All of this depends on having the ability to identify whether or not an order guide is associated with an item that has been ordered, and which order guide that is. As such, your first step will be to make sure that you are recording the order guide used against the parent request record. This setup is not provided by default but you can add it by following the instructions in this article.

NOTE: This is recorded for you automatically in the Helsinki release and beyond! The instructions below reflect these changes as of the Helsinki release.

Establishing an execution order

Once you’ve validated that the order guide is being populated correctly you’re ready to set up the execution order for your items within that order guide. The solution is actually pretty simple and only requires 2 pieces, both of which are implemented in the workflow for the respective items within an order guide.

Example:
In order to illustrate this setup, I’ll use a simple example. Let’s say that you have an order guide for new hires that includes 2 items; ‘Computer Workstation’ and ‘Computer Software’. Both of these items need to be ordered and delivered as part of the new hire process, but they need to be delivered in a specific order. The ‘Computer Software’ item cannot be started until the ‘Computer Workstation’ item has finished because we need to have a workstation to be able to install the software.

The first step is to modify the graphical workflow associated with item 1 (the ‘Computer Workstation’ catalog item). The workflow should run through the same process whether or not the item is ordered as part of an order guide, but at some point in the workflow (probably right before the end) we need to check if the item is associated with an order guide and then tell the next item to start. The next item in this case is ‘Computer Software’.

We don’t have direct access to the next item, but we can easily set up a ‘Run script’ workflow activity to query for that item and set a value there telling the item that it can start. I’ve found that the simplest way of doing this is to set the ‘State’ field on the next request item record to ‘Work in Progress’. The script below can be used in your ‘Run script’ activity in your workflow. Just replace the name of the ‘Computer Software’ item below with the name of the item in your system.

‘Start next item’ Run script workflow activity
Name: Start next item
Script:

//If item is part of an order guide then start next item(s)
if(!current.order_guide.nil()){ //Change to 'current.request.u_order_guide' for pre-Helsinki
//Start the 'Computer Software' item next
itemStart('Computer Software');
}function itemStart(nextItemName){
//Query for the item that should start next
var item = new GlideRecord('sc_req_item');
item.addQuery('request', current.request);
item.addQuery('cat_item.name', nextItemName);
item.query();
while(item.next()){
//Set the item to 'Work in Progress' to initiate the item workflow (requires 'Wait for' activity in item workflow)
item.state = 2;
item.update();
}
}

 

This script works great, but it’s only part of the puzzle! Unless you tell item 2 (Computer Software) to wait for item 1 (Computer Workstation) then your script isn’t going to work the way you need it to. So, the second configuration change you’ll need to make is to add a ‘Wait for’ activity to the graphical workflow associated with item 2 (Computer Software). The ‘Wait for’ activity placement should probably be the first activity in the item 2 workflow, but will depend on your specific workflow. It should only apply if an order guide is associated with the parent request and the state is ‘Work in Progress.

Order Guide Wait For Activity

If you’ve followed the instructions above correctly, you should now be able to order your order guide item and execute the items in the order you’ve specified in the workflows. You can handle any order guide execution order scenario by repeating the same steps in the workflow for each item. If you have multiple items that need to start when item 1 is finished, then simply add those items to the script from item 1 and add the wait for condition to items 2, 3, 4, etc…

Bonus! Copying variable values from one item to another

Because your items are associated under a single order guide, it might also be necessary to pass variable values from one item to another. In order to do this, you’ll need to make sure that each item sharing variable values this way has an identically-named variable to place the value in. Once you’ve got that you could execute the following script inside a workflow ‘Run script’ activity.

copyVariables();

function copyVariables(){
//Copy the matching variables from this item to the other item(s) in this request
//Query the item option table for item variables
var rec = new GlideRecord('sc_item_option_mtom');
rec.addQuery('request_item', current.sys_id);
rec.query();
while(rec.next()){
//Query for the same variable associated with the parent Request's items
var itemVars = new GlideRecord('sc_item_option_mtom');
itemVars.addQuery('request_item', '!=', current.sys_id);
itemVars.addQuery('request_item.request', current.request);
itemVars.addQuery('sc_item_option.item_option_new.name', rec.sc_item_option.item_option_new.name.toString());
itemVars.query();

//If we find a matching variable in another item update its value
while(itemVars.next()){
//Get the variable value record
var itemVar = new GlideRecord('sc_item_option');
itemVar.get(itemVars.sc_item_option);
itemVar.value = rec.sc_item_option.value.toString();
itemVar.update();
}
}
}

The post Control the Execution Order of Request Items in an Order Guide appeared first on ServiceNow Guru.

]]>
https://servicenowguru.com/system-definition/order-request-items-order-guide/feed/ 15
Exporting Graphical Workflows in One Step https://servicenowguru.com/system-definition/exporting-graphical-workflows/ https://servicenowguru.com/system-definition/exporting-graphical-workflows/#comments Tue, 14 Dec 2010 18:08:50 +0000 https://servicenowguru.wpengine.com/?p=3096 While this article is still extremely useful as an example and a reference for exporting records and use of processors, the specific functionality for exporting workflow versions is now included by default in ServiceNow. The functionality was built-in starting with the Aspen release. I’ve written before about how you can quckly export and import data

The post Exporting Graphical Workflows in One Step appeared first on ServiceNow Guru.

]]>
While this article is still extremely useful as an example and a reference for exporting records and use of processors, the specific functionality for exporting workflow versions is now included by default in ServiceNow. The functionality was built-in starting with the Aspen release.

I’ve written before about how you can quckly export and import data between ServiceNow instances using the XML export/import context menus. While this works great for a lot of situations, it doesn’t work so great for data that resides in multiple tables, but really makes sense to be exported as a single unit. One example of this is Graphical Workflows. The components that make up a Graphical Workflow version are actually stored in 7 separate tables. It is possible to export a graphical workflow version but you have to do 7 separate exports to do it! In this post, I’ll show you how you can set up UI actions for some of these more complex export tasks.


The first step is to set up a ‘Processor’ record to handle the export. ServiceNow actually has some built-in code to handle exports like this. You just have to know how to leverage it. Here’s how you would set up a processor for the workflow export.

‘ExportWorkflow’ Processor
Name: ExportWorkflow
Type: Script
Path: export_workflow
Script:

//Get the sys_id of the workflow version
var sysID = g_request.getParameter('sysparm_sys_id');
//Get the sys_id of the workflow
var wfID = g_request.getParameter('sysparm_wf_id');
var actID = '';//Query for workflow activities
var act = new GlideRecord('wf_activity');
act.addQuery('workflow_version', sysID);
act.query();
while(act.next()){
actID = actID + ',' + act.sys_id.toString();
}//Export workflow version info to XML
var exporter = new ExportWithRelatedLists('wf_workflow_version', sysID);
exporter.addRelatedList('wf_stage', 'workflow_version');
exporter.addRelatedList('wf_activity', 'workflow_version');
exporter.addRelatedList('wf_condition', 'activity.workflow_version');
exporter.addRelatedList('wf_transition', 'to.workflow_version');
exporter.addRelatedList('wf_transition', 'from.workflow_version');
exporter.addRelatedList('wf_workflow_instance', 'workflow_version');
if(wfID != ''){
exporter.addQuerySet('wf_workflow', 'sys_id=' + wfID);
}
if(actID != ''){
exporter.addQuerySet('sys_variable_value', 'document_keyIN' + actID);
}
exporter.exportRecords(g_response);

Once you have your processor set up, you just need to call it. The processor above is called by its path name ‘export_workflow’ followed by ‘.do’. It also needs to know what to export so you need to pass it the sys_id of the top-level record that you want to export…in this case, the sys_id of the ‘Workflow context’ record.

‘Export to XML’ UI Action
Name: Export to XML
Table: Workflow Version (wf_workflow_version)
Order: 200
Form context menu: True
Hint: Export workflow for importing in another instance
Condition: gs.hasRole(“admin”)
Script:

action.setRedirectURL('export_workflow.do?sysparm_sys_id=' + current.sys_id + '&sysparm_wf_id=' + current.workflow);

Once you’re done with this, you should have an ‘Export to XML’ UI action context menu item on your ‘Workflow version’ form that you can use to transport workflows in the event that they don’t get captured in an update set.

The post Exporting Graphical Workflows in One Step appeared first on ServiceNow Guru.

]]>
https://servicenowguru.com/system-definition/exporting-graphical-workflows/feed/ 34
Change Management Workflow Approval Scripts in ServiceNow https://servicenowguru.com/scripting/change-management-workflow-approval-scripts-servicenowcom/ https://servicenowguru.com/scripting/change-management-workflow-approval-scripts-servicenowcom/#comments Wed, 20 Oct 2010 16:25:52 +0000 https://servicenowguru.wpengine.com/?p=2193 Service-now.com provides a really cool Graphical Workflow engine to help manage workflows for different tasks. This graphical workflow engine is particularly useful when working with approvals for Change Requests. As a ServiceNow consultant I’ve found that change approvals usually fall into just a few different types but new administrators and consultants sometimes don’t know the

The post Change Management Workflow Approval Scripts in ServiceNow appeared first on ServiceNow Guru.

]]>
Service-now.com provides a really cool Graphical Workflow engine to help manage workflows for different tasks. This graphical workflow engine is particularly useful when working with approvals for Change Requests. As a ServiceNow consultant I’ve found that change approvals usually fall into just a few different types but new administrators and consultants sometimes don’t know the best way to implement approvals. In this post I’ll share some of the common change workflow approval methods and scripts I’ve seen used before. I wouldn’t be surprised to see this list grow over time and I know I haven’t seen all of the common methods. If you have something you’ve used before please comment on this post or use the ‘Contact’ link above to send in your suggestion to share.

Simple Approvers Selection (Select Specific Group)

The simplest (and most common) type of approval is to select specific groups or users to approve the change. The screenshot below shows how you can use the standard reference field lookup to select a group to add as approvers to the change request. This method is commonly used when you want to have a specific group (like the CAB) approve at some point in your workflow.

Simple Approvers Selection (Drill to Related Records)

Another common method is to drill into the change request itself and pull the approvers from a field on the change. This method is commonly used when you want to have something like a manager approval for the person requesting the change (as shown below) or maybe when you want to have the assignment group on the change request approve.

Advanced Approvers Script (Approval Groups for all Change CIs)

The ServiceNow Graphical Workflow mechanism also allows you be even more complex in the selection of approvals for your change requests. You can use script with GlideRecord queries to return any users or groups you want to have approve. The one thing to keep in mind with these scripts is that you need to return group records if your workflow activity is a Group Approval type and user records if your workflow activity is a User Approval type.
One common request I’ve seen before that requires a script is to add approval groups based on the Configuration Items associated to the change request. Chances are you’ll have multiple CIs associated on the ‘Affected CIs’ related list for the change. This script queries for those records and then adds the groups from the ‘Approval Group’ field on each CI.

//Initialize an answer array to be returned
var answer = [];

//Add the primary CI approval group to the array
answer.push(current.cmdb_ci.change_control);

//Add the Affected CIs list approval groups to the array
var affCIs = new GlideRecord('task_ci');
affCIs.addQuery('task', current.sys_id);
affCIs.query();
while(affCIs.next()){
answer.push(affCIs.ci_item.change_control);
}

Advanced Approvers Script (Approval Groups for all Impacted Change CIs)

There are some rare cases where clients want to pull approval groups from other CIs that will be impacted by the change based on CI relationships. For these cases you can use the CIUtils2 script I created to walk the CI relationship tree and find the impacted CIs that you need to add approvals for. In order to use these scripts you’ll need to add the CIUtils2 script include to your system first. You’ll also want to use this type of approval method sparingly since it involves a sometimes resource-intensive traversal of your CMDB (if you have hundreds of thousands of CIs). It’s also pretty expensive process-wise as well. Do you really want to require approval from every single group in your company when your network team needs to make a change to the core router? Maybe so, maybe not, but either way you’re probably talking about a lot of approvals because that CI impacts so many other CIs in your environment.

Impacted CIs approval scripts
–This first example returns Approval Groups for all of the Business Services impacted by the change request–

//Initialize a variable for the CIUtils2 Script include
var ciu = new CIUtils2();
//Initialize an answer array to be returned
var answer = [];//Add any impacted business services for the change
var allCIs = ciu.cisAffectedByTask(current);

//Query for all CIs and return Approval Groups
for (var i = 0; i < allCIs.length; i++) {
var cis = new GlideRecord('cmdb_ci');
cis.addQuery('sys_id', allCIs[i]);
cis.query();
if (cis.next()) {
answer.push(cis.change_control);
}
}

–This example returns Approval Groups for all of the Business Services impacted by the change request AND Approval Groups for all directly Affected CIs on the change request. It utilizes the ‘CheckDuplicates‘ function I wrote to eliminate some unnecessary processing.–

//Initialize a variable for the CIUtils2 Script include
var ciu = new CIUtils2();
//Initialize an answer array to be returned
var answer = [];
//Initialize an array to gather and store all impacted CIs
var allCIs = [];

//Add the primary CI to the CI array
allCIs.push(current.cmdb_ci);

//Add the Affected CIs list to the CI array
var affCIs = new GlideRecord('task_ci');
affCIs.addQuery('task',current.sys_id);
affCIs.query();
while (affCIs.next()) {
allCIs.push(affCIs.ci_item);
}

//For each directly affected CI on the change, add any impacted business services
for (var i = 0; i < allCIs.length; i++) {
allCIs = allCIs.concat(ciu.cisAffectedByCI(allCIs[i]));
}

//Remove duplicate CIs from the array
allCIs = checkDuplicates(allCIs);

//Query for all CIs and return Approval Groups
for (var j = 0; j < allCIs.length; j++) {
var cis = new GlideRecord('cmdb_ci');
cis.addQuery('sys_id', allCIs[j]);
cis.query();
while (cis.next()) {
answer.push(cis.change_control);
}
}

function checkDuplicates(a) {
//Check all values in the incoming array and eliminate any duplicates
var r = []; //Create a new array to be returned with unique values
//Iterate through all values in the array passed to this function
o:for(var i = 0, n = a.length; i < n; i++){
//Iterate through any values in the array to be returned
for(var x = 0, y = r.length; x < y; x++){
//Compare the current value in the return array with the current value in the incoming array
if(r[x]==a[i]){
//If they match, then the incoming array value is a duplicate and should be skipped
continue o;
}
}
//If the value hasn't already been added to the return array (not a duplicate) then add it
r[r.length] = a[i];
}
//Return the reconstructed array of unique values
return r;
}

Ensuring someone approves

One of the big problems you may encounter is what happens if the approvers don’t exist or aren’t active. The behavior in ServiceNow is to mark the approval activity as ‘Approved’ if no approvers are returned by the activity.

Change admin failsafe approval activity
–This script looks to see if an approver is returned, and if not it pulls in the ‘Change admins’ group as approvers for the approval activity.–

// Set the variable 'answer' to a comma-separated list of user/group ids or an array of user/group ids to add as approvers.
//
// For example:
// var answer = [];
// answer.push('id1');
// answer.push('id2');var answer = [];
//Requested by and assignment group manager approval
if(current.requested_by.manager.active){
answer.push(current.requested_by.manager.sys_id);
}
if(current.assignment_group.manager.active){
answer.push(current.assignment_group.manager.sys_id);
}

//Ensure 'Change Admins' group gets added if no other approvers (optional)
if(answer.length == 0){
var grpName = 'Change Admins';
//Query for change admins group
var cGrp = new GlideRecord('sys_user_group');
cGrp.get('name', grpName);
answer.push(cGrp.sys_id);
}

Making a specific person the key approver

Some approval scenarios may also require that a specific individual has the full approval/rejection responsibility even as a member of a group. Even though others can approve or reject, a single person has the final say. Once they approve or reject, we move on from the activity. The following script can be used in an ‘Approval – User’ workflow activity to facilitate this type of setup.

Key Person Approval workflow activity
This script should be placed in the ‘Approval Script’ field in a ‘Approval – User’ workflow activity. The ‘Approval Script’ field displays when the ‘Wait for’ field is set to ‘Condition based on script’ as shown in the following screenshot.

//'keyApproverID' must approve or reject to advance approval
//Set the 'keyApproverID' variable to the sys_id of the user record of the key approver
var keyApproverID = '97000fcc0a0a0a6e0104ca999f619e5b';
if (approvalIDs) {
if (approvalIDs['approved'].indexOf(keyApproverID) > -1) {
answer = 'approved';
}
if (approvalIDs['rejected'].indexOf(keyApproverID) > -1) {
answer = 'rejected';
}
}

The post Change Management Workflow Approval Scripts in ServiceNow appeared first on ServiceNow Guru.

]]>
https://servicenowguru.com/scripting/change-management-workflow-approval-scripts-servicenowcom/feed/ 18
Managing Ad-hoc Tasks in ServiceNow Workflow https://servicenowguru.com/graphical-workflow/managing-adhoc-tasks-servicenow-workflow/ https://servicenowguru.com/graphical-workflow/managing-adhoc-tasks-servicenow-workflow/#comments Tue, 12 Jan 2010 22:19:25 +0000 https://servicenowguru.wpengine.com/?p=656 This post is written in response to a question I received from a reader about how to handle ad-hoc tasks when you’re using graphical workflow. I’m always open to suggestions on how to improve the site and its content. If you have any ideas, questions, or suggestions for the site just use the Contact link

The post Managing Ad-hoc Tasks in ServiceNow Workflow appeared first on ServiceNow Guru.

]]>
This post is written in response to a question I received from a reader about how to handle ad-hoc tasks when you’re using graphical workflow. I’m always open to suggestions on how to improve the site and its content. If you have any ideas, questions, or suggestions for the site just use the Contact link to submit them. Thanks Ruth!

“The requirement is to add an extra task to a set of tasks defined in a graphical workflow once it is running AND have a way of specifying the order AND have the new tasks start automatically when its predecessor completes and start the next one when it completes. In the days of execution/delivery plans I had done this using a rule which set the new predecessor/successor entries but can anyone advise how to approach it with workflow?”

This isn’t an easy problem to solve. I still don’t know if I’ve found a really good way to approach it yet, but here are a couple of things I’ve done in the past (that are currently being used in production systems) that may give you some ideas. Take it for what it’s worth. These probably aren’t perfect solutions, but it’s better than nothing I suppose! I’d love to hear of any feedback you have as you try these out (if you do) because this is an issue that I’m probably going to have to tackle in another month or so again.

Option #1:

Using execution plans and a custom business rule to allow insertion and re-ordering of tasks after the execution plan has initially been attached.–
What I’ve found is that execution plans are still more forgiving when it comes to ad-hoc tasks than workflow is. Because of this, if you have a need for ad-hoc tasks in Change requests, I think it makes a lot of sense to split the workflow processing and use Graphical workflow for approvals, and use Execution plans for task generation. If there’s no need for ad-hoc tasks, then I think Graphical workflow works best.

The challenge with ad-hoc tasks is the sequencing of those tasks. This business rule basically re-orders the entire list of associated change tasks in the execution plan each time the order on a change task changes. This includes when a new task is inserted.

-Table: Change task
-Order: 100
-Runs after insert/update
-Condition: current.order.changes()

syncTaskOrder();

function syncTaskOrder(){
//Query for all tasks that are associated to the same parent
var rec = new GlideRecord('change_task');
rec.addQuery('parent', current.parent);
rec.orderBy('order');
rec.query();
while(rec.next()){
//Delete all of the existing successor/predecessor records for the task
var rec1 = new GlideRecord('execution_plan_local');
var qc = rec1.addQuery('predecessor', rec.sys_id);
qc.addOrCondition('successor', rec.sys_id);
rec1.query();
while(rec1.next()){
rec1.deleteRecord();
}
}

//Query for all tasks that are associated to the same parent
var tsk = new GlideRecord(current.sys_class_name);
tsk.addQuery('parent', current.parent);
tsk.orderBy('order');
tsk.query();
var lastID = '';
var lastOrder;
var myIDArray=new Array();
while(tsk.next()){
if(tsk.order > lastOrder){
//Iterate through the sys_id array and create a new successor/predecessor record for each item
for(x in myIDArray){
//Initialize the creation of a new Task Sequencing record
var tsk1 = new GlideRecord('execution_plan_local');
tsk1.initialize();
tsk1.predecessor = myIDArray[x];
tsk1.successor = tsk.sys_id;
tsk1.insert();
}
//Empty the existing array
myIDArray.length = 0;
//Populate the current task sys_id into the array
myIDArray[0] = tsk.sys_id.toString();
}
else if((tsk.order == lastOrder) || !lastOrder){
var myIDArrayLength = myIDArray.length;
if(myIDArrayLength > 0){
//Get the last item in the array
var arrayIDVal = myIDArray[myIDArrayLength - 1];
//Query the Task Sequencing table for that item
var ps = new GlideRecord('execution_plan_local');
ps.addQuery('successor', arrayIDVal);
ps.query();
while(ps.next()){
//Create a new successor/predecessor record for the current task
var ps1 = new GlideRecord('execution_plan_local');
ps1.initialize();
ps1.predecessor = ps.predecessor;
ps1.successor = tsk.sys_id;
ps1.insert();
}
}
//Populate the current task sys_id into the array
myIDArray[myIDArrayLength] = tsk.sys_id.toString();
}
else{
}
lastOrder = Math.round(tsk.order);
lastID = tsk.sys_id.toString();
}
}

I also had to include this business rule to get the orders on the tasks to sync with execution plan task orders initially (although this may have been a bug that has since been fixed so this one may be optional).

-Table: Change task
-Order: 1,100 – This is important!
-Runs before insert
-Condition: current.delivery_task != ”

current.order = current.delivery_task.order;

I suppose the above method could also be used with Service requests, but I haven’t tried it.

Option #2:

I’ve seen this option used for service requests in ServiceNow. You can set up ‘dummy’ service request items that can be added to a service request with a defined number and ordering of tasks. This method could be used with either Graphical workflow or Execution plans.

The client that used this method (like most other customers) didn’t have a defined Service catalog, but wanted to use our Service catalog anyway. Basically what they ended up doing was having a single generic Service catalog item with a couple of steps that got added to any service request. Then they allowed their technicians to add other pre-defined request items to the request on the back end using the ‘Add new item’ button on the Request form. They defined as much as they could, but they also had pre-defined items that had tasks associated with them like ‘One task item’, ‘Three task item’, etc.
The nice thing about this method is that you can still attach your workflow or execution plan directly to those items. The person who needs to add more tasks can simply add another item to the request and it already has its workflow associated with it.

Option #3:

Create sub-tasks that can be manually added to the generated change or catalog tasks. Here is an example of how you could handle this for change requests. Let’s say that all of your change requests have to go through the same 3 steps. However, in certain cases, one or more ad-hoc tasks are needed. You could set up an execution plan (or workflow) to create 3 change tasks, and then create another table called ‘subtask’ that could be manually added to each auto-generated change task as necessary like this…

*Change Request
*Change task 1 –> FROM EXECUTION PLAN
*Subtask 1 –> MANUALLY ADDED
*Subtask 2 –> MANUALLY ADDED
*Change task 2 –> FROM EXECUTION PLAN
*Change task 3 –> FROM EXECUTION PLAN

So Subtasks 1 and 2 are children of Change task 1, and change task 1 does not get closed until subtasks 1 and 2 are closed.

Option #4:

Use a script in a ‘Wait for’ activity in your workflow to query for associated tasks and wait for their completion before moving on. This approach doesn’t deal with the ordering directly, but it does allow you to control tasks that are added outside of the workflow scope. The full solution is documented here in the Service-now wiki.

The post Managing Ad-hoc Tasks in ServiceNow Workflow appeared first on ServiceNow Guru.

]]>
https://servicenowguru.com/graphical-workflow/managing-adhoc-tasks-servicenow-workflow/feed/ 8
Parsing the Date and Time Sections from a Date/Time field https://servicenowguru.com/scripting/parsing-date-time-sections-from-datetime-field/ https://servicenowguru.com/scripting/parsing-date-time-sections-from-datetime-field/#comments Mon, 11 Jan 2010 14:49:51 +0000 https://servicenowguru.wpengine.com/?p=634 Here are some examples of how you could use a simple Javascript 'split' method to parse out the date and/or time value from a date/time field.  Both examples split out the date and time, populate them into variables, and then populate the date section into a regular date field on the same record. Business rule

The post Parsing the Date and Time Sections from a Date/Time field appeared first on ServiceNow Guru.

]]>
Here are some examples of how you could use a simple Javascript ‘split’ method to parse out the date and/or time value from a date/time field.  Both examples split out the date and time, populate them into variables, and then populate the date section into a regular date field on the same record.

Business rule example:

This could also be used in a graphical workflow ‘Run script’ activity but would need to include ‘current.update()’ at the end to call the update to the record.

Name: Populate Date from Date/Time
When: Before
Update: True
Condition: current.u_start_date_time.changes()

var dateSection = current.u_start_date_time.split(' ')[0]; //Gets the Date
var timeSection = current.u_start_date_time.split(' ')[1]; //Gets the Time
//Set the value of the Date field with the date from the Date/Time field
current.u_start_date = dateSection;

Client script example:

As is the case with all client scripting in Service-now, all fields referenced must actually be part of the rendered form (though they may be invisible) to be referenced by the client-side script.

Name: Populate Date from Date/Time
Type: OnChange
Field name: Start date/time (or whatever your date/time field is named)

function onChange(control, oldValue, newValue, isLoading) {
  //If the page isn't loading
  if (!isLoading) {
    //If the new value isn't blank
    if(newValue != '') {
      var dateSection = g_form.getValue('u_start_date_time').split(' ')[0]; //Gets the Date
      var timeSection = g_form.getValue('u_start_date_time').split(' ')[1]; //Gets the Time
      //Set the value of the Date field with the date from the Date/Time field
      g_form.setValue('u_start_date', dateSection);
    }
  }
}

The post Parsing the Date and Time Sections from a Date/Time field appeared first on ServiceNow Guru.

]]>
https://servicenowguru.com/scripting/parsing-date-time-sections-from-datetime-field/feed/ 3
Canceling executing workflows on task closure https://servicenowguru.com/business-rules-scripting/canceling-executing-workflows-task-closure/ https://servicenowguru.com/business-rules-scripting/canceling-executing-workflows-task-closure/#comments Tue, 29 Dec 2009 12:55:14 +0000 https://servicenowguru.wpengine.com/?p=407 It is very common to use graphical workflow to help facilitate some change management process within your organization. One common requirement in change management is to be able to cancel or close the change request at any time during the process. "Simple", you say. "Just allow the user to change the value of the 'State' field to 'Closed'."
You would not be incorrect in saying something like that, but you would be forgetting about part of the problem with closing or canceling a change request or other task ticket.

The post Canceling executing workflows on task closure appeared first on ServiceNow Guru.

]]>
Service-now.com provides a very robust and simple way to manage your tasks and approvals (among other things) through its graphical workflow engine.  It is very common to use graphical workflow to help facilitate some change management process within your organization.  One common requirement in change management is to be able to cancel or close the change request at any time during the process.  “Simple”, you say.  “Just allow the user to change the value of the ‘State’ field to ‘Closed’.”

You would not be incorrect in saying something like that, but you would be forgetting about part of the problem with closing or canceling a change request or other task ticket.  What if the attached workflow(s) still think that the change request and its associated tasks and approvals are still in progress?  Should the attached workflow context(s) continue to run indefinitely?  If your workflow doesn’t have a way to know about the completion of the change request then it will continue to run (or more likely just sit and be forgotten).


The answer to this problem is actually pretty simple.  Service-now.com comes with several out-of-box workflow utility functions defined under ‘System Definition -> Script Includes’ that can be helpful in situations like these.  While you don’t want to modify these script includes, it is probably a good idea as a Service-now administrator to become familiar with the tools and functions there.  One of the functions in the ‘Workflow’ script include is called ‘cancel’.  It can be used to cancel any running workflow activities for a given record. This script could be called from a UI action button, another workflow, or a business rule. You just need to be able to tell the function what GlideRecord should have its workflows canceled. The example below shows how you could create a business rule to cancel all running workflows for a given record if the ‘active’ field changed to ‘false’. The cancellation in the example below happens for the ‘current’ GlideRecord object (which is the current record being updated).

Cancel All Workflow Contexts for a given Record

Cancel Workflow Business Rule
Name: Cancel workflows
When: After
Insert: True
Update: True
Condition: current.active.changesTo(false)
Script:

//Query for all executing workflows and cancel any running activities
new Workflow().cancel(current);

Cancel a Single Workflow Context (by name) for a given Record

You may also encounter situations where you don’t want to cancel all associated workflow contexts, just a single one, or all but one. Again, you can find the solution in the ‘Workflow’ script include by way of the ‘getRunningFlows’ and ‘cancelContext’ functions. The following script could be run from a business rule, UI action, or even within a ‘Run Script’ workflow activity. The example given here cancels any ‘Routine Change’ workflow contexts associated with the ‘current’ record.

//Query for all executing workflow contexts
var flows = new Workflow().getRunningFlows(current);
while(flows.next()){
//Check for associated workflows by name
if(flows.workflow_version.getDisplayValue() == 'Routine Change'){
//Cancel the workflow context
new Workflow().cancelContext(flows);
}
}

The post Canceling executing workflows on task closure appeared first on ServiceNow Guru.

]]>
https://servicenowguru.com/business-rules-scripting/canceling-executing-workflows-task-closure/feed/ 23