Accumulate Story Points on Parent based on Sub: Task story points

siva June 22, 2022

Hello,

I want the Story Points field for the parent story to be the sum of the sub-tasks. In my jira server instance we are using Script runner plugin and is it possible to sum up all sub task story points to parent issue story point. Please help me how to achieve this issue.

For example: 

If parent issue had 2 story points and sub task had 1 story point and I need sum up both 2+1=3 on Parent.

 

Thanks,

Siva.

4 answers

1 accepted

0 votes
Answer accepted
Andrea Pannitti
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.
June 26, 2022

Hi @siva,

I changed the code as follows:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.index.IssueIndexingService

def issue = event.issue
def eventName = ComponentAccessor.eventTypeManager.getEventType(event.eventTypeId).name
def cfStoryPoints = ComponentAccessor.customFieldManager.getCustomFieldObjectsByName("Estimated Story Points").first()

if (issue.parentObject != null) {
def subTasks = ComponentAccessor.subTaskManager.getSubTaskObjects(issue.parentObject)
int intStoryPoints = (issue.parentObject.getCustomFieldValue(cfStoryPoints) != null ? ((issue.parentObject.getCustomFieldValue(cfStoryPoints).toString() as Double) as Integer) : 0) + (eventName == "Issue Created" ? (issue.getCustomFieldValue(cfStoryPoints) != null ? ((issue.getCustomFieldValue(cfStoryPoints).toString() as Double) as Integer) : 0) : 0)
/*subTasks.each {
intStoryPoints += (it.getCustomFieldValue(cfStoryPoints) != null ? ((it.getCustomFieldValue(cfStoryPoints).toString() as Double) as Integer) : 0)
}*/
cfStoryPoints.updateValue(null, issue.parentObject, new ModifiedValue(issue.parentObject.getCustomFieldValue(cfStoryPoints), intStoryPoints as Double), new DefaultIssueChangeHolder())
ComponentAccessor.getComponent(IssueIndexingService).reIndex(issue.parentObject)
} else {
def subTasks = ComponentAccessor.subTaskManager.getSubTaskObjects(issue)
int intStoryPoints = (issue.getCustomFieldValue(cfStoryPoints) != null ? ((issue.getCustomFieldValue(cfStoryPoints).toString() as Double) as Integer) : 0)
subTasks.each {
intStoryPoints += (it.getCustomFieldValue(cfStoryPoints) != null ? ((it.getCustomFieldValue(cfStoryPoints).toString() as Double) as Integer) : 0)
}
cfStoryPoints.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(cfStoryPoints), intStoryPoints as Double), new DefaultIssueChangeHolder())
ComponentAccessor.getComponent(IssueIndexingService).reIndex(issue)
}
Check if it's ok for you.
siva June 27, 2022

@Andrea Pannitti 

Tested the above script this also performed like previous script calculates the all subtask story points again when 2nd subtask created.

Once again will explain it

I had created issue story and story point was 2 under story created subtask-1  and story point is 1. So far the script working fine it calculated 2+1=3.

Now this time created 2nd subtask-2  and story point is 2 now suppose to calculate parent + subtask-2 i.e  3+2=5.  But our script calculates parent + subtask-1 +subtask-2 i.e 3+1+2=6

Thank,

Siva

Andrea Pannitti
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.
June 27, 2022

@siva,

I've commented out a few lines in the code above; can you check if the behavior is what you expect?

siva June 27, 2022

@Andrea Pannitti 

Thank you very much finally it start working as i expert and finally one more last modification in the script is it any possibility to update  Estimated Story Points in parent when existing subtasks story points are updated and also when subtask is deleted. As of now the present script working fine when subtask is created and also I'm attaching the screen shot how I configure the script in listener. Once again thank you very much for your help and very appreciated.

Story Point issue .png

Thanks,

Siva.

siva June 29, 2022

@Andrea Pannitti 

Please help me on this issue the whole team waiting for your response

Andrea Pannitti
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.
June 29, 2022

Hi @siva,

from what you wrote in your last post, I thought the problem was completely solved.
Thank you very much for appreciating the help I have given you but I don't think I can devote myself further to this issue.

0 votes
Andrea Pannitti
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.
June 25, 2022

Hi @siva,

replace this line:

int intStoryPoints = 0 + (eventName == "Issue Created" ? (issue.getCustomFieldValue(cfStoryPoints) != null ? ((issue.getCustomFieldValue(cfStoryPoints).toString() as Double) as Integer) : 0) : 0)

with the following:

int intStoryPoints = (issue.parentObject.getCustomFieldValue(cfStoryPoints) as Integer) + (eventName == "Issue Created" ? (issue.getCustomFieldValue(cfStoryPoints) != null ? ((issue.getCustomFieldValue(cfStoryPoints).toString() as Double) as Integer) : 0) : 0) 
siva June 26, 2022

@Andrea Pannitti 

Thanks for the reply and changes done on the script what you mention in above comment and it start working now it calculates parent story points also. But coming to script it works perfectly only when single Sub Task and  if parent had two subtasks it counts twice.

For example:

If we created  Sub Task-1 and story point is 2 here it counts well (assume parent story point is 2) Parent+2=4

Now if we created another  Sub Task-2 and story point is 2 and it suppose to count 4+2=6 but our script counts parent+ 'Sub Task-1'+ 'Sub Task-2' that is 4+2+2=8. It can't calculate individual Sub Task it counts the all Sub Task to parent when 2nd Sub Task is created. Here the modified script below.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.index.IssueIndexingService

def issue = event.issue
def eventName = ComponentAccessor.eventTypeManager.getEventType(event.eventTypeId).name
def cfStoryPoints = ComponentAccessor.customFieldManager.getCustomFieldObjectsByName("Estimated Story Points").first()

if (issue.parentObject != null) {
def subTasks = ComponentAccessor.subTaskManager.getSubTaskObjects(issue.parentObject)
int intStoryPoints = (issue.parentObject.getCustomFieldValue(cfStoryPoints) as Integer) + (eventName == "Issue Created" ? (issue.getCustomFieldValue(cfStoryPoints) != null ? ((issue.getCustomFieldValue(cfStoryPoints).toString() as Double) as Integer) : 0) : 0)
subTasks.each {
intStoryPoints += (it.getCustomFieldValue(cfStoryPoints) != null ? ((it.getCustomFieldValue(cfStoryPoints).toString() as Double) as Integer) : 0)
}
cfStoryPoints.updateValue(null, issue.parentObject, new ModifiedValue(issue.parentObject.getCustomFieldValue(cfStoryPoints), intStoryPoints as Double), new DefaultIssueChangeHolder())
ComponentAccessor.getComponent(IssueIndexingService).reIndex(event.issue)
}

 

Thanks,

Siva

siva June 26, 2022

@Andrea Pannitti 

Please help me how to solve this issue.

0 votes
Andrea Pannitti
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.
June 23, 2022

Hi @siva,

to solve your issue you could add a Script Listener to your project on Issue Created and Issue Updated events with the following code:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.index.IssueIndexingService

def issue = event.issue
def eventName = ComponentAccessor.eventTypeManager.getEventType(event.eventTypeId).name
def cfStoryPoints = ComponentAccessor.customFieldManager.getCustomFieldObjectsByName("Original Story points").first()

if (issue.parentObject != null) {
def subTasks = ComponentAccessor.subTaskManager.getSubTaskObjects(issue.parentObject)
int intStoryPoints = 0 + (eventName == "Issue Created" ? (issue.getCustomFieldValue(cfStoryPoints) != null ? ((issue.getCustomFieldValue(cfStoryPoints).toString() as Double) as Integer) : 0) : 0)
subTasks.each {
intStoryPoints += (it.getCustomFieldValue(cfStoryPoints) != null ? ((it.getCustomFieldValue(cfStoryPoints).toString() as Double) as Integer) : 0)
}
cfStoryPoints.updateValue(null, issue.parentObject, new ModifiedValue(issue.parentObject.getCustomFieldValue(cfStoryPoints), intStoryPoints as Double), new DefaultIssueChangeHolder())
ComponentAccessor.getComponent(IssueIndexingService).reIndex(event.issue)
}
siva June 24, 2022

@Andrea Pannitti 

 

Thanks for your reply and I created Script Listener with Created  and Issue Updated events with the following code:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.index.IssueIndexingService

def issue = event.issue
def eventName = ComponentAccessor.eventTypeManager.getEventType(event.eventTypeId).name
def cfStoryPoints = ComponentAccessor.customFieldManager.getCustomFieldObjectsByName("Estimated Story points").first()

if (issue.parentObject != null) {
def subTasks = ComponentAccessor.subTaskManager.getSubTaskObjects(issue.parentObject)
int intStoryPoints = 0 + (eventName == "Issue Created" ? (issue.getCustomFieldValue(cfStoryPoints) != null ? ((issue.getCustomFieldValue(cfStoryPoints).toString() as Double) as Integer) : 0) : 0)
subTasks.each {
intStoryPoints += (it.getCustomFieldValue(cfStoryPoints) != null ? ((it.getCustomFieldValue(cfStoryPoints).toString() as Double) as Integer) : 0)
}
cfStoryPoints.updateValue(null, issue.parentObject, new ModifiedValue(issue.parentObject.getCustomFieldValue(cfStoryPoints), intStoryPoints as Double), new DefaultIssueChangeHolder())
ComponentAccessor.getComponent(IssueIndexingService).reIndex(event.issue)
}

 

But I'm getting the error on implementing the script here the error logs below

2022-06-24 21:11:52,007 ERROR [runner.AbstractScriptListener]: *************************************************************************************
2022-06-24 21:11:52,007 ERROR [runner.AbstractScriptListener]: Script function failed on event: com.atlassian.jira.event.issue.IssueEvent, file: null
java.util.NoSuchElementException: Cannot access first() element from an empty List
at Script58.run(Script58.groovy:8)

 

Please suggest me where i modified the script and just letting you the field name you are using for story point is Estimated Story Points.

 

Thanks,

Siva

Andrea Pannitti
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.
June 24, 2022

Hi @siva,

the issue could depends by the fact that the custom field name is "Estimated Story Points" but you writed "Estimated Story points" in the code. Upper and lower cases are importants.

siva June 25, 2022

@Andrea Pannitti 

Thanks for the reply and I updated "Estimated Story Points" field with correct lettering  in  the script and it is start working. But the present script sum up only Sub-Tasks Estimated Story Points and didn't calculate the Parent one. 

For example:

If parent had 3 Estimated Story Points and Sub-Task-1 had 5 Story Points and  Sub-Task-2 had 6 story points then normally calculates 3+5+6=14 story points but our present script calculates only Sub-Tasks 5+6=11 and this 11 updated on Parent  "Estimated Story Points" where as 3 parent story point totally gone. Please help me where i modified the script and your help very appreciated. Here the script below

 

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.index.IssueIndexingService

def issue = event.issue
def eventName = ComponentAccessor.eventTypeManager.getEventType(event.eventTypeId).name
def cfStoryPoints = ComponentAccessor.customFieldManager.getCustomFieldObjectsByName("Estimated Story Points").first()

if (issue.parentObject != null) {
def subTasks = ComponentAccessor.subTaskManager.getSubTaskObjects(issue.parentObject)
int intStoryPoints = 0 + (eventName == "Issue Created" ? (issue.getCustomFieldValue(cfStoryPoints) != null ? ((issue.getCustomFieldValue(cfStoryPoints).toString() as Double) as Integer) : 0) : 0)
subTasks.each {
intStoryPoints += (it.getCustomFieldValue(cfStoryPoints) != null ? ((it.getCustomFieldValue(cfStoryPoints).toString() as Double) as Integer) : 0)
}
cfStoryPoints.updateValue(null, issue.parentObject, new ModifiedValue(issue.parentObject.getCustomFieldValue(cfStoryPoints), intStoryPoints as Double), new DefaultIssueChangeHolder())
ComponentAccessor.getComponent(IssueIndexingService).reIndex(event.issue)
}

 

 

Thanks,

Siva.

siva August 28, 2022

@Andrea Pannitti 

How are you doing? I believe you are doing well. This is an old post, and you have resolved it, but I need your assistance. The current script sum up all  all Estimated story points to the parent, and here is the script.

 

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.index.IssueIndexingService

def issue = event.issue
def eventName = ComponentAccessor.eventTypeManager.getEventType(event.eventTypeId).name
def cfStoryPoints = ComponentAccessor.customFieldManager.getCustomFieldObjectsByName("Estimated Story Points").first()

if (issue.parentObject != null) {
def subTasks = ComponentAccessor.subTaskManager.getSubTaskObjects(issue.parentObject)
int intStoryPoints = 0 + (eventName == "Issue Created" ? (issue.getCustomFieldValue(cfStoryPoints) != null ? ((issue.getCustomFieldValue(cfStoryPoints).toString() as Double) as Integer) : 0) : 0)
subTasks.each {
intStoryPoints += (it.getCustomFieldValue(cfStoryPoints) != null ? ((it.getCustomFieldValue(cfStoryPoints).toString() as Double) as Integer) : 0)
}
cfStoryPoints.updateValue(null, issue.parentObject, new ModifiedValue(issue.parentObject.getCustomFieldValue(cfStoryPoints), intStoryPoints as Double), new DefaultIssueChangeHolder())
ComponentAccessor.getComponent(IssueIndexingService).reIndex(event.issue)
}

I had  a scenario (which I did not know was a possibility) that we need to make an adjustment to the script.

There can be a possibility where sub-tasks are created with 0 story points (as they have not been sized yet) but the parent story has existing story points and this is being overwritten with a value of 0.

The change needs to evaluate the total of the sub-task's story points and if the value is 0 do not overwrite the value in the parent issue's story point field.

 

Thanks,

Siva.

0 votes
Nic Brough -Adaptavist-
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
June 23, 2022

Before you do this, it's important to understand if you are trying to use Jira to support an Agile way of working.  If you are, then you don't want to be adding story points up to the parent.

Suggest an answer

Log in or Sign up to answer