Groovy set single select customfield

Kristian Koniarz November 23, 2020

Dear community,

I wrote a script which will set an single select field to an specific value in dependency to the condition. I already studied other community entries which referred to the same problem. Unfortunately non of them seems to have a usable answer, at least for me.

Please do not look how clean the code is. Its a test and I may added to to much unneeded libraries, during the attempt to solve the problem. The problem I got is that Jira / Groovy seems not to know the method to finally set the single select field.

 

 

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.customfields.option.Options
import com.atlassian.jira.issue.customfields.manager.OptionsManager
import com.atlassian.jira.issue.CustomFieldManager

// Set CustomFieldManager
def customFieldManager = ComponentAccessor.getCustomFieldManager()
// Set IssueManager
def issueManager = ComponentAccessor.getIssueManager()
// Set UserManager
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

def optionsManager = ComponentAccessor.getOptionsManager()

def customField = customFieldManager.getCustomFieldObjectByName("Grenzwert")
def config = customField.getRelevantConfig(issue)
def options = optionsManager.getOptions(config)
def optionGruen = options.find { it.value == "<span class='status-macro aui-lozenge aui-lozenge-success'>grün</span>" }
def optionGelb = options.find { it.value == "<span class='status-macro aui-lozenge aui-lozenge-success'>grün</span>" }
def optionRot = options.find { it.value == "<span class='status-macro aui-lozenge aui-lozenge-success'>grün</span>" }

def ausfallzeit = customFieldManager.getCustomFieldObjectByName("Ausfallzeit")

def system = customFieldManager.getCustomFieldObjectByName("Betroffenes System")
def myIssue = issue

// grün
if ( ausfallzeit <= 15 && ( system == "NetApp Filer" || system == "VMWare" || system == "Internet" )) {
customField.setFormValue(optionGruen.optionId)
} else if ( ( ausfallzeit > 15 && ausfallzeit <= 30 ) && ( system == "IVIS" || system == "Oracle" || system == "MS SQL" )) {
customField.setFormValue(optionGruen.optionId)
// gelb
} else if ( ( ausfallzeit > 30 && ausfallzeit <= 60 ) && ( system == "NetApp Filer" || system == "VMWare" || system == "Internet")) {
customField.setFormValue(optionGelb.optionId)
} else if ( ( ausfallzeit > 60 && ausfallzeit <= 120 ) && ( system == "IVIS" || system == "Oracle" || system == "MS SQL" )) {
customField.setFormValue(optionGelb.optionId)
// rot
} else if ( ( ausfallzeit > 60 && ausfallzeit <= 120) && ( system == "NetApp Filer" || system == "VMWare" || system == "Internet")) {
customField.setFormValue(optionRot.optionId)
} else if ( ausfallzeit > 120 && ( system == "IVIS" || system == "Oracle" || system == "MS SQL")) {
customField.setFormValue(optionRot.optionId)
}

// Updates the issue without additional activity entries
issueManager.updateIssue(user, issue, EventDispatchOption.DO_NOT_DISPATCH, false)

 

1 answer

1 accepted

0 votes
Answer accepted
Hana Kučerová
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
November 23, 2020

Hi @Kristian Koniarz ,

when exactly do you want to execute this script? Is it a post function?

I believe, there are two main problems now:

  • the variable "system" is not string (it's com.atlassian.jira.issue.fields.CustomField), it is not possible to compare it with string
  • there is no such method as setFormValue for custom field in this context (this method is used in behaviours with com.onresolve.jira.groovy.user.FormField)

Please look at this script, it could help you to finish your code.

Kristian Koniarz November 23, 2020

Hi @Hana Kučerová

Thanks a lot for your hints.

Yes its a post function. I got less errors meanwhile but the last line seems not to work.

Further it was necessary to add "...first().getRelevantConfig(issue))" in availableOptions. 

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

// the name of the custom field (single select list type)
final customFieldName = "Grenzwert"

// the value of the new option to set
final newValue = "<span class='status-macro aui-lozenge aui-lozenge-success'>grün</span>"

// the issue key to update
final issueKey = "UHD-1297"

def issue = ComponentAccessor.issueManager.getIssueByCurrentKey(issueKey)
assert issue: "Could not find issue with key $issueKey"

def customField = ComponentAccessor.customFieldManager.getCustomFieldObjectsByName(customFieldName)
assert customField: "Could not find custom field with name $customFieldName"

def availableOptions = ComponentAccessor.optionsManager.getOptions(customField.first().getRelevantConfig(issue))

def optionToSet = availableOptions.find { it.value == newValue }
assert optionToSet: "Could not find option with value $newValue. Available options are ${availableOptions*.value.join(",")}"

customField.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(customField), optionToSet), new DefaultIssueChangeHolder())

Best,

Kristian

Kristian Koniarz November 24, 2020

Hi @Hana Kučerová

I am almost through. Do you know how to use the setValue function for single select fields? The API documentation is not really helpful, at least for me.

I receive all options with

def value = ComponentAccessor.optionsManager.getOptions(cfConfig)
return value

But how to set a value?

Best,

Kristian

Hana Kučerová
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
November 24, 2020

Hi @Kristian Koniarz ,

which types your custom fields with names Grenzwert, Ausfallzeit and Betroffenes System have?

It seems to me, that:

  • Grenzwert = Select List (Single Choice)
  • Ausfallzeit = Number field
  • Betroffenes System = Select List (Single Choice)

I will try to improve your original code, but I need to know the types to handle the custom fields correctly. Thank you.

Kristian Koniarz November 24, 2020

Hi @Hana Kučerová

Thanks for your reply.

  • Grenzwert (threshold) is an single select yes
  • Ausfallzeit (downtime) is an number yes
  • Betroffenes System (affected system) is an multi select

I only need to automatically set Grenzwert, the rest must be done manually for now.

I may found the problem, which implicates it would never work. Could it be that I need to set / manipulate behaviour of those fields with third party apps like Scriptrunner before I can actually set them?

I only have "MyGroovy" installed, seems those app wouldn´t do the job.

Best,

Kristian

Hana Kučerová
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
November 25, 2020

Hi @Kristian Koniarz ,

something like this could work for you, please try. I've tested with MyGroovy and it worked, but I didn't test it much. You need to insert it as a post function to your workflow. It assumes that Ausfallzeit and Betroffenes System custom fields are already set in the issue. The script get the values of these two fields and based on them set the third one, Grenzwert.

I'm not sure what you mean by "I need to set / manipulate behaviour of those fields with third party apps like Scriptrunner before I can actually set them?"

Both applications (ScriptRunner and MyGroovy) enables you to add some groovy scripts to your Jira. ScriptRunner has many, many more functionalities, but the basic one is the same.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.customfields.option.Options
import com.atlassian.jira.issue.customfields.manager.OptionsManager
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.issue.fields.config.FieldConfig
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.customfields.option.Option

final String limitCustomFieldName = "Grenzwert"
final String downTimeCustomFieldName = "Ausfallzeit"
final String affectedSystemCustomFieldName = "Betroffenes System"
final String limitOptionGreenValue = "grün"
final String limitOptionYellowValue = "gelb"
final String limitOptionRedValue = "rot"
final List<String> affectedSystemsList1 = ["NetApp Filer", "VMWare", "Internet"]
final List<String> affectedSystemsList2 = ["IVIS", "Oracle", "MS SQL"]

MutableIssue issue = issue
CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager()
OptionsManager optionsManager = ComponentAccessor.getOptionsManager()

// get custom fields
CustomField limitCustomField = customFieldManager.getCustomFieldObjectsByName(limitCustomFieldName).first()
CustomField downTimeCustomField = customFieldManager.getCustomFieldObjectsByName(downTimeCustomFieldName).first()
CustomField affectedSystemCustomField = customFieldManager.getCustomFieldObjectsByName(affectedSystemCustomFieldName).first()

// get config for limit custom field
FieldConfig customFieldConfig = limitCustomField.getRelevantConfig(issue)
Options options = optionsManager.getOptions(customFieldConfig)

// get possible options for affected system custom field
Option optionGreen = options.find { it.value == limitOptionGreenValue }
Option optionYellow = options.find { it.value == limitOptionYellowValue }
Option optionRed = options.find { it.value == limitOptionRedValue }

// get current custom fields values
Option limitOption = issue.getCustomFieldValue(limitCustomField) as Option
Double downTime = issue.getCustomFieldValue(downTimeCustomField) as Double
List<Option> affectedSystemOptions = issue.getCustomFieldValue(affectedSystemCustomField) as List<Option>
List<String> affectedSystems = affectedSystemOptions.collect {Option affectedSystem ->
affectedSystem.getValue()
}

if (affectedSystems.size() > 0 && downTime > 0) {
// try to find the option based on the current custom field values
Boolean oneOfSystemsIsInList1 = affectedSystems.any { affectedSystemsList1.contains(it) }
Boolean oneOfSystemsIsInList2 = affectedSystems.any { affectedSystemsList2.contains(it) }
Option newLimitOption
if ( (downTime <= 15 && oneOfSystemsIsInList1) || (downTime > 15 && downTime <= 30 && oneOfSystemsIsInList2) ) {
newLimitOption = optionGreen
} else if ( (downTime > 30 && downTime <= 60 && oneOfSystemsIsInList1) || (downTime > 60 && downTime <= 120 && oneOfSystemsIsInList2) ) {
newLimitOption = optionYellow
} else if ( (downTime > 60 && downTime <= 120 && oneOfSystemsIsInList1) || (downTime > 120 && oneOfSystemsIsInList2) ) {
newLimitOption = optionRed
}
// if we've found the option, set it to limit custom field
if (newLimitOption) {
limitCustomField.updateValue(null, issue, new ModifiedValue(limitOption, newLimitOption), new DefaultIssueChangeHolder())
}
}
Like # people like this
Kristian Koniarz November 25, 2020

Hello @Hana Kučerová

Let me take the opportunity to thank you for your time and effort your invest to help me.

I implemented your code as a post function, lucky us no syntax error or similar but unfortunately also not working after the first attempt. I am receiving the error below, which I can´t understand. Because each created list was initialised by you.

Cannot access first() element from an empty List

Further I did a quick test and removed the .first() for limit and downTime initialisation, to utilize the deprecated method.

CustomField limitCustomField = customFieldManager.getCustomFieldObjectByName(limitCustomFieldName)
CustomField downTimeCustomField = customFieldManager.getCustomFieldObjectByName(downTimeCustomFieldName)
CustomField affectedSystemCustomField = customFieldManager.getCustomFieldObjectsByName(affectedSystemCustomFieldName).first()

So I did another try with those changes and received a null pointer exception. Seems to be harder as I thought to implement such a easy post function.

Regarding the behaviours which I mentioned before, i was talking about those. As several community threads containing a similar question and all of them got it done with the help of scriptrunner and setting behaviours.

https://scriptrunner.adaptavist.com/5.3.9/jira/behaviours-overview.html

Best,

Kristian

Hana Kučerová
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
November 25, 2020

Hi @Kristian Koniarz ,

the error you mention is about not beeing able to find your custom field(s).

Please check the names of custom fields used in the config section of the script, if they are correct.

Alternatively you can replace

CustomField limitCustomField = customFieldManager.getCustomFieldObjectsByName(limitCustomFieldName).first()

with 


CustomField limitCustomField = customFieldManager.getCustomFieldObject("customfield_10400")

where 10400 needs to be replaced with the correct id of your customfield. 

Same thing could be done for all the three customfields. It is better to use id instead of names, because these ids don't change in time and they are unique.

About the second part. It depends on your use case. Behaviours typicall use case looks like this: when I edit my issue and change two fields, I want another one to became mandatory and prepopulated with some value. But the user needs to store these values manually. You've mentioned, that you need to set the value of select list during transition. So I thought your use case is: values of my two custom fields were already stored in the issue, I need to set the third one based on them after some transition (without the interaction with user).

Like Kristian Koniarz likes this
Kristian Koniarz November 25, 2020

Hello @Hana Kučerová 

It worked with the ID´s.

Thanks so much, you definitely made my day.

Best,

Kristian

Harsh
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.
April 4, 2023

Hi @Hana Kučerová 

I m using JIRA 8.2 Server and I have a similar requirement, I have a customfield (Single select) with 3 values [high, low, med]. 
I want to set the value of the customfield (single select) to HIGH, when I go from Open to In Progress. 

Can you please help with this. I did try the solution  and modified above solution but no luck


Thanks!

Hana Kučerová
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 5, 2023

Hi @Harsh ,

I recommend you to create a new question, also please share your code. Thank you.

Harsh
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.
April 5, 2023

Hi @Hana Kučerová 

 

Thank you for your reply. I actually figured out. There was a small error from my end. I was using the wrong class to get custom field options. Used option manager and called the options and set it. So it worked and works now. 

Much appreciate for.your reply.

Thanks!

Like Hana Kučerová likes this

Suggest an answer

Log in or Sign up to answer