Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

Scripted Field to get percent complete based on estimates of subtasks

Alex Christensen
Community Champion
September 16, 2015

I'm trying to create a scripted field on a parent task that gives me a percentage of the work completed based on the Time Spent and Remaining Estimate fields of the sub-tasks associated with that parent tasks. For example:

  • Parent Task
    • Sub-Task 1
      • Logged: 2h
      • Remaining: 0h
    • Sub-Task 2
      • Logged: 2h
      • Remaining: 0h
    • Sub-Task 3
      • Logged: 1h
      • Remaining: 1h

The percentage of work completed in this case would be 83.3%. I want this number to appear on the parent task.

I've created a scripted field to calculate this, but I'm having issues pulling the information I want. Please note that I'm very new to coding in general, so I've built this by combining and toying with multiple examples I've found online. Here's what I have so far:

import com.atlassian.jira.ComponentManager
import com.atlassian.jira.issue.Issue
import org.apache.log4j.Category
import com.atlassian.jira.config.SubTaskManager

SubTaskManager subTaskManager = ComponentManager.getInstance().getSubTaskManager();
Collection subTasks = issue.getSubTasks()
Double timeSpentTotal = 0
Double remainingEstimate = 0


if (subTaskManager.subTasksEnabled && !subTasks.empty) {
    subTasks.each {
        timeSpentTotal += it.getTimeSpent()
		// used .getTimeSpent because issue.getTimeSpent() works to retrieve Logged hours, but doesn't seem to work for subtasks
        remainingEstimate += it.estimate 
		// used .estimate because issue.estimate works to retrieve the remaining estimate, but doesn't seem to work for subtasks
        }
    }
Double progress = ( timeSpentTotal / ( timeSpentTotal + remainingEstimate ) ) * 100
return progress

Whenever I preview this using Script Runner, I get these errors: [GenericEntity.get] "getTimeSpent" is not a field of Issue and [GenericEntity.get] "estimate" is not a field of Issue. How can I adjust my script to get what I'm looking for? Is there a better way to do this that isn't based on the above script?

Thanks in advance for your help!

2 answers

1 accepted

0 votes
Answer accepted
Mark McCormack (Adaptavist)
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 16, 2015

Alex,

Try this:

import com.atlassian.jira.component.ComponentAccessor
  
def timeWorked = issue.getTimeSpent()
double progress = 0
if (timeWorked == null) timeWorked = 0
  
def timeEstimated = issue.getEstimate()
if (timeEstimated == null) timeEstimated = 0
  
def subTaskManager = ComponentAccessor.getSubTaskManager();
  
Collection subTasks = subTaskManager.getSubTaskObjects(issue)
  
if (subTaskManager.subTasksEnabled && !subTasks.empty) {
    subTasks.each {
        if (it.getTimeSpent() != null) {
            timeWorked += it.getTimeSpent()
        }
       if (it.getEstimate() != null) {
            timeEstimated += it.getEstimate()
        }
    }
}
  
progress = (timeWorked / (timeWorked + timeEstimated)) * 100
return progress.round(2)
Alex Christensen
Community Champion
September 17, 2015

Thanks for the help, Mark! This helped point me in the right direction. The value returned here is a Big Decimal, so I rounded the value to the nearest two decimal places - I needed a Double since I wanted to go with Jamie's other suggestion here of creating a custom template to display the value in an actual percentage, but store as a number so we can search on the value. Appreciate your help, Mark!

0 votes
JamieA
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 17, 2015

Out of interest I pasted your code in SR in 4.1 and it shows me:

image2015-9-17 12:42:14.png

The issue is that you're using issue.getSubtasks(), which is deprecated and returns a list of GenericValues. You should use issue.getSubtaskObjects().

My other suggestion would be to use a custom template that truncates the value to 1dp and shows the % sign, but would index the value as a number, which would allow you to search on this calculated value.

 

Alex Christensen
Community Champion
September 17, 2015

Thanks, Jamie. That helped. I took your suggestion and created a custom template, as well. Appreciate it!

Therese Liebermann
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
October 17, 2016

How do you actually make that custom template?  I am still learning about that.

Alex Christensen
Community Champion
October 17, 2016

Hi, Therese - when editing the custom field script, you can choose a template. Choose "Custom" from the list of options.

template.PNG

Here's the template I ended up using for this scripted field:

#if($value == 0)
    <div><strong>[<span style="color:green;font-weight:bolder"></span></strong>>>>>>>>>>><strong>]</strong> $numberTool.format('integer',$value)%</div>
#elseif($value > 0 && $value <= 10)
    <div><strong>[<span style="color:green;font-weight:bolder">></span></strong>>>>>>>>>><strong>]</strong> $numberTool.format('integer',$value)%</div>
#elseif($value > 10 && $value <= 20)
    <div><strong>[<span style="color:green;font-weight:bolder">>></span></strong>>>>>>>>><strong>]</strong> $numberTool.format('integer',$value)%</div>
#elseif($value > 20 && $value <= 30)
    <div><strong>[<span style="color:green;font-weight:bolder">>>></span></strong>>>>>>>><strong>]</strong> $numberTool.format('integer',$value)%</div>
#elseif($value > 30 && $value <= 40)
    <div><strong>[<span style="color:green;font-weight:bolder">>>>></span></strong>>>>>>><strong>]</strong> $numberTool.format('integer',$value)%</div>
#elseif($value > 40 && $value <= 50)
    <div><strong>[<span style="color:green;font-weight:bolder">>>>>></span></strong>>>>>><strong>]</strong> $numberTool.format('integer',$value)%</div>
#elseif($value > 50 && $value <= 60)
    <div><strong>[<span style="color:green;font-weight:bolder">>>>>></span></strong>>>>>><strong>]</strong> $numberTool.format('integer',$value)%</div>
#elseif($value > 60 && $value <= 70)
    <div><strong>[<span style="color:green;font-weight:bolder">>>>>>></span></strong>>>>><strong>]</strong> $numberTool.format('integer',$value)%</div>
#elseif($value > 70 && $value <= 80)
    <div><strong>[<span style="color:green;font-weight:bolder">>>>>>>></span></strong>>>><strong>]</strong> $numberTool.format('integer',$value)%</div>
#elseif($value > 80 && $value <= 90)
    <div><strong>[<span style="color:green;font-weight:bolder">>>>>>>>></span></strong>>><strong>]</strong> $numberTool.format('integer',$value)%</div>
#elseif($value > 90 && $value < 100)
    <div><strong>[<span style="color:green;font-weight:bolder">>>>>>>>>></span></strong>><strong>]</strong> $numberTool.format('integer',$value)%</div>
#elseif($value == 100)
    <div><strong>[<span style="color:green;font-weight:bolder">>>>>>>>>>></span></strong><strong>]</strong> $numberTool.format('integer',$value)%</div>
#else
    <div></div>
#end

Suggest an answer

Log in or Sign up to answer