The Now Platform® Washington DC release is live. Watch now!

Help
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
jamesmcwhinney
Mega Guru

We recently were asked to add checklists to some of our catalog tasks, so that our service desk could easily track the specific steps that needed to be taken for the completion of the catalog task.

Ideally, we would like to manage the checkbox creation from within the "Catalog Task Activity", to make configuration and maintenance easy. It also would mean that the configuration of the checklist is also tied nicely to the workflow version, in case things need to change over time.

Unfortunately, the catalog task's "Advanced Script" function seems to be executed before the catalog task is created, meaning we dont know the task's sysid, which is something we need in order to link a checklist to the resulting task.

Below is the solution we came up with.  If anyone knows of a better way, I am always interested to hear it.

Cheers,

- James

 

Step 1: Script Include

We created a script include with a series of methods which will accept a catalog task, look for the associated workflow activity, find the "Advanced Script" function, parse that script and look for a given function, and then execute the code.

We also included some script to create a checklist.

var workflowTools = Class.create();
workflowTools.prototype = {
    initialize: function() {
    },
	createChecklist: function (table_name, record_sys_id, description, owner_sys_id){
	//Create Checklist
		var gr_checklist = new GlideRecord('checklist');
		gr_checklist.initialize(); 
		gr_checklist.table = table_name;
		gr_checklist.document = record_sys_id;
		gr_checklist.name = description;
		gr_checklist.owner = owner_sys_id; 
		return gr_checklist.insert();
	},
	addChecklistItem: function(checklist_sys_id, description, order){
		var gr_item = new GlideRecord('checklist_item');
		gr_item.checklist = checklist_sys_id;
		gr_item.complete = false;
		gr_item.name = description;
		gr_item.order = order;
		return gr_item.insert();
	},
	runScript: function(script, vars){
		//Thanks to https://community.servicenow.com/community?id=community_question&sys_id=881b8faddb5cdbc01dcaf3231f9619c1&view_source=searchResult
		var result;
		var evaluator = new GlideScopedEvaluator();   
		var gr = new GlideRecord('sys_script');   
		gr.addQuery('sys_policy','read'); //additional protection against accidental update
		gr.setLimit(1);   
		gr.query();   
		if (gr.next()) {
			gr.setValue('script',script);   
			try {
				result = evaluator.evaluateScript(gr, 'script', vars);
			} catch (e) {
				gs.error(e);
			}
		} else {
			throw new Error('No rows were found to dynamically use GlideScopedEvaluator against');
		}
		return result;
	},
	getExecutingActivityFromTask: function(task, document_sysid){
		//get all executing activities against the target document and find the one tied to this specific task
		var executingActivity;
		var gr_executingActivity = new GlideRecord('wf_executing');
		var join_wf_context = gr_executingActivity.addJoinQuery('wf_context', 'context', 'sys_id');
		join_wf_context.addCondition('id', "" + document_sysid);
		gr_executingActivity.query();
		while(gr_executingActivity.next()){
			if(gr_executingActivity.scratchpad.taskID == ("" + task.sys_id)){
				executingActivity = gr_executingActivity;
			}
		}
		return executingActivity;	
	},
	getScriptFunction: function(str_script, str_tag_start, str_tag_end){
		var str_function;
		if(str_script){
			if(str_script.length > 0){
				//Find start of Function.
				var int_startPos = str_script.indexOf(str_tag_start);
				if(int_startPos > -1){
					//Found start of function
					var int_endPos = str_script.indexOf(str_tag_end,int_startPos);
					if(int_endPos > -1){
						//Found end of function
						str_function = str_script.substring(int_startPos,int_endPos+1);
					}
				}
			}
		}
		return str_function;
	},
	callTaskFunction: function(functionName, task, document_table, document_sysid){
		//Get Corresponding wf_activity for this task
		var bool_processedSuccessfully = false;
		var executingActivity = this.getExecutingActivityFromTask(task, document_sysid);
		if(executingActivity){
			//Get task's advanced script
			var gr_varval = new GlideRecord('sys_variable_value');
			gr_varval.addQuery('document','wf_activity');
			gr_varval.addQuery('document_key',"" + executingActivity.activity);
			gr_varval.addQuery('variable','98b96f90c0a800666b58ec516f330397'); // Advanced Script
			gr_varval.query();
			while(gr_varval.next()){
				var str_fullscript = gr_varval.getValue('value');
				var str_function = this.getScriptFunction(str_fullscript, 'function ' + functionName + '(task,document){', '}//end' + functionName);
				if(str_function){
					//Get Current Document Record
					var gr_document = new GlideRecord(document_table);
					if(gr_document.get(document_sysid)){
						var vars = {'task' : task, 'document' : gr_document};
						var result = this.runScript(str_function + ";" + functionName + "(task,document);", vars);
						bool_processedSuccessfully = result.success;
					}
				}
			}
		}
		return bool_processedSuccessfully;
	},
	type: 'workflowTools'
};

Step 2: Business Rule

We created a business rule that runs after each catalog task is created, and uses the above script to execute the function "onTaskCreated" within the catalog task's associated activity record's "Advanced Script" function.

Table: sc_task
When: async
Insert: Yes
Update: No
Script:

(function executeRule(current, previous /*null when async*/) {
	var wfTools = new workflowTools();
	
	//Process onClick script specified in Workflow Activity
	var bool_processedSuccessfully = wfTools.callTaskFunction('onTaskCreated', current, 'sc_req_item', "" + current.request_item);
})(current, previous);

Step 3: Add custom function in catalog task activity's Advanced Script:

// Set values for the task in this script.  Use the variable 'task' when setting additional values.
// Note: This script is run after the task values are set using the Fields, Template or Values you have specified.
//
// For example:
//     task.short_description = current.short_description;
function onTaskCreated(task,document){
	var wfTools = new workflowTools();
	var user_sys_id = '..your desired owner user account sysid here..'; 
	var checklist_sys_id = wfTools.createChecklist("sc_task", task.sys_id, "Reciept Checklist",user_sys_id);
	wfTools.addChecklistItem(checklist_sys_id, "Ship the phone", 0);
	wfTools.addChecklistItem(checklist_sys_id, "Have a beer", 1);	
}//endonTaskCreated

 

After the Catalog task activity generates its catalog task, the business rule fires and looks for the "onTaskCreated" function inside its associated activity and executes it.  The checklist is created and linked to the catalog task.

 

Comments
Maharechi
Tera Contributor

Hi James,

I came across this issue too. I was able to solve it using setNewGuid();

Here is what to do.

1: The Business rule is not needed

2: The workflowTools Script Include can still be used

3: Update the Advanced script section of the Workflow Activity as follows with the difference commented

//------------------------begin script-------------------------

onTaskCreated(task.setNewGuid()); //setting the guid/sys_id of the workflow activity and calling the function here

function onTaskCreated(task){  //removed 'document' variable as it is not used

      var wfTools = new workflowTools();

      var user_sys_id = '..your desired owner user account sysid here..';

      var checklist_sys_id = wfTools.createChecklist("sc_task", task, "Reciept Checklist",user_sys_id); //removed .sysid from task.sys_id

      wfTools.addChecklistItem(checklist_sys_id, "Ship the phone", 0);

      wfTools.addChecklistItem(checklist_sys_id, "Have 8 beers", 1); //changed from 'a' beer to 8 beers. Cheers!!! 

}//endonTaskCreated

 

-Calvin 

 

 

jamesmcwhinney
Mega Guru

Hi Calvin,

 

 

 

So "setNewGuid()" forces the new glide record to get a sysid even before its actually been inserted?

And that sysid isnt overwritten when its actually inserted??

 

If so, that is a way way cleaner solution than the insanity I posted above.

Thanks!!

jamesmcwhinney
Mega Guru

Hi Calvin,

 

one other thought on this.

Doesn't this introduce some risk in the sense that if the .insert() ends up failing or not getting executed for whatever reason, then you will have created a checklist against a bad sysid?

 

Thanks,

- James

ericgilmore
Tera Guru

What was the answer on this? Curious because I'm looking at possibly using this.

Version history
Last update:
‎10-05-2018 08:56 AM
Updated by: