How to find defects or stories that have been moved from one iteration to another?
Even though re-scheduling leaves an entry in the Revision History of a work item, querying the Revisions in WS API and parsing Revisions' descriptions for a specific string is discouraged because it is expensive and inefficient.
A more efficient solution requires using Lookback API, which, unlike WS API that returns current state of objects, returns historic snapshots.
Here is an example of a LookbackAPI query that returns all defects in a workspace where Iteration has been changed at one point. We start with a condition: "_PreviousValues.Iteration":{"$exists":true}
https://rally1.rallydev.com/analytics/v2.0/service/rally/workspace/<WORKSPACE_OID>/artifact/snapshot/query.js?find={"Project":<PROJECT_OID>,"_TypeHierarchy":"Defect","_PreviousValues.Iteration":{"$exists":true}}&fields=["ObjectID","_ValidFrom","_ValidTo","FormattedID","Iteration","_PreviousValues.Iteration"]&compress=true
In this example this query returns 54 results:
A limitation of this query is that its results include both the work items (Defects in this case) where iteration was changed from one iteration to another, and also those defects were previous iteration was null. This is true even in cases when a work item (specifically, a User Story) is created directly on the Iteration details page using Action > Schedule New User Story which immediately schedules a story as it is being created.
One of the results of this query illustrates this. Notice _PreviousValues.Iteration? below:
To exclude work items where Iteration was null before it was changed we add this condition to the query: "_PreviousValues.Iteration":{"$ne":null}}
https://rally1.rallydev.com/analytics/v2.0/service/rally/workspace/<WORKSPACE_OID>/artifact/snapshot/query.js?find={"Project":<PROJECT_OID>,"_TypeHierarchy":"Defect","_PreviousValues.Iteration":{"$exists":true},"_PreviousValues.Iteration":{"$ne":null}}&fields=["ObjectID","_ValidFrom","_ValidTo","FormattedID","Iteration","_PreviousValues.Iteration"]&compress=true
Now the total result count is lower, and excludes defects where previous iteration value was null.
If we want to further restrict the results to the subset of defects where _PreviousValues.Iteration was a specific Iteration, the following condition can be added:?"_PreviousValues.Iteration":<OBJECT_OID>
https://rally1.rallydev.com/analytics/v2.0/service/rally/workspace/<WORKSPACE_OID>/artifact/snapshot/query.js?find={"Project":<PROJECT_OID>,"_TypeHierarchy":"Defect","_PreviousValues.Iteration":{"$exists":true},"_PreviousValues.Iteration":<OBJECT_OID>}&fields=["ObjectID","_ValidFrom","_ValidTo","FormattedID","Iteration","_PreviousValues.Iteration"]&compress=true
In this example the total result count drops to 1:
For more information about _PreviousValues see Lookback API manual.
To visualize Lookback API data in an AppSDK2 app, see SnapshotStore that retrieves data from Lookback API.