Forums

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

Custom Script Post-Function [ScriptRunner]

Almu September 10, 2021

Hi everyone,

I would appreciate if someone could shed light on this, please.

I am a groovy learner, and I need to fulfill this requirement:

There are 2 checkbox custom fields: cf1, cf2 used in several issuetypes

In Create transition, there is a postfunction that fills in cf1, depending on other custom field, so each issue has different cf1 values. 

The thing is that cf2 must be filled in with some values of cf1 that apply to that issue. That is:

when creating issue1, cf1 takes values: a,b,c,e. Then, cf2 checks a list, and takes b,c, because b,c are in that list.

when creating issue2, cf1 takes values: a,c,d. Then, cf2 checks a list, and takes c,d, because c,d are in that list.

The list depends on the issuetype, that is why I have decided to add a postfuntion in each workflow of each issuetype. This postfunction is placed after the postfunction to fill in cf1, and this is the code: 

 

import com.atlassian.jira.component.ComponentAccessor
def customFieldManager = ComponentAccessor.customFieldManager
def optionsManager = ComponentAccessor.optionsManager
def issueManager = ComponentAccessor.issueManager

def cf2 = customFieldManager.getCustomFieldObjectsByName("custom field 2")[0]
def cf1 = customFieldManager.getCustomFieldObjectsByName("custom field 1")[0]
def fieldConfig2 = cf2.getRelevantConfig(issue)
def options2 = optionsManager.getOptions(fieldConfig2)
def fieldConfig1 = cf1.getRelevantConfig(issue)
def options1 = optionsManager.getOptions(fieldConfig1)

for (x in options1) {
if (x == "b")
{
def optionsToSet = options2.findAll { it.value in ["b"] }
issue.setCustomFieldValue(cf2, optionsToSet)
}
if (x == "c")
{
def optionsToSet = options2.findAll { it.value in ["c"] }
issue.setCustomFieldValue(cf2, optionsToSet)

}
if (x == "d")
{
def optionsToSet = options2.findAll { it.value in ["d"] }
issue.setCustomFieldValue(cf2, optionsToSet)

}}

 

As I do not know how to compare options1 with a list, I have used "if" statements.

But it does not work. Any idea, please?

 

Thanks in advance.

Cheers,

Almu

 

1 answer

2 votes
Nic Brough -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 10, 2021

Welcome to the Atlassian Community!

You say "In Create transition, there is a postfunction that fills in cf1, depending on other custom field, [...] cf2 must be filled in with some values of cf1 that apply to that issue.".  This seems like a clear specification to me, but I just want to say that I am not 100% sure I am reading it right, so if anything in the rest of my answer seems to be looking at the wrong thing or answering the wrong question, please do tell me!

I'm going to imagine that you are aiming for:

  • Post-function 1: runs a script that does something simple like "set cf1 to 'badgers'"
  • Post-function 2: runs a script that looks at cf1 and if it sees 'badgers', sets cf2 to 'mushroom', and if cf1 is not 'badgers', sets cf2 to 'snake'
  • cf1 and cf2 are select-lists

The exact logic of what you are reading and setting is not too important, your script shows you know what you're doing with that.  I've just constructed a simplified scenario I can refer back to

Problem 1:

I think the problem here is, as you say, the "if":

for (x in options1) {
if (x == "b")
{

The for/in part is fine, options1 will contain a list of options, and x a single option but the x == "badgers" is going to false every time.  This is because an option is an option object, not a string.

I think what you probably want to do here is compare the name of the option, not the whole thing.  For my example, this would mean

for (x in options1) {
if ( "badgers".equals( x.getName() ) )
{

Note that I've used equals through force of habit, I'm more Java than Groovy and the "use .equals. not == when comparing strings" is a hard habit to break

Problem 2:

Depending on what is run and where, cf1 may not contain 'badgers' when you come to ask whether cf2 should be 'mushroom' or 'snake'

There's a long and complicated story about the timing cycles in here, but the actual fix is to think slightly differently when coding the second script.

Instead of 

  • Read cf1 and set cf2 from it

You code "defensively", assume cf1 is not set correctly, and do:

  • Work out what cf1 should be set to, and set cf2 from that
Almu September 13, 2021

Hi Nic,

Thank you so much for your swift reply, and your help. Very much appreciated :-)

As you suggested, I modified the code, so now:

for (x in options1) {
if ("b" == x.getValue())
{

and it works, but the thing is that the cf2 only gets the last value of the "for". As cf2 is a multicheckbox, it is necessary that every value, in "if" with true result, has to be selected. 

Any idea about how to append values, please?

Thanks again.

Cheers,

Almu

Nic Brough -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 13, 2021

For a multi-check-box, the options are contained in an collection (the value of cf2 is a collection of options, not a single option), and to use them, you'll need to iterate over them too.

To append values, you'll need to fetch the current value and add your new option(s) to it and then put the new collection back in the field.

Almu September 13, 2021

Hi Nic,

As I am a newbie to groovy, I do not know how to do what you say, but i am trying.

My new code does not do what I need :-(

import com.atlassian.jira.component.ComponentAccessor
def customFieldManager = ComponentAccessor.customFieldManager
def optionsManager = ComponentAccessor.optionsManager
def issueManager = ComponentAccessor.issueManager

def cf2 = customFieldManager.getCustomFieldObjectsByName("custom field 2")[0]
def cf1 = customFieldManager.getCustomFieldObjectsByName("custom field 1")[0]
def fieldConfig2 = cf2.getRelevantConfig(issue)
def options2 = optionsManager.getOptions(fieldConfig2)
def fieldConfig1 = cf1.getRelevantConfig(issue)
def options1 = optionsManager.getOptions(fieldConfig1)

def list = []

for (x in options1) {
if ("b" == x.getValue()) {
list.add(x.getValue())
}
if ("c" == x.getValue()){
list.add(x.getValue())
}
if ("d" == x.getValue()){
list.add(x.getValue())
}}

def optionsToSet = options2.findAll { it.value in list }
issue.setCustomFieldValue(cf2, optionsToSet)

 

The result is:

cf1 takes all values <-why?, I set cf2, not cf1 with ->issue.setCustomFieldValue(cf2, optionsToSet) 

cf1 must not change

 

As said, what i need it that cf2 takes only some values from cf1. And it worked when cf2 takes the value in the last "if", but I need to join all values with "if" equals true.

 

Any help is welcome, thanks a lot!

Suggest an answer

Log in or Sign up to answer