Can I use single select cascading custom field to get risk index?

Vedat Ozdemirler May 13, 2022

Hi All,

I am trying to calculate risk index by setting likelyhood and impact values in a single select cascading custom field. How can I get this calculation with scriptrunner?

example:

likelyhood values are in parent: 1-improbable, 2-unlikely, 3-occasional, 4-Probable, 5-Frequent

Impact values are in child for each: 1-Negligible, 2-Minor, 3-Major, 4-Critical

Risk Index = Parent * Child (Serious >10, High>6, Medium>2, Low<=2)

1 answer

1 accepted

0 votes
Answer accepted
Ram Kumar Aravindakshan _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.
May 14, 2022

Hi @Vedat Ozdemirler

For your requirement, you should use the Scripted Field.

Below is a sample working code for your reference:-

import com.atlassian.jira.component.ComponentAccessor

def customFieldManager = ComponentAccessor.customFieldManager
def cascadeField = customFieldManager.getCustomFieldObjectsByName('Sample Cascade').first()
def cascadeFieldValue = issue.getCustomFieldValue(cascadeField) as Map

def parentMap = ['Improbable':1, 'Unlikely':2, 'Occasional':3, 'Probable':4, 'Frequent':5]
def childMap = ['Negligible':1, 'Minor':2, 'Major':3, 'Critical':4]

def parentValue = parentMap.get(cascadeFieldValue.values().first().toString()) as Integer

def childValue = childMap.get(cascadeFieldValue.values().last().toString()) as Integer

def result = (parentValue * childValue) as Integer

if (result > 10) {
'Serious'
} else if (result > 6 && result <= 10) {
'High'
} else if (result > 2 && result <= 6) {
'Medium'
} else if (result <= 2) {
'Low'
}

Please note that the sample working code above is not 100% exact to your environment. Hence, you will need to make the required modifications.

Below is a screenshot of the Scripted Field's configuration:-

scripted_field_configuration.png

The screenshot above shows that the Scripted Field type used Custom Script Field, and the Template used is Text-Field (multi-line).

Below are a few test screens for your information:-

1) Improbable and Negligible options were selected from the cascading list when the issue was first created. As a result, the Risk Index scripted field is updated to Low as shown below:-

test1.png

2) When the cascading field options are then updated to Occasional and Major, the Risk Index Scripted Field is accordingly updated to High, as shown below:-

test2.png

3) Accordingly, when the Cascading field options are updated to Frequent and Critical, the Risk Index Scripted Field is updated to Serious, as shown below:-

test3.png

I hope this helps to answer your question. :)

Thank you and Kind regards,

Ram 

Vedat Ozdemirler May 16, 2022

Hi Ram,

Thank you for your support. After I adjusted the script for my instance, I get the following error.

java.lang.NullPointerException: Cannot invoke method multiply() on null object
at Script1749.run(Script1749.groovy:14)

2022-05-16 07:15:23,400 ERROR [customfield.GroovyCustomField]: *************************************************************************************
2022-05-16 07:15:23,400 ERROR [customfield.GroovyCustomField]: Script field failed on issue: NBPP-244, field: Unused
java.lang.NullPointerException: Cannot invoke method multiply() on null object
at Script1749.run(Script1749.groovy:14)

 

Ram Kumar Aravindakshan _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.
May 16, 2022

Hi @Vedat Ozdemirler

Can you please share your updated code and also a screenshot of the scripted field configuration you are adding this to?

Thank you and Kind regards,

Ram

Vedat Ozdemirler May 16, 2022

Hi Ram

Here are the code and screenshot you requested.

 

import com.atlassian.jira.component.ComponentAccessor

def customFieldManager = ComponentAccessor.customFieldManager

def cascadeField = customFieldManager.getCustomFieldObjectsByName('zztestrbt').first()

def cascadeFieldValue = issue.getCustomFieldValue(cascadeField) as Map

def parentMap = ['Improbable':1, 'Unlikely':2, 'Occasional':3, 'Probable':4, 'Frequent':5]

def childMap = ['Negligible':1, 'Marginal':2, 'Critical':3, 'Catastrophic':4]

def parentValue = parentMap.get(cascadeFieldValue.values().first().toString()) as Integer

def childValue = childMap.get(cascadeFieldValue.values().last().toString()) as Integer

def result = (parentValue * childValue) as Integer

if (result > 10) {

   'Serious'

} else if (result > 6 && result <= 10) {

    'High'

} else if (result > 2 && result <= 6) {

    'Medium'

} else if (result <= 2) {

    'Low'

}

 

Error on Preview:

java.lang.NullPointerException: Cannot invoke method multiply() on null object at Script1749.run(Script1749.groovy:14)
An error occurred, the field will have no value

image.png

Ram Kumar Aravindakshan _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.
May 16, 2022

Hi @Vedat Ozdemirler

After comparing the error message to the code that you have shared, it appears that the error is coming from this line:-

def result = (parentValue * childValue) as Integer

I can confirm that the NullPointerException is returned because you have only selected one option from the cascading list, i.e. the parent and nothing is selected from the child.

You need to select from both the parent and child list for the calculation to work correctly.

Below is an updated version of the sample code:-

import com.atlassian.jira.component.ComponentAccessor

def customFieldManager = ComponentAccessor.customFieldManager
def cascadeField = customFieldManager.getCustomFieldObjectsByName('Sample Cascade').first()
def cascadeFieldValue = issue.getCustomFieldValue(cascadeField) as Map

def parentMap = ['Improbable':1, 'Unlikely':2, 'Occasional':3, 'Probable':4, 'Frequent':5]
def childMap = ['Negligible':1, 'Minor':2, 'Major':3, 'Critical':4]

if (cascadeFieldValue) {
def parentValue = parentMap.get(cascadeFieldValue.values().first().toString()) as Integer
def childValue = childMap.get(cascadeFieldValue.values().last().toString()) as Integer

if (parentValue == null || childValue == null) {
return
} else {
def result = (parentValue * childValue) as Integer

if (result > 10) {
'Serious'
} else if (result > 6 && result <= 10) {
'High'
} else if (result > 2 && result <= 6) {
'Medium'
} else if (result <= 2) {
'Low'
}
}
}

Please note that the sample working code above is not 100% exact to your environment. Hence, you will need to make the required modifications.

If you observe in the updated code, I have added two if / else conditions to determine whether any value has been selected from the cascading field.

Next, if either the parent or child cascading list is empty, it will implicitly return nothing, and Scripted Field will not be displayed when the issue is created or edited.

Only when both parent and child values are set from the cascading field will the calculation take effect and return the result in the Scripted Field.

I hope this helps to answer your question. :)

Thank you and Kind regards,

Ram

Vedat Ozdemirler May 16, 2022

Hi Ram,

Thank you for the updates. It seems that I am getting null for values regardless of what I select on the cascading field. Would it be possible to get the values for that field using the custom field ID (customfield_12004) instead of the name?

Here are the custom field details.

image.png

image.png

Regards,

Vedat

Ram Kumar Aravindakshan _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.
May 16, 2022

Hi @Vedat Ozdemirler

In the updated code that you shared earlier, you appear to be invoking the field as 

def cascadeField = customFieldManager.getCustomFieldObjectsByName('zztestrbt').first()

i.e., the field name is set to 'zztestrbt'.

However, in the screenshot you shared, the field name appears to be RBT Rating.

Hence, could you please try to modify the field name to match RBT Rating, i.e.

import com.atlassian.jira.component.ComponentAccessor

def customFieldManager = ComponentAccessor.customFieldManager
def cascadeField = customFieldManager.getCustomFieldObjectsByName('RBT Rating').first()
def cascadeFieldValue = issue.getCustomFieldValue(cascadeField) as Map

def parentMap = ['Improbable':1, 'Unlikely':2, 'Occasional':3, 'Probable':4, 'Frequent':5]
def childMap = ['Negligible':1, 'Minor':2, 'Major':3, 'Critical':4]

if (cascadeFieldValue) {
def parentValue = parentMap.get(cascadeFieldValue.values().first().toString()) as Integer
def childValue = childMap.get(cascadeFieldValue.values().last().toString()) as Integer

if (parentValue == null || childValue == null) {
return
} else {
def result = (parentValue * childValue) as Integer

if (result > 10) {
'Serious'
} else if (result > 6 && result <= 10) {
'High'
} else if (result > 2 && result <= 6) {
'Medium'
} else if (result <= 2) {
'Low'
}
}
}

and test it once again. 

If this still fails, then yes, you can modify the code and try to invoke the field according to the custom field id instead.

I hope this helps to answer your question. :)

Thank you and Kind regards,

Ram

Vedat Ozdemirler May 16, 2022

Hi Ram,

I wanted to get a clean start and deleted the zztestrbt cascading field and zzrbtindex custom script field then I created new RBT Values cascading field and RBT Rating custom script field with below code. This is still giving me null return and RBT Rating is not displayed on my selected screens.

 

import com.atlassian.jira.component.ComponentAccessor

def customFieldManager = ComponentAccessor.customFieldManager
def cascadeField = customFieldManager.getCustomFieldObjectsByName('RBT Values').first()
def cascadeFieldValue = issue.getCustomFieldValue(cascadeField) as Map

def parentMap = ['Improbable':1, 'Unlikely':2, 'Occasional':3, 'Probable':4, 'Frequent':5]
def childMap = ['Negligible':1, 'Marginal':2, 'Critical':3, 'Catastrophic':4]

if (cascadeFieldValue) {
    def parentValue = parentMap.get(cascadeFieldValue.values().first().toString()) as Integer
    def childValue = childMap.get(cascadeFieldValue.values().last().toString()) as Integer

    if (parentValue == null || childValue == null) {
            return
        } else {
            def result = (parentValue * childValue) as Integer

           
if (result > 10) {
               'Serious'
            } else if (result > 6 && result <= 10) {
                'High'
            } else if (result > 2 && result <= 6) {
                'Medium'
            } else if (result <= 2) {
                'Low'
            }
        }
}
Ram Kumar Aravindakshan _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.
May 16, 2022

Hi @Vedat Ozdemirler

Could you please provide the error that you are getting in the atlassian-jira.log file when you try to test the code?

Also, can you confirm if you have more than one field with the name RBT Values? If yes, then you should use the custom field id instead of the field name.

Thank you and Kind regards,

Ram

Vedat Ozdemirler May 16, 2022

Hi Ram,

After adding some log.warn lines and tracing the values, I have figured out my mistake and corrected the script. It is working now. I appreciate your support.

I have one more question: How can I display the RBT Rating in color or highlight?

Regards,

Vedat

Ram Kumar Aravindakshan _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.
May 20, 2022

Hi @Vedat Ozdemirler

To answer your question, if you want to colour the scripted field, you should try something like this:-

import com.atlassian.jira.component.ComponentAccessor

def customFieldManager = ComponentAccessor.customFieldManager
def cascadeField = customFieldManager.getCustomFieldObjectsByName('Sample Cascade').first()
def cascadeFieldValue = issue.getCustomFieldValue(cascadeField) as Map

def parentMap = ['Improbable':1, 'Unlikely':2, 'Occasional':3, 'Probable':4, 'Frequent':5]
def childMap = ['Negligible':1, 'Minor':2, 'Major':3, 'Critical':4]

if (cascadeFieldValue) {
def parentValue = parentMap.get(cascadeFieldValue.values().first().toString()) as Integer
def childValue = childMap.get(cascadeFieldValue.values().last().toString()) as Integer

if (parentValue == null || childValue == null) {
return
} else {
def result = (parentValue * childValue) as Integer

if (result > 10) {
"<font color= '#FF0707'><b>Serious</b></font>"
} else if (result > 6 && result <= 10) {
"<font color= '#E58818'><b>High</b></font>"
} else if (result > 2 && result <= 6) {
"<font color= '#ffe32e'><b>Medium</b></font>"
} else if (result <= 2) {
"<font color= 'green'><b>Low</b></font>"
}
}
}

The HTML parameters added to the results will change the colour of the field based on the result.

Some print screens for your reference:-

image1.pngimage2.pngimage3.pngimage4.png

I hope this helps to solve your question. :)

Thank you and Kind regards,

Ram

Like Vedat Ozdemirler likes this
Vedat Ozdemirler May 22, 2022

Thank you very much.

Suggest an answer

Log in or Sign up to answer