Forums

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

Script in Scripted field not updating custom field select list correctly, help!

Ross Lynsdale
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!
July 1, 2022

Using the following script I am calculating a result field with coloured HTML results that will display. However, as part of the same script I need it to populate another custom field so that JQL searches/dashboards etc can be searched on as there's a known issue using Scripted fields for JQL etc: 

The result means that my custom field "Overall RAG list" is populated, but not always with the correct option and my previously working "Overall RAG Status" is now blank. :(

Here's the 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.fields.ImmutableCustomField
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.IssueImpl
import org.apache.log4j.Logger
import org.apache.log4j.Level
import com.atlassian.jira.issue.customfields.manager.OptionsManager
import com.atlassian.jira.issue.customfields.option.Option
import com.atlassian.jira.issue.fields.config.FieldConfig
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.issue.CustomFieldManager

//Set initial RAG field score to nothing.
int overallRagField = 0;

//Defining all custom fields that the values will be used for scoring.
def qualityField = getCustomFieldValue('Quality RAG Status ');
def costField = getCustomFieldValue('Cost RAG Status ');
def timeField = getCustomFieldValue('Time RAG Status ');
def resourceField = getCustomFieldValue('Resource RAG Status ');
def riskField = getCustomFieldValue('Risk RAG Status ');
def technicalField = getCustomFieldValue('Technical RAG Status ');
def csatField = getCustomFieldValue('Customer Satisfaction RAG Status ');

//Debugging
log.setLevel(Level.DEBUG)

//Check to ensure all fields are NOT null.
if (qualityField == null || costField == null || timeField == null || resourceField == null || riskField == null || technicalField == null || csatField == null)
{
return null;
}
else
{

String result = "";
String colour = "";

//Calculate what the RAG score will be.
switch(qualityField) {
case "G":
overallRagField = overallRagField + 1
break;
case "A":
overallRagField = overallRagField + 2
break;
case "R":
overallRagField = overallRagField + 5
break;
}

switch(costField) {
case "G":
overallRagField = overallRagField + 1
break;
case "A":
overallRagField = overallRagField + 4
break;
case "R":
overallRagField = overallRagField + 8
break;
}

switch(timeField) {
case "G":
overallRagField = overallRagField + 1
break;
case "A":
overallRagField = overallRagField + 5
break;
case "R":
overallRagField = overallRagField + 10
break;
}

switch(resourceField) {
case "G":
overallRagField = overallRagField + 1
break;
case "A":
overallRagField = overallRagField + 2
break;
case "R":
overallRagField = overallRagField + 5
break;
}

switch(riskField) {
case "G":
overallRagField = overallRagField + 1
break;
case "A":
overallRagField = overallRagField + 2
break;
case "R":
overallRagField = overallRagField + 5
break;
}

switch(technicalField) {
case "G":
overallRagField = overallRagField + 1
break;
case "A":
overallRagField = overallRagField + 2
break;
case "R":
overallRagField = overallRagField + 5
break;
}

switch(csatField) {
case "G":
overallRagField = overallRagField + 1
break;
case "A":
overallRagField = overallRagField + 2
break;
case "R":
overallRagField = overallRagField + 5
break;
}

//Calculate RAG colour based on the RAG score
if (overallRagField < 9)
{
colour = "#0FFF00";
result = "G";
}
else
if (overallRagField >= 16)
{
colour = "#FF5555";
result = "R";
}
else
//if (overallRagField == 9||10||11||12||13||14||15)
{
colour = "#FF9E00";
result = "A";
}


log.debug "1"
MutableIssue issueToUpdate = (MutableIssue) issue;

//define the values you want to disable here
log.debug "2"
def optionsToSet = [result];

//to get the custom field, pass the custom field id
log.debug "3"
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def customField = customFieldManager.getCustomFieldObjectsByName("Overall RAG list")[0]

//get the custom field options
log.debug "4"
def optionsManager = ComponentAccessor.getOptionsManager()
def options = optionsManager.getOptions(customField.getRelevantConfig(issue))

log.debug "5"
//set options
options.each {
if(optionsToSet.contains(it.toString())){
log.debug "6"
log.info it.toString()
issueToUpdate.setCustomFieldValue(customField, it)
}
}


if(result != "")
{
return "<span style=\"font-weight: bold ; border: 1px solid grey; border-radius: 4px; padding: 0px 4px; background-color: " + colour + "\">" + result + "</span>";
}


}

1 answer

1 vote
PD Sheehan
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.
July 13, 2022

First, let me warn you that it's a BAAAD idea to attempt to perform a transaction (updating a field) on a scripted field script.

See, the script for your field is executed every time an issue is accessed. Every time a user refreshes a page. Every time the issue is returned in a REST api call. Every time the issue is re-indexed.

If you want a static version of your calculated value, create a scripted listener that will watch for a change in any of your RAG fields and update the overall calculated RAG field value accordingly. This will happen only when the issue changes.

But I think if you arrange your scripted field correctly, you can get it to store and index just the result value and use the script field template to render the correct color/style.

Looking at your code, I saw a lot of repetition that I felt could be greatly reduced.

Check this out:

import org.apache.log4j.Level

//Debugging
log.setLevel(Level.DEBUG)

def
ragFieldList = [
'Quality RAG Status',
'Cost RAG Status',
'Time RAG Status',
'Resource RAG Status',
'Risk RAG Status',
'Technical RAG Status',
'Customer Satisfaction RAG Status'
]

def
ragValues = ragFieldList.collect {
//I'll assume you have a function somewhere that does this
getCustomFieldValue(it)
}

//if any of the RAG field is empty, we don't calculate the score and exit early
if
(ragValues.any { it == null }) return null

def valueScoreMap = [G: 1, A: 2, R: 5]
def overallRagValue = ragValues.sum { valueScoreMap[it]}

//Return the appropriate RAG value based on the RAG score
if (overallRagValue < 9) return 'G'
if (overallRagValue >= 16) return 'R'
return 'A'

Now, if you setup a "Custom Template" for your field, you can have it like this:

#disable_html_escaping()
#if ($value != '')
#if ($value=='R')
#set ($color = "#FF5555")
#elseif ($value=='A')
#set ($color = "#FF9E00")
#elseif ($value=='G')
#set ($color = "#0FFF00")
#end
<span style="fond-weight:bold; border:1px solid grey; border-radius:4px: padding:0px 4px; background-color:$color">$value</span>
#else
<span/>
#end

And in your customfield configuration, change the Search Template to "Exact Text Searcher"

After you re-index, you should be able to access your field from the JQL and easily search for "Overall RAG" = R (and the R, A, ang G should appear as auto complete)

Now, this script will still run each time the issue are indexed or accessed, but at least it doesn't perform any writes to the db. It's purely read-only.

Suggest an answer

Log in or Sign up to answer