Set Story Points Field according to Single Select Field on same Issue

Peter April 18, 2019

Hello together,

I tried to set the Story Points field according to a single Select field, to force all users to use the fibonacci values.

 

Therefor i simply want to copy the value of my Single Select List into the Story Point Field.

As i read, this would be possible with Scriptrunner, so i just installed the trial on a test instance, but failed badly o.O

 

First attempt was really simple, but woked.. almost :D

I tried a behaviour with  following code:

def nsp = getFieldByName("New Story Points").getValue();
def sp = getFieldByName("Story Points");

if (nsp != 0) {
sp.setFormValue(nsp);
} else if (nsp == 0) {0}

 As this would be to easy to be true, it just updates the value in the edit screen, but doesnt update the Issue.

 

So i tried using a "Script Listener".. therefor i found some suggestions online but none of them worked..

I tried to set a custom listener on Issue Updated and Created with the following code:

import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.component.ComponentAccessor

def issue = event.issue as Issue
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def tgtField = customFieldManager.getCustomFieldObjects(event.issue).find {it.name == "Story Points"}
def calcField = customFieldManager.getCustomFieldObjectByName("New Story Points")
def changeHolder = new DefaultIssueChangeHolder()
tgtField.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(tgtField), calcField),changeHolder)

  but this just ends in an History hint for the listener "X of X failed, including the last one"

 

i would appreciate any help..

Thank you

1 answer

1 accepted

1 vote
Answer accepted
Antoine Berry
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
April 18, 2019

Hi @Peter ,

I think you are really close. Just need to update with the value of the field instead. Also, I do not think you need to use the event object to get the issue. See : 

import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.component.ComponentAccessor

def newStoryPointsChanged = event?.getChangeLog()?.getRelated("ChildChangeItem")?.find {it.field == "New Story Points"}

if (newStoryPointsChanged){
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def tgtField = customFieldManager.getCustomFieldObjectByName("Story Points")
def calcField = customFieldManager.getCustomFieldObjectByName("New Story Points")
def changeHolder = new DefaultIssueChangeHolder()
tgtField.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(tgtField), issue.getCustomFieldValue(calcField)),changeHolder)
}

You can use this if so that the story poitns field will update only if new story points field is changed (If you are using Issue Updated event for example).

Antoine

Peter April 24, 2019

Hello @Antoine Berry ,

 

Thank you for your answer.

Since i am really new to ScriptRunner (i just installed the trial) - i might miss something obvious for you, but the Script doesnt work. (all i've done is covered within the Screenshot).

Just nothing happens. -> Do i miss something like any project configuration?

i tried the exat same code from you -  without an declaratiion of issue as an event object, i got an error message, so i added this declaration again.

Screenshot.JPG

Antoine Berry
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
April 24, 2019

Hi @Peter ,

Everything looks fine ! We might need to some debugging then. Can you confirm that "New Story Points" is exactly the name of the custom field, and that it is a Number field ?

Also, you do not need to redefine issue. Please update the script as : 

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

def newStoryPointsChanged = event?.getChangeLog()?.getRelated("ChildChangeItem")?.find {it.field == "New Story Points"}

log.error("newStoryPointsChanged : " + newStoryPointsChanged)
if (newStoryPointsChanged){
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def tgtField = customFieldManager.getCustomFieldObjectByName("Story Points")
def calcField = customFieldManager.getCustomFieldObjectByName("New Story Points")
def tgtFieldValue = issue.getCustomFieldValue(tgtField)
def calcFieldValue = issue.getCustomFieldValue(calcField)
log.error("tgtFieldValue : " + tgtFieldValue)
log.error("calcFieldValue : " + calcFieldValue)
tgtField.updateValue(null, issue, new ModifiedValue(tgtFieldValue, calcFieldValue),new DefaultIssueChangeHolder())
}

and provide the logs.

Antoine

Peter April 24, 2019

Hi @Antoine Berry 

First of all the Field is for sure "New Story Points" - but its not a Number field it is a Select List (Single Choice) - but there are only the fibonacci numbers available!

 

The Log ececuted with your code above is the following:

 

Time (on server): Wed Apr 24 2019 17:17:36 GMT+0200 (Central European Summer Time)

The following log information was produced by this execution. Use statements like:log.info("...") to record logging information.

2019-04-24 17:17:36,382 ERROR [runner.ScriptRunnerImpl]: newStoryPointsChanged : [newvalue:11212, field:New Story Points, oldstring:1, newstring:13, id:81418, fieldtype:custom, oldvalue:11207, group:72149]
2019-04-24 17:17:36,384 ERROR [runner.ScriptRunnerImpl]: tgtFieldValue : 2.0
2019-04-24 17:17:36,384 ERROR [runner.ScriptRunnerImpl]: calcFieldValue : 13
2019-04-24 17:17:36,388 ERROR [runner.AbstractScriptListener]: *************************************************************************************
2019-04-24 17:17:36,388 ERROR [runner.AbstractScriptListener]: Script function failed on event: com.atlassian.jira.event.issue.IssueEvent, file: <inline script>
java.lang.ClassCastException: com.atlassian.jira.issue.customfields.option.LazyLoadedOption cannot be cast to java.lang.Double
 at com.atlassian.jira.issue.customfields.impl.NumberCFType.getDbValueFromObject(NumberCFType.java:45)
 at com.atlassian.jira.issue.customfields.impl.AbstractSingleFieldType.updateValue(AbstractSingleFieldType.java:151)
 at com.atlassian.jira.issue.fields.ImmutableCustomField.updateValue(ImmutableCustomField.java:426)
 at com.atlassian.jira.issue.fields.ImmutableCustomField.updateValue(ImmutableCustomField.java:396)
 at com.atlassian.jira.issue.fields.OrderableField$updateValue.call(Unknown Source)
 at Script483.run(Script483.groovy:16)

 

Thank you so much for your help!

Really appreciate it!

Antoine Berry
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
April 24, 2019

Hi @Peter ,

it seems that your last comment has disappeared ? 

Antoine

Peter April 24, 2019

Hello @Antoine Berry ,

 

Thats true - strange!

So again:

The Field Name "New Story Points" is correct - but its no Number field -It is a Select List (Single Choice) - with only fibonacci (Integers) available.

 

The log produced with your code is as follows:

Time (on server): Wed Apr 24 2019 17:17:36 GMT+0200 (Central European Summer Time)

The following log information was produced by this execution. Use statements like:log.info("...") to record logging information.

2019-04-24 17:17:36,382 ERROR [runner.ScriptRunnerImpl]: newStoryPointsChanged : [newvalue:11212, field:New Story Points, oldstring:1, newstring:13, id:81418, fieldtype:custom, oldvalue:11207, group:72149]
2019-04-24 17:17:36,384 ERROR [runner.ScriptRunnerImpl]: tgtFieldValue : 2.0
2019-04-24 17:17:36,384 ERROR [runner.ScriptRunnerImpl]: calcFieldValue : 13
2019-04-24 17:17:36,388 ERROR [runner.AbstractScriptListener]: *************************************************************************************
2019-04-24 17:17:36,388 ERROR [runner.AbstractScriptListener]: Script function failed on event: com.atlassian.jira.event.issue.IssueEvent, file: <inline script>
java.lang.ClassCastException: com.atlassian.jira.issue.customfields.option.LazyLoadedOption cannot be cast to java.lang.Double
 at com.atlassian.jira.issue.customfields.impl.NumberCFType.getDbValueFromObject(NumberCFType.java:45)
 at com.atlassian.jira.issue.customfields.impl.AbstractSingleFieldType.updateValue(AbstractSingleFieldType.java:151)
 at com.atlassian.jira.issue.fields.ImmutableCustomField.updateValue(ImmutableCustomField.java:426)
 at com.atlassian.jira.issue.fields.ImmutableCustomField.updateValue(ImmutableCustomField.java:396)
 at com.atlassian.jira.issue.fields.OrderableField$updateValue.call(Unknown Source)
 at Script483.run(Script483.groovy:16)


 

And at last i wanted to thank you very much for your help.

hopefully there is a soloution =)

Really appreciate it!

Antoine Berry
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
April 24, 2019

Yes, there definitely is a solution, try this : 

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

def newStoryPointsChanged = event?.getChangeLog()?.getRelated("ChildChangeItem")?.find {it.field == "New Story Points"}

log.error("newStoryPointsChanged : " + newStoryPointsChanged)
if (newStoryPointsChanged){
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def tgtField = customFieldManager.getCustomFieldObjectByName("Story Points")
def calcField = customFieldManager.getCustomFieldObjectByName("New Story Points")
def tgtFieldValue = issue.getCustomFieldValue(tgtField)
def calcFieldValue = issue.getCustomFieldValue(calcField) == null ? null : (Double) issue.getCustomFieldValue(calcField).getValue()
log.error("tgtFieldValue : " + tgtFieldValue)
log.error("calcFieldValue : " + calcFieldValue)
tgtField.updateValue(null, issue, new ModifiedValue(tgtFieldValue, calcFieldValue),new DefaultIssueChangeHolder())
}

I have not tried it but it should do the trick.

Antoine

Like Peter likes this
Peter April 25, 2019

Hello  @Antoine Berry ,

 

Thank you so much!

This almost did it - however the cast didnt work properly (see log)

2019-04-25 09:19:59,242 ERROR [runner.ScriptRunnerImpl]: newStoryPointsChanged : [newvalue:11208, field:New Story Points, oldstring:13, newstring:2, id:81442, fieldtype:custom, oldvalue:11212, group:72173]
2019-04-25 09:19:59,243 ERROR [runner.ScriptRunnerImpl]: tgtFieldValue : 13.0
2019-04-25 09:19:59,243 ERROR [runner.ScriptRunnerImpl]: calcFieldValue : 50.0

 however, i only changed the "cast line" to the following, and it worked fine

def calcFieldValue = issue.getCustomFieldValue(calcField) == null ? null : issue.getCustomFieldValue(calcField).getValue().toDouble()

 

Thank you so much for your help!

Like Antoine Berry likes this
Antoine Berry
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
April 25, 2019

Glad to help ! :) Indeed this is a proper way to cast.

If you are satisfied with the answer please consider marking it as accepted.

Antoine

Rupa Jain April 19, 2020

Hi Antoine,

I am using Jira v8.6

I am getting an error when I try to use either:

org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '5' with class 'com.atlassian.jira.issue.customfields.option.LazyLoadedOption' to class 'java.lang.Double'
at Script151.run(Script151.groovy:22)

 

issue.getCustomFieldValue(calcField).getValue().toDouble()
OR
(Double)issue.getCustomFieldValue(calcField).getValue()

 

Any suggestions on how to fix this?

Also, looks like the function 'getValue' is no longer available.

 

Thanks,

Rupa

Suggest an answer

Log in or Sign up to answer