It's all about the answers!

Ask a question

Attribute Configuration: Calculated timestamp being set unexpectantly


0
1
Chris Schaubach (611) | asked Jun 03 '12, 3:32 p.m.
edited Mar 26 '13, 4:23 a.m. by Ralph Schoon (56.5k23642)
I defined a dojo script to calculate the "Closed" timestamp of a defect.  The script has very simple logic; it simply looks if the Status is set to Closed, then returns the current timestamp.  (BTW, if the Status is set to anything else, I really WISH to be able to set the Closed timestamp to unassigned, but I don't see any documentation on how to do this, so I had no choice but to set the timestamp to some bogus value....).

This all works great.  HOWEVER.... I noticed that after the defect is set to Closed, and then you change some other attribute (such as....need to add a little bit more text to the "Description" to clarify the resolution):  The new Closed attribute gets set the current date again!  If this update to the defect was days/weeks/months later, then the Closed field is not trusted!

I put debug statements in my script.  And here is the bizarre thing.  As the Status changes, my script gets called and the console log messages really do get generated.  HOWEVER, when the status was previously Closed, and the update to the defect is to some other field with the status remaining as Closed, my debug console log messages aren't generated???  Yet the Closed attribute gets a new current timestamp.  Confusing!  Any ideas why?  Any workaround available? 

I'm on RTC V3.  Here is how I configured RTC:

Under "Configuration Data -> Attribute Customization", I defined a new "Calculated Values" dojo script of type "Script Based Calculated Value".

I defined a new attribute for defects that is a "Timestamp", with a "Calculated Value" set to the above script name, with "Dependencies" set to "Status".

Here's my script:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

dojo.provide("com.ibm.ism.calculateClosedTimestamp");

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

// --------------------------------------------------------------------------------
// Calculate the Closed Date.  When a defect goes into Closed status, then set
// the date to the current timestamp.
// If the defect has any other status, then set the Close Date to some bogus value.
// --------------------------------------------------------------------------------

(function() {
var WorkItemAttributes= com.ibm.team.workitem.api.common.WorkItemAttributes;

dojo.declare("com.ibm.ism.calculateClosedTimestamp", null, {
    getValue: function(attributeId, workItem, configuration) {
       
        // Log messages go to:  Eclipse client: client/eclipse/workspace/.metadata/.log
        console.log("com.ibm.ism.calculateClosedTimestamp - Entry");
       
        // Default value, which is a bogus timestamp
        var result = "1111-11-11T16:11:11.111Z";
               
        // Get the current timestamp, and convert it to an ISO-8601 string
        var currentDate = new Date();
        var currentDateString= dojo.date.stamp.toISOString(currentDate, {milliseconds:true, zulu:true});
        // console.log("com.ibm.ism.calculateClosedTimestamp:  currentDate: '" + currentDate + "'   currentDateString: '" + currentDateString + "'");
  
        var defectStatus = workItem.getValue(WorkItemAttributes.STATE);   
        // console.log("com.ibm.ism.calculateClosedTimestamp:  defectStatus: '" + defectStatus + "'");

        // If the state is closed
        if ( defectStatus == "DefectWorkflow.state.s1" )
        {
 
             result = currentDateString
             console.log("com.ibm.ism.calculateClosedTimestamp:  The state is closed.  Set close date to '" + result + "'");
 
        }
        else
        {
           console.log("com.ibm.ism.calculateClosedTimestamp:  The state is NOT closed.  Set close date to '" + result + "'")
        }
         
        console.log("com.ibm.ism.calculateClosedTimestamp - Exit:  Closed date returned is '" + result + "'")
       
        return result;
    }
});
})();




Comments
Ken Creager commented Dec 04 '12, 11:37 a.m.

Does anyone have the code to set the values of all States/Status??  I want to create a date field for each State/Status, and set them as those states get set.  Then if they get set again, i.e. the work item went back in the workflow, it would reset the date the the latest one.  So if the work item got to Resolved, and Resolved Date was set to 11 June 2012, then went back to some previous state and came back through and got resolved again on 1 December 2012, it would reset to the latest date?  I know this can get very complicated, with work items going back/forth in the workflow, but any suggestions?

Anyone using some other method to capture this information, i.e. it's in the history?

thanks

Ken

2 answers



permanent link
Filip Wieladek (30413) | answered Jun 04 '12, 4:05 a.m.
edited Jun 05 '12, 12:43 p.m.
You are right. It is currently not possible to return a "null" value for timestamps. You can return "0" which would be the time "1 Jan 1970" and could be treated as null for now.

The calculated value scripts are executed on every save operation (on the server side). This causes your issue. It is however very easy to fix on your side. Instead of simply saving the value every time, you can check if a valid closed value is already saved.

e.g.
<pre>
dojo.provide("com.ibm.ism.calculateClosedTimestamp");

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

// --------------------------------------------------------------------------------
// Calculate the Closed Date.  When a defect goes into Closed status, then set
// the date to the current timestamp.
// If the defect has any other status, then set the Close Date to some bogus value.
// --------------------------------------------------------------------------------

(function() {
var WorkItemAttributes= com.ibm.team.workitem.api.common.WorkItemAttributes;

dojo.declare("com.ibm.ism.calculateClosedTimestamp", null, {
    getValue: function(attributeId, workItem, configuration) {
      
        // Log messages go to:  Eclipse client: client/eclipse/workspace/.metadata/.log
        console.log("com.ibm.ism.calculateClosedTimestamp - Entry");
      
        // Default value, which is a bogus timestamp
        var result = "0";
              
        // Get the current timestamp, and convert it to an ISO-8601 string
        var currentDate = new Date();
        var currentDateString= dojo.date.stamp.toISOString(currentDate, {milliseconds:true, zulu:true});
        // console.log("com.ibm.ism.calculateClosedTimestamp:  currentDate: '" + currentDate + "'   currentDateString: '" + currentDateString + "'");
 
        var defectStatus = workItem.getValue(WorkItemAttributes.STATE);  
        console.log("com.ibm.ism.calculateClosedTimestamp:  defectStatus: '" + defectStatus + "'");

        // If the state is closed
        if ( defectStatus == "DefectWorkflow.state.s1" )
        {
             var closedDate= dojo.date.stamp.fromISOString(workItem.getValue(attributeId));
             console.log("com.ibm.ism.calculateClosedTimestamp: The current closed date is '" + closedDate +"'");
             if (closedDate.getTime() == 0) {
                 result = currentDateString
                 console.log("com.ibm.ism.calculateClosedTimestamp:  The state is closed.  Set close date to '" + result + "'");
             } else {
                 console.log("com.ibm.ism.calculateClosedTimestamp:  The state is closed.  But has already a closed Date. Use that instead");
                 result= dojo.date.stamp.toISOString(closedDate, {milliseconds:true, zulu:true});
             }
        }
        else
        {
           console.log("com.ibm.ism.calculateClosedTimestamp:  The state is NOT closed.  Set close date to '" + result + "'")
        }
        
        console.log("com.ibm.ism.calculateClosedTimestamp - Exit:  Closed date returned is '" + result + "'")
      
        return result;
    }
});
})();

Comments
Chris Schaubach commented Jun 04 '12, 8:55 a.m. | edited Jun 04 '12, 10:05 a.m.

Thanks Filip..... There is only one thing that concerns me with your suggestion:  Recursion.  I'm implementing a getValue method for this Closed date attribute.  Inside my method, I make a call to getValue on the same attribute.  Won't I get into an infinite recursive loop?

I had previously experimented with something similar, but not exactly as you suggested (which I definitely like your suggestion better), and I found I corrupted the Closed date value, and RTC would not display my experimental defect ever again.  And worse, when I performed a general query for defects, whose result set would contain my experimental defect, RTC stops cold in its tracks and does not display the remainder of the defects.  Thus, I got real skittish about this recursion, because this corrupted defect will impact the rest of my team.


Filip Wieladek commented Jun 04 '12, 9:35 a.m. | edited Jun 04 '12, 9:36 a.m.

Side note: We now have this QA style forum, please use the "Add comment" functionality if you are not posting an answer. You can convert this "answer" to a comment using the "more" menu.

No, it should not cause any recursive issues. Every access in the script is already resolved (at this point you will simply have the old value). I have also tested the script before I posted it :).

I also filed a work item for returning "null" dates under: Work Item 213940


Chris Schaubach commented Jun 04 '12, 11:09 a.m.

Thanks Filip....It works like a champ....thanks for opening that workitem.....


Filip Wieladek commented Jun 05 '12, 12:43 p.m. | edited Jun 05 '12, 12:44 p.m.

nvm wrong question


Gayathri Vikraman commented Jul 03 '12, 3:21 a.m. | edited Jul 03 '12, 3:22 a.m.

Hi Filip and Chris
      I am also working on a similar customization, where in I want the timestamp at which a Review work item is moved to Ready For Review state. For this I created  a new custom attribute Review Date and a claculated value script is used. I used the script given by Filip in this forum post and made few modification with respect to the literal value of the state and the attribute ids.
    The problem I am facing is at the below line of code.
var ReviewDate= dojo.date.stamp.fromISOString(workItem.getValue(attributeId)); 
   In the console log ReviewDate returns 'null' even though there is the default value which is set Jan 1,1970 5:30AM.
And for the further steps in the script there are errors in the console log.
   Can you please help me on this?


priya sekar commented Jun 13 '13, 6:43 a.m.

Hi Gayathri,

Could you pls let me know if you were able to fix this issue? I am also facing the same.

showing 5 of 6 show 1 more comments

permanent link
Randy Lexvold (6) | answered Mar 05 '14, 10:14 a.m.
 Couldn't you also use the Attribute dependency and say that timestamp attribute is dependent on Status? Then if Status doesn't change, the script never gets called.

Your answer


Register or to post your answer.