It's all about the answers!

Ask a question

Why does a "Conditions" script (assigned in Operation Behavior) result of false fail to prevent a Save on the work item?


Paul Inman (3526) | asked Apr 12 '15, 5:31 p.m.
 RTC 5.0.1 using Client for Eclipse 4.2.x IDE
Based on various combinations of attribute values, we need to prevent the user from selecting particular actions that result in transitions to certain states.  We do not have the option of creating a plug-in and are limited to client-side scripting.  The situation arises when the state machine (workflow) defined for the work item allows transitions from one state to more than one other state, but the valid transitions depend on combinations of attribute values.  We are not permitted by the client to use roles, approvals, or any other approach to address this need.

The minimum we would like to do is to refuse to allow the user to save the work item if certain combinations of attribute values exist.  (Providing a proper error message is a separate issue.)

I am trying to use the Attribute Customization for Conditions facility to supply the Javascript for execution and the Operation Behavior of "Required Attributes for Condition" for the Save Work Item (server) Operation facility to trigger the script.  This works, except that a return value of false from the "matches" function implemented by the script does not prevent the work item from being saved.

I created a Sandbox project are to explore this potential solution with a simple work item and an associated workflow.  For this exploration, only one attribute is used: "Category" with an enum with two values - "A" and "B".  The state machine is simple: (I can't upload the diagram yet, due to lack of reputation points)
New => (via "Continue") => Stage 1
Stage 1 => (via "Submit A") => Branch A  OR (via "Submit B") => Branch B

The Conditions script is:
dojo.provide("sandbox.stateMachine.ValidStateTransition");

dojo.require("com.ibm.team.workitem.api.common.WorkItemAttributes");

(function() {
var doDebug = true;
var WorkItemAttributes = com.ibm.team.workitem.api.common.WorkItemAttributes;
  
var scriptname = "sandbox.stateMachine.ValidStateTransition";
    dojo.declare(scriptname, null, {

        matches: function(workItem, configuration) {
        debug("Start matches");
       
        var returnResult = true;
       
        var workFlowAction = configuration.getWorkflowAction();
        var workFlowState  = workItem.getValue(WorkItemAttributes.STATE);

        debug("WorkflowState:   " + workFlowState);
        debug("Workflow Action: " + workFlowAction);

        if (workFlowAction == null) {
            debug("user has not selected an action - nothing to do...");
            returnResult = true;

        } else if (workFlowState == "sandbox.stateMachine.conditionalWorkflowAB.state.stage1") {

            var selectedCategory = workItem.getValue("sandbox.stateMachine.category");
            debug("Category: " + selectedCategory);
           
            returnResult = false;

            if ((selectedCategory == "categoryA") && (workFlowAction == "sandbox.stateMachine.conditionalWorkflowAB.action.submitA")) {
                returnResult = true;
            }

            if ((selectedCategory == "categoryB") && (workFlowAction == "sandbox.stateMachine.conditionalWorkflowAB.action.submitB")) {
                returnResult = true;
            }
        }

        debug("matches result: " + returnResult);
        debug("End matches");  console.log("***");
        return returnResult;
           
    function debug(display){if(doDebug) {console.log(scriptname + ": " + display);}}
    }
    });
})();

Here's the (annotated using "===") console output from the log file when I load an existing work item already in the Stage 1 state:

=== Open the work item
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 12:59:42.450
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: Start matches'

!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 12:59:42.450
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: WorkflowState:   sandbox.stateMachine.conditionalWorkflowAB.state.stage1'

!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 12:59:42.451
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: Workflow Action: null'

!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 12:59:42.452
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: user has not selected an action - nothing to do...'

!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 12:59:42.452
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: matches result: true'

!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 12:59:42.452
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: End matches'

!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 12:59:42.452
!MESSAGE LOG: '***'

=== Category attribute is set to "A" and the "Submit B" action is selected
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:32.721
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: Start matches'

!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:32.722
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: WorkflowState:   sandbox.stateMachine.conditionalWorkflowAB.state.stage1'

!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:32.722
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: Workflow Action: sandbox.stateMachine.conditionalWorkflowAB.action.submitB'

!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:32.722
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: Category: categoryA'

!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:32.723
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: matches result: false'

!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:32.723
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: End matches'

!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:32.723
!MESSAGE LOG: '***'

=== Save is clicked
!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:48.737
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: Start matches'

!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:48.738
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: WorkflowState:   sandbox.stateMachine.conditionalWorkflowAB.state.stage1'

!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:48.739
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: Workflow Action: sandbox.stateMachine.conditionalWorkflowAB.action.submitB'

!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:48.740
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: Category: categoryA'

!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:48.740
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: matches result: false'
=== Note result of "false", above

!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:48.740
!MESSAGE LOG: 'sandbox.stateMachine.ValidStateTransition: End matches'

!ENTRY com.ibm.team.rtc.common.scriptengine 1 0 2015-04-12 13:00:48.740
!MESSAGE LOG: '***'

The work item is successfully saved with a state of "Branch B", even though the script returned false.  Note: in assigning the script "ValidStateTransition", above, to "Condition" for "Required Attributes for Condition", it does not matter which attribute, if any, are selected for the Condition in the table - the result is the same.

Thanks,
   -Paul Inman

Accepted answer


permanent link
Ralph Schoon (56.5k23642) | answered Apr 13 '15, 4:20 a.m.
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER
edited Apr 13 '15, 4:21 a.m.
Paul,

your description of the behavior above is correct. There is no "prevent workflow action based on condition" built in at this time. You could, maybe, achieve what you want though.

You could try to
  1. Add an attribute that is read only in the UI and has a default that is nor recognized as being set
  2. A required attribute for condition script would require the attribute for certain conditions that evaluates the selected workflow action as you do above

This way, the user could not save the work item with the chosen action, because the attribute does not have a required value and the user can't even enter one.

The selected workflow action is only available to conditions, so I don't see a different way to achieve what you want. The error message should tell the user that the action is not allowed.


I think it would be better to create a custom server advisor. You state you can't use any of the mechanism RTC usually provides to approach requirements like this however.

Paul Inman selected this answer as the correct answer

Comments
Paul Inman commented Apr 13 '15, 11:25 a.m.

 Ralph:


That's a clever idea - using a R/O attribute with an unset value.  I would try it hidden, also.  I'll have to think through this particular situation.  The test I ran is dramatically less complex than our situation, with multiple attributes and states involved.  Even if I can make this work in a complex situation, I also don't know how to set a custom error message from Conditions scripts (see: https://jazz.net/forum/questions/151624/how-can-i-define-the-error-message-for-a-required-attributes-for-condition).

With this information, we may be able to convince the client that we need to create a server extension, such as you suggest.

Thanks,
   -Paul

3 other answers



permanent link
Paul Inman (3526) | answered Apr 12 '15, 7:17 p.m.
I just learned that the "Required Attributes for Condition" pre-condition in the Operation Behavior does not do what I thought it did.  As I now understand it, all it can do is determine whether the attribute(s) it is tied to are required to have a value different than its default value for whatever condition you want to test.  The boolean return value from the "matches" function only tells the system whether the attribute value in question is required or not.  The return value only determines whether the Save operation can proceed in regard to required attributes.  I think I have that right.  Bottom line: I can't use this approach to prevent a user from taking a particular action.

Comments
Nate Decker commented Aug 10 '15, 11:01 a.m.

This information may be no longer relevant to you, but I just wanted to point out that you can make your Condition attribute validation a script and control when it returns "true". That way, it's not just based on a non-default value, but criteria you specify.


Paul Inman commented Aug 20 '15, 7:54 p.m.

 That's exactly what I did.  The conditions are a bit complex.  We ended up doing something else.  I will be experimenting with Ralph's suggestion, above.


   -Paul


permanent link
Mohanraj Ragupathi (54315) | answered Aug 10 '15, 9:01 a.m.
 Paul,
         Did you get the answer? I am in the same position to address this.


permanent link
Mohanraj Ragupathi (54315) | answered Aug 11 '15, 6:21 a.m.
Hi,
I have explained my requirement with details and script in the following forum. Please check what goes wrong and update me. Thanks in advance for your reply.

https://jazz.net/forum/questions/204365/why-workflow-action-is-not-working-in-condition-based-script

Your answer


Register or to post your answer.