how to get the time spent from Assigned to In Progress in jira?

fabby January 31, 2013

my jira version is 4.4.1

my jira workflow is

i tried to use Scripted Field to get the time spent from Assigned to In Progres?

i can get the time Start Progress(4) (the time change Assigned status to In Progress Status) by

changeHistoryManager.getChangeItemsForField (issue, "status").reverse().each {ChangeItemBean item ->
 item.fromString=="Assigned" && item.toString=="In Progress"
}

my problem is how can i get the Assign time (some action like Assign761,Assign751,or Assign 741 whose destination step is Assigned).i.e. Start Progress(4) 's previous Action time

any one can give some ideas?

7 answers

1 accepted

3 votes
Answer accepted
fabby February 1, 2013

i have fix it myself.

import com.atlassian.core.util.DateUtils
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.history.ChangeItemBean
import com.atlassian.jira.issue.Issue 
  
def componentManager = ComponentManager.getInstance()
def changeHistoryManager = componentManager.getChangeHistoryManager()

log.warn("+++++++++++++++++++++++")

def getTimeSpent={  //define a closure to get transfered timeSpent
    if(it){
        return it
    }else{ //negative value or less than one minute
        return "<1m"
    }
}

def createTime=issue.getCreated().getTime() // getTime() tranfer to milliseconds
log.warn("create time:"+issue.getCreated().toString()+"to millisecond:"+issue.getCreated().getTime())

def firstAssign=changeHistoryManager.getChangeItemsForField(issue, "status").find{
it.fromString=="Open" && it.toString=="Assigned"
}?.getCreated()
log.warn("firstAssign:"+firstAssign)

def firstStart=changeHistoryManager.getChangeItemsForField(issue, "status").find{
it.fromString=="Assigned" && it.toString=="In Progress"
}?.getCreated()
log.warn("firstStart:"+firstStart)

if(firstAssign){ //has initially Assign
    if(firstStart){ //has execute Start Progress
        def Duration_A=[0] //Assigned->In Progress
        def Duration_R=[0] //Reopened->In Progress
        
        def items = [["","",""]]
        changeHistoryManager.getChangeItemsForField (issue, "status").each {
            if (it.toString == "Assigned" || (it.fromString == "Assigned" && it.toString == "In Progress")) { //filter specified status
                items << [it.fromString,it.toString,it.created]  
            }
        }
        items=items.drop(1)
        //log.warn("items:"+items)
        while(!(items.last().getAt(0)=="Assigned" && items.last().getAt(1)=="In Progress")){
            items.pop()
        }
        log.warn("items:"+items)
        for(int i=0;i<items.size();i++){
            if(items.getAt(i).getAt(0)=="Assigned" && items.getAt(i).getAt(1)=="In Progress"){ 
                Duration_A << items.getAt(i).getAt(2).getTime()
            }else if(items.getAt(i+1).getAt(0)=="Assigned" && items.getAt(i+1).getAt(1)=="In Progress"){
                Duration_A << -items.getAt(i).getAt(2).getTime()
            }
        }
        Duration_A=DateUtils.getDurationString(Math.round(Duration_A.sum()/1000))
        timeSpent_A=getTimeSpent(Duration_A)
    }else  //return the time from Assign to now
    {
        def Duration = System.currentTimeMillis() - firstAssign.getTime()
        def timeSpent=DateUtils.getDurationString(Math.round(Duration/1000))
        timeSpent=getTimeSpent(timeSpent)
    }
}else{ //there aren't workflow transitions executed yet.
    return "has not Assigned yet"
}

Jeannette Lamb June 25, 2014

can anyone help me modify this to achieve the following:

if status = "Open"

calculate from "Open" to Now

else

calculate from "Open" to "Acknowledged"

Thank you!

1 vote
fabby February 2, 2013

below is to get time spent In Progress->Resolved

import com.atlassian.core.util.DateUtils
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.history.ChangeItemBean
import com.atlassian.jira.issue.Issue 
  
def componentManager = ComponentManager.getInstance()
def changeHistoryManager = componentManager.getChangeHistoryManager()

log.warn("+++++++++++++++++++++++")

def getTimeSpent={it->  //define a closure to get transfered timeSpent
    def timeSpent=DateUtils.getDurationString(Math.round(it/1000))
    if(timeSpent){
        return timeSpent
    }else{ //negative value or less than one minute
        return "<1m"
    }
}

def getDuration={x,y-> //difine a closure to get Duration
    def Duration=[0]
    def items = [["","",""]]
    changeHistoryManager.getChangeItemsForField (issue, "status").each {
        if (it.toString == x || (it.fromString == x && it.toString == y)) { //filter specified status
            items << [it.fromString,it.toString,it.created]  
        }
    }
    items=items.drop(1)
    //log.warn("items:"+items)
    while(!(items.last().getAt(0)==x && items.last().getAt(1)==y)){
        items.pop()
    }
    log.warn("items:"+items)
    for(int i=0;i<items.size();i++){
        if(items.getAt(i).getAt(0)==x && items.getAt(i).getAt(1)==y){ 
            Duration << items.getAt(i).getAt(2).getTime()
        }else if(items.getAt(i+1).getAt(0)==x && items.getAt(i+1).getAt(1)==y){
            Duration << -items.getAt(i).getAt(2).getTime()
        }
    }
    return Duration
}

def createTime=issue.getCreated().getTime() // getTime() tranfer to milliseconds
log.warn("create time:"+issue.getCreated().toString()+"to millisecond:"+issue.getCreated().getTime())

def firstAssign=changeHistoryManager.getChangeItemsForField(issue, "status").find{
it.fromString=="Open" && it.toString=="Assigned"
}?.getCreated()
log.warn("firstAssign:"+firstAssign)

def firstStart=changeHistoryManager.getChangeItemsForField(issue, "status").find{
it.fromString=="Assigned" && it.toString=="In Progress"
}?.getCreated()
log.warn("firstStart:"+firstStart)

//get first (In Progress -> Resolved)
def firstResolve=changeHistoryManager.getChangeItemsForField(issue, "status").find{
it.fromString=="In Progress" && it.toString=="Resolved"
}?.getCreated()
log.warn("firstResolve:"+firstResolve)

if(firstAssign){ //has initially Assign
    if(firstStart){ //has execute Start Progress
        if(firstResolve){  //exist (In Progress -> Resolved)
            def Duration=getDuration("In Progress","Resolved")
            log.warn("Duration"+Duration+" class:"+Duration.sum().class)
            def timeSpent=getTimeSpent(Duration.sum())
        }else{ //not exist (In Progress -> Resolved)
            def Duration = System.currentTimeMillis() - firstStart.getTime()
            log.warn("Duration:"+Duration+"class:"+Duration.class)
            def timeSpent=getTimeSpent(Duration)
        }
    }else  //return the time from Assign to now
    {
        return "has not Start Progress yet."
    }
}else{ //there aren't workflow transitions executed yet.
    return "has not Assigned yet"
}

Tomas Gustavsson
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 14, 2019

Hello 

I'm not that experienced with coding an i'm trying to test this scripts with the script console in Jira via Script runner, but i can't manage to get it to work, can i compile this in some tool to get it to work.  
e.g, some things are not recognized, like it-&gt and &amp and at some occasion, there are, double, i guess there are some things i need to replace to make it work in my instance?  

it.fromString=="Reopened" && it.toString=="In Progress"

 
Sorry for little knowledge in this matter 

/T

1 vote
fabby February 2, 2013

and below code is to get total time spent from Assigned->In Progress,and Reopened->In Progress

import com.atlassian.core.util.DateUtils
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.history.ChangeItemBean
import com.atlassian.jira.issue.Issue 
  
def componentManager = ComponentManager.getInstance()
def changeHistoryManager = componentManager.getChangeHistoryManager()

log.warn("+++++++++++++++++++++++")

def getTimeSpent={it->  //define a closure to get transfered timeSpent
    def timeSpent=DateUtils.getDurationString(Math.round(it/1000))
    if(timeSpent){
        return timeSpent
    }else{ //negative value or less than one minute
        return "<1m"
    }
}

def getDuration={x,y-> //difine a closure to get Duration
    def Duration=[0]
    def items = [["","",""]]
    changeHistoryManager.getChangeItemsForField (issue, "status").each {
        if (it.toString == x || (it.fromString == x && it.toString == y)) { //filter specified status
            items << [it.fromString,it.toString,it.created]  
        }
    }
    items=items.drop(1)
    //log.warn("items:"+items)
    while(!(items.last().getAt(0)==x && items.last().getAt(1)==y)){
        items.pop()
    }
    log.warn("items:"+items)
    for(int i=0;i<items.size();i++){
        if(items.getAt(i).getAt(0)==x && items.getAt(i).getAt(1)==y){ 
            Duration << items.getAt(i).getAt(2).getTime()
        }else if(items.getAt(i+1).getAt(0)==x && items.getAt(i+1).getAt(1)==y){
            Duration << -items.getAt(i).getAt(2).getTime()
        }
    }
    return Duration
}

def createTime=issue.getCreated().getTime() // getTime() tranfer to milliseconds
log.warn("create time:"+issue.getCreated().toString()+"to millisecond:"+issue.getCreated().getTime())

def firstAssign=changeHistoryManager.getChangeItemsForField(issue, "status").find{
it.fromString=="Open" && it.toString=="Assigned"
}?.getCreated()
log.warn("firstAssign:"+firstAssign)

def firstStart=changeHistoryManager.getChangeItemsForField(issue, "status").find{
it.fromString=="Assigned" && it.toString=="In Progress"
}?.getCreated()
log.warn("firstStart:"+firstStart)

//get first (Reopened -> In Progress)
def firstReopentoInProgress=changeHistoryManager.getChangeItemsForField(issue, "status").find{
it.fromString=="Reopened" && it.toString=="In Progress"
}?.getCreated()
log.warn("firstReopentoInProgress:"+firstReopentoInProgress)

if(firstAssign){ //has initially Assign
    if(firstStart){ //has execute Start Progress
        def Duration_A=getDuration("Assigned","In Progress")
        log.warn("Duration_A"+Duration_A+" class:"+Duration_A.sum().class)
        def timeSpent_A=getTimeSpent(Duration_A.sum())
        log.warn("timeSpent_A:"+timeSpent_A)
        def Duration_R,timeSpent_R,timeSpent_total
        if(firstReopentoInProgress){  //exist (Reopened -> In Progress)
            Duration_R=getDuration("Reopened","In Progress").sum()
            log.warn("Duration_R:"+Duration_R)
            timeSpent_R=getTimeSpent(Duration_R)
        }else{ //not exist (Reopened -> In Progress)
            Duration_R=0
        }
        timeSpent_total=getTimeSpent(Duration_A.sum()+Duration_R)
        return "timeSpent_A:${timeSpent_A},timeSpent_R:${timeSpent_R},timeSpent_total:${timeSpent_total}"
    }else  //return the time from Assign to now
    {
        def Duration = System.currentTimeMillis() - firstAssign.getTime()
        log.warn("Duration:"+Duration+"class:"+Duration.class)
        timeSpent=getTimeSpent(Duration)
    }
}else{ //there aren't workflow transitions executed yet.
    return "has not Assigned yet"
}

Raju Adluru
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 25, 2014

Hi Fabby Chen i have similar kind of request, where user want to know how long the issue is in current status, for e.g Issue is in "In Progress" status, how long it has been in this status, like wise for other statuses of other issues, how to get this kind of report, manager wants to track, which status is bottleneck to resolve the issue. Appreciate your help on this. Thanks alot Raj

0 votes
RomainD February 13, 2013

Hi,

I’m the product manager of VertygoSLA

As Rahul says, it seems that you can solve your problem using VertygoSLA.

You can create an issue to get some helps in our support system : https://jira.valiantys.com.

You can also have a look on the documentation : https://confluence.valiantys.com/display/VSLA/VertygoSLA


Best regards,

0 votes
Jozef Kotlár
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 31, 2013

You are not very clear with explanation what you want to compute.At least for me.

Anyway with your proposed method you should be able to find the time where issue was "assigned", e.g. when item.toString=="Assigned", shouldn't you?

Jozef Kotlár
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 31, 2013

More precisely item.fromString!="Open" && item.toString=="Assigned"

fabby February 1, 2013

hi Jozef,

one issue's lifecycle may be open -> Assigned -> In Progress...

there also exists other possibilities:

if one issue's lifecycle is like open(a) -> Assigned(b) -> Assigned(c) -> In Progress(d)...

1 when tester create the issue,issue is in open(a) status,

2 then leader assign the issue to Tom,issue is in Assigned(b) status,

3 later the leader find he has wrong assigned ,so he reassign the issue to Jim,issue is in Assigned(c) status,

4 jim Start Progress,issue is in In Progress(d) status.

so item.fromString!="Open" && item.toString=="Assigned" may not correctly reflect the time Jim spent on responding the issue,i.e. the time spent from Assigned(c) -> In Progress(d)

Jozef Kotlár
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 3, 2013

Well, you know your workflow better ;-)

0 votes
fabby January 31, 2013

i'm urgent to fix this issue.anyone can give help?

0 votes
Rahul Aich [Nagra]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 31, 2013

Have you looked at the transitions tab on the issue (assuming you have jira suite utilities plugin). This tab tells you amount of time spent on each status.

Otherwise, you can install plugin vertyGo SLA which can provide detailed information on amount of time spent on each status.

https://marketplace.atlassian.com/plugins/com.valiantys.jira.plugins.vertygo.jira-vertygosla-plugin

Rahul

fabby January 31, 2013

hi,Rahul

i have already installed jira suite utilities plugin,i just can 'see' the 'Time In Source Status' value.

what i want is obtain the value and store it in one field.and then we can make a statistic on dashboard.

Suggest an answer

Log in or Sign up to answer