Rolling back from resolved to In progress in Request
We need to be able to rollback when the request is already resolved. The two points of rollback are when the supporter goes again to Assigned manually, or when the caller puts a comment on a resolved request.
When you publish a new workflow,
only the new requests use this workflow. For this reason, we have made a mechanism to know in which workflow version are we, so that we allow the user to rollback or not (will be used by the Business rule that rollback from a user comment, and the client script that allows the Assigned state).
Steps
Modify Workflow 'CERN Request Fulfillment Workflow v2'
We have changed the workflow, so that all the request categories goes to the state 'Wait For Fulfillment Resolved', so that we can handle if there is a change to the state going to
In progress from a comment from the user (Business rule explained later), to
Assigned by the supporter (manually) or closed after 3 days by the system.
The limitation is that we don't allow the rollback from a rejected approval, we need other workflow modules for that.
Create Script Include 'WorkflowRequestVersioningHelper'
- Server-side helper to know if the current workflow associated with a record is specific version. In this case, our workflow version that we want check is the one with Rollback functionality.
- We check the release date of a specific version of the workflow (manually set), comparing it with the date that context workflow on the record was started.
var WorkflowRequestVersioningHelper = Class.create();
WorkflowRequestVersioningHelper.prototype = Object.extendsObject(AbstractAjaxProcessor, {
/**
* Constants determining the date when a workflow version was deployed, so
* that we can check whether we are in one version or another not to break
* back compatibility
*/
TAGGED_WF_DATE_VERSION_1 : '02/05/2011', // Rollback in request
/*
* Returns true if the associated workflow is compatible with
* the rollback functionality
*
* Used by Business Rules
*/
isRollbackResolveCompatibleServer: function(/* gliderecord*/ record) {
return this._isWFVersionRunning(record.sys_class_name, record.sys_id,
this.TAGGED_WF_DATE_VERSION_1);
},
/*
* Returns true if the associated workflow is compatible with
* the rollback functionality
*
* Used by Client Scripts via GlideAjax
*/
isRollbackResolveCompatibleClient: function() {
return this._isWFVersionRunning(this.getParameter('sysparm_class_name'), this.getParameter('sysparm_sys_id'),
this.TAGGED_WF_DATE_VERSION_1);
},
/*
* Check if the current record is running this specific version of the Workflow.
*
* We check the release date of a specific version of the workflow, comparing
* it with the date that context workflow on the record was started.
*/
_isWFVersionRunning: function(className, recordSysId, versionDate) {
gs.include('Workflow');
var wf = new Workflow();
var contexts = this._getRunningFlows(className, recordSysId);
if (contexts != null && contexts.next()) {
var updatedOnDateObject = contexts.started;
var versionDateObject = new Packages.com.glide.glideobject.GlideDateTime();
versionDateObject.setDisplayValue(versionDate);
if(this._isDateLaterThan(updatedOnDateObject, versionDateObject)) {
return true;
} else {
return false;
}
} else {
return false;
}
},
/**
* Get the running workflow contexts for 'record'
*/
_getRunningFlows: function(className, recordSysId) {
var gr = new GlideRecord('wf_context');
gr.addQuery('table', className);
gr.addQuery('state', 'executing');
gr.addQuery('id', recordSysId);
gr.query();
return gr;
},
_isDateLaterThan: function(/* glidedate */ date1, /* glidedate */ date2) {
// gs.dateDiff makes param2 - param1
var diffDates = gs.dateDiff(date2.getDisplayValue(), date1.getDisplayValue(), true);
if(diffDates >= 0) {
return true;
} else {
return false;
}
}
});
Usage of the Script Include
gs.include('WorkflowRequestVersioningHelper');
var wfHelper = new WorkflowRequestVersioningHelper();
if (wfHelper.isRollbackResolveCompatibleServer(current)) {
gs.addInfoMessage('Is rollback compatible');
} else {
gs.addInfoMessage('Is not rollback compatible or it is not running');
}
var ga = new GlideAjax('WorkflowRequestVersioningHelper');
ga.addParam('sysparm_name','isRollbackResolveCompatibleClient');
ga.addParam('sysparm_class_name',g_form.getTableName());
ga.addParam('sysparm_sys_id',g_form.getUniqueValue());
ga.getXML(doSomething);
function doSomething(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
alert(answer);
}
Change Client Script 'Request state transitions'
- Comment the option Assigned (so, it will appear) when the state is resolved.
..
if (TaskState == 9) { //Resolved
g_form.removeOption('u_current_task_state', 1); //New
// OP: Added rollback in 30th April, only if we are in the new workflow, we allow this option
disableAssignedIfWFisNotRollbackCompatible();
g_form.removeOption('u_current_task_state', 4); //In progress
..
..
function disableAssignedIfWFisNotRollbackCompatible() {
var ga = new GlideAjax('WorkflowRequestVersioningHelper');
ga.addParam('sysparm_name','isRollbackResolveCompatibleClient');
ga.addParam('sysparm_class_name',g_form.getTableName());
ga.addParam('sysparm_sys_id',g_form.getUniqueValue());
ga.getXML(setAssignedOptionDisabled);
}
function setAssignedOptionDisabled(response) {
var compatible = response.responseXML.documentElement.getAttribute("answer");
if (compatible != 'true' && compatible != true) {
g_form.removeOption('u_current_task_state', 2); //Assigned
}
// else, we allow Assigned
}
Modify BR 'RequestF Change Status Resolve User Info'
- If the caller update the additional comment of his request fulfillment when it was "Resolved", we set the status to "In progress"
- This only happens when the workflow is rollback compatible, making use of the previously explained Script Include.
Condition |
current.u_current_task_state == 9 && !current.u_current_task_state.changes() && current.comments.changes() |
Script |
gs.include('WorkflowRequestVersioningHelper');
var wfHelper = new WorkflowRequestVersioningHelper();
if (wfHelper.isRollbackResolveCompatibleServer(current)) {
//gs.addInfoMessage('Is the workflow version with rollback');
if (gs.getUserID() == current.u_caller_id.sys_id){
current.u_current_task_state = 4; //Request fulfillment state In progress
}
} else {
//gs.addInfoMessage('Is the workflow version without rollback');
} |
Create a BR 'Rolling back from Resolved,coordinate WF'
- If it was resolved, and it goes to another state that is NOT closed, we put it to Fulfillment stage. No matter which category it is.
Condition |
(current.u_current_task_state.changesFrom('9') || current.u_workflow_stage.changesFrom('Resolved'))
&& !(current.u_current_task_state.changesTo('10') || current.u_workflow_stage.changesTo('Closed')) |
Script |
current.u_workflow_stage = 'Fulfillment'; |
Limitations
- When the category is Access, Services or Configuration (need approvals), when the approval is rejected there is no rollback. Once we have approval rollback we can add this functionality. At the moment, it is just from Resolved to In progress/Assigned.
--
OmarPera - 05-May-2011