Scripted Field to get percent complete based on estimates of subtasks

Alex Christensen
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
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 Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
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 Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
September 17, 2015

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

Therese Liebermann October 17, 2016

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

Alex Christensen
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
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