Forums

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

Stop creation of ticket with same custom field data

Caoimhin Caldwell
Contributor
December 21, 2022

Hi Guys,

 

Hoping you can help me on this one. I am looking for a way to basically meet the following 

 

Users try's to create ticket and fills duplicate data into a custom field which already exists in a separate ticket. Jira denies this ticket creation due to the duplicate field info

The existing ticket with that info transitions automatically to a new status.

 

Hopefully have explained that clearly, have Scriptrunner and JSU as plugins so can probably be achieved using that although im still sharpening my groovy skills

Regards

 

3 answers

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.
December 21, 2022

So it sounds like you are attempting the have the values in that custom field unique across all issues in the project. Is that correct?

What type of field if the custom field?

I see several aspects to this requirement

1) Behaviour

When the user fills in the custom field, create a JQL to search for other tickets matching the input. If nothing is found. All is good. If an issue is retrieved, set an error on the field with a link to the existing issue for the user to click on.

From there, the user might need to manually re-open that ticket.

2) Workflow Validator

Like behaviour, but will report the error only after the user attempts to submit. This will never happen from the UI if the behaviour is also setup, but it will catch anyone trying to use the rest api of some other non-standard ui.

What I would not recommend, is to have either the behaviour or the validator trigger a change in the existing issue. Validations should never trigger transactions elsewhere in the system.
Maybe the user just made a typo or other mistake. They may not really want that other issue to be re-opened.

I can help suggest some groovy script for the behaviour and validator if I'm on the right direction and you confirm the type of field (and searcher) that the custom field is.

Caoimhin Caldwell
Contributor
December 30, 2022

Hi Peter, 

 

Yes that’s correct . The field in question is type text field (single line) . From above I think you have the requirements spot on. The link wouldn’t be necessary as these tickets are coming in through an RPA bot. As long as the custom field having duplicate data and a ticket being created is stopped that is sufficient. The only thing I might reiterate is the 2nd point where if that happens the original ticket with the data is then moved to a status in workflow ( this is to highlight it needs to be looked at again hence why another ticket is trying to be logged with the same custom field id. It seems tricky to me but hopefully you could help. Really appreciate this 

Caoimhin Caldwell
Contributor
December 30, 2022

Oh and the custom field search template is free text searcher 

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

As I said, I think triggering the re-open on the original issue seems like a bad idea. Perhaps the user only made a typo in the custom field and I don't think you should automatically re-open the ticket that matched the typo. 

A script like this in a behaviour configuration for your project against the unique field's server-side script should get you close:

import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.web.bean.PagerFilter
import com.onresolve.jira.groovy.user.FieldBehaviours
import groovy.transform.BaseScript

@BaseScript FieldBehaviours fieldBehaviours

def uniqueFieldName = 'Unique Text Field'

def field = getFieldByName(uniqueFieldName)
field.clearError() //remove any prior errors

def inputValue = field.value as String // the value the user just typed

def jql = """project = $issueContext.projectObject.key and "$uniqueFieldName" like "$inputValue" """

def currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def searchService = ComponentAccessor.getComponent(SearchService)
def parseResult = searchService.parseQuery(currentUser, jql)

assert parseResult.valid , "The JQL ($jql) could not be parsed: $parseResult.errors"

if(searchService.searchCount(currentUser, parseResult.query)){
def issue = searchService.search(currentUser, parseResult.query, PagerFilter.unlimitedFilter).results.first()
def issueUrl = "$baseUrl/browse/$issue.key"
field.setError("""$inputValue has already been used on issue <a href="$issueUrl">$issue.key</a> if more work is needed, access that issue and re-open it.""")
}
Caoimhin Caldwell
Contributor
January 5, 2023

Thanks for that Peter I will give it a try and let you know how it goes . Just on the second part about triggering the transition . The issues in question I would want to transition wouldn’t actually be in a closed status, it would just be transitioning from one open status to another within the workflow . If the issue was indeed closed then it wouldn’t trigger a reopen . I was thinking if the logic was included to only transition if it’s on that open status else don’t run. Would this logic make more sense? I think this doesn’t affect anything then in terms of if some mistakes were made . Hopefully I’m making my point clear if not I can further explain . Really appreciate your help 

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

I would recommend we simply just adjust the error message based on the status of the found issue:

if(searchService.searchCount(currentUser, parseResult.query)){
def issue = searchService.search(currentUser, parseResult.query, PagerFilter.unlimitedFilter).results.first()
if(issue.resolution){
field.setError("""$inputValue has already been used on a closed issue: <a href="$issueUrl">$issue.key</a> """)
} else {
def issueUrl = "$baseUrl/browse/$issue.key"
field.setError("""$inputValue has already been used on issue <a href="$issueUrl">$issue.key</a>. Open this issue to apply transition X.""")
}
}

Basically, you want to have a clear intention from the users to trigger a transition, any transition. Normally, that's done by clicking a button, either a "submit" button on a form or a transition button on an issue view screen.

Triggering a transition based on typed text in a field is a bad idea.

Caoimhin Caldwell
Contributor
January 6, 2023

deleted

Caoimhin Caldwell
Contributor
January 6, 2023

For the text in a field is its actually a 6 figure ID so for example '235443' so it would be very unlikely a typo would occur there if that makes sense? Would you still advise against that as its really a key requirement for me

Caoimhin Caldwell
Contributor
January 6, 2023

@PD Sheehan If the above isn’t feasible could you add the code to do this which you outlined in your first response ?

 

“If an issue is retrieved, set an error on the field with a link to the existing issue for the user to click on.”

Thanks

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.
January 6, 2023

That is exactly what the code I provided in my previous comment does.

Caoimhin Caldwell
Contributor
January 10, 2023

Hi Peter,

 

I have placed the first code you gave in the behaviour and added the custom field against it but it is still allowing me to enter duplicate data when creating issue for that field, any possible reason ?

 

Thanks again

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.
January 10, 2023

Can you share a screenshot of the behaviour configuration page?

Caoimhin Caldwell
Contributor
January 10, 2023

Screenshots added

Caoimhin Caldwell
Contributor
January 10, 2023

.

Caoimhin Caldwell
Contributor
January 10, 2023

920271C2-EA79-4A71-BA3A-C21534D3BCDA.jpeg60243DD1-5DCB-48DE-B969-594B257E4161.jpegDE8955CF-A88C-4FF6-AC95-316264247AB5.jpeg 

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.
January 10, 2023

Can you review the atlassian-jira.log file for errors at the time that you attempted to update the Claim ID field?

Let's try to output some messages on the field to make it easier.

Replace the script with:

import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.web.bean.PagerFilter
import com.onresolve.jira.groovy.user.FieldBehaviours
import groovy.transform.BaseScript

@BaseScript FieldBehaviours fieldBehaviours

def showDebugMessage = true
def uniqueFieldName = 'Claim Id'

def field = getFieldByName(uniqueFieldName)
field.clearError() //remove any prior errors

def inputValue = field.value as String // the value the user just typed

def jql = """project = $issueContext.projectObject.key and "$uniqueFieldName" like "$inputValue" """

def currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def searchService = ComponentAccessor.getComponent(SearchService)
def parseResult = searchService.parseQuery(currentUser, jql)

if(!parseResult.valid){
field.setError("The JQL ($jql) could not be parsed: $parseResult.errors")
return
}

if(searchService.searchCount(currentUser, parseResult.query)){
def issue = searchService.search(currentUser, parseResult.query, PagerFilter.unlimitedFilter).results.first()
def issueUrl = "$baseUrl/browse/$issue.key"
if(issue.resolution){
field.setError("""$inputValue has already been used on a closed issue: <a href="$issueUrl">$issue.key</a> """)
} else {
field.setError("""$inputValue has already been used on issue <a href="$issueUrl">$issue.key</a>. Open this issue to apply transition X.""")
}
} else {
showDebugMessage && field.setHelpText("DEBUG: The search using JQL ($jql) returned no results when exececuted as $currentUser.name")
}
Caoimhin Caldwell
Contributor
January 10, 2023

Getting this error on the create screen 1842931B-92DC-49ED-90EA-C7FD147736F1.jpeg

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.
January 10, 2023

Ah!

Sorry, that was my mistake. I've been working with Assets AQL too much lately.

Let's try this:

import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.web.bean.PagerFilter
import com.onresolve.jira.groovy.user.FieldBehaviours
import groovy.transform.BaseScript

@BaseScript FieldBehaviours fieldBehaviours

def showDebugMessage = true
def uniqueFieldName = 'Claim Id'

def field = getFieldByName(uniqueFieldName)
field.clearError() //remove any prior errors

def inputValue = field.value as String // the value the user just typed

def jql = """project = $issueContext.projectObject.key and "$uniqueFieldName" ~ "$inputValue" """

def currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def searchService = ComponentAccessor.getComponent(SearchService)
def parseResult = searchService.parseQuery(currentUser, jql)

if(!parseResult.valid){
field.setError("The JQL ($jql) could not be parsed: $parseResult.errors")
return
}

if(searchService.searchCount(currentUser, parseResult.query)){
def issue = searchService.search(currentUser, parseResult.query, PagerFilter.unlimitedFilter).results.first()
def issueUrl = "$baseUrl/browse/$issue.key"
if(issue.resolution){
field.setError("""$inputValue has already been used on a closed issue: <a href="$issueUrl">$issue.key</a> """)
} else {
field.setError("""$inputValue has already been used on issue <a href="$issueUrl">$issue.key</a>. Open this issue to apply transition X.""")
}
} else {
showDebugMessage && field.setHelpText("DEBUG: The search using JQL ($jql) returned no results when exececuted as $currentUser.name")
}
Caoimhin Caldwell
Contributor
January 10, 2023

Amazing ! That’s working , final question , any good resources/websites to share to get to this level of groovy scripting ? Really impressive , thanks again Peter !

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.
January 10, 2023

I'm completely self-thought. 

But the main resources I use are

1) This site. There are many great examples in various posts.

2) The groovy documentation 

3) The jira javadocs (almost everything starts with the component accessor)

4) The scriptrunner documentation

5) The adaptavist library

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.
January 11, 2023

If you only need to run a script during issue creation, you can do that easily by checking to see if there is an "underlyingIssue".

When we are creating an issue, that variable is empty.

So add, near the top:

//if the is an underlying issue, we're not in in a create screen. Nothing to do
if
(underlyingIssue) return null
0 votes
Caoimhin Caldwell
Contributor
January 11, 2023

Hi Peter, 

 

I found one issue with this , when you click edit on an issue with this now it shows this message and gives the link to the same ticket so there is no way to actually edit and close an issue now . Is there anyway to only have this behaviour happen on the create screen ?

 

Thanks

0166D6B7-AAA5-422C-8032-F30691B2EE3E.jpeg

0 votes
Caoimhin Caldwell
Contributor
January 5, 2023

@PD Sheehan would you be able to help on this ? Much appreciated 

Suggest an answer

Log in or Sign up to answer