Run JQL Search and Create Subtasks based on User Picker CF (PostFunction)

Richard Duffy
Contributor
December 15, 2020

HI Everyone

Scriptrunner version - 6.15.0

Jira Version - 8.11.0

Method - Post Function - Custom Script Function

Custom Field - Tempo Validator (User picker single)

JQL Query - project = TEMPO

Goal ->

I want to create a subtask on the issue which triggers the post-funtion based off the JQL query result. 

For example - Lets say the JQL query result has 5 tickets, each of these tickets has a custom field called Tempo Validator which is a single user picker type (Or I can use multi user)

So based on this example the postfunction will create 5 sub-task which will be assigned to the values of the Tempo Validators from the JQL query

 

I have below experimenting with below code but need some help to get this working 

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.search.SearchProvider
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.jql.parser.JqlQueryParser
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.user.ApplicationUser


def jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser.class)
def searchProvider = ComponentAccessor.getComponent(SearchProvider.class)
def issueManager = ComponentAccessor.getIssueManager()
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()

// The search query
def query = jqlQueryParser.parseQuery("project = TEMPO")

// Results from query
def results = searchProvider.search(query, user, PagerFilter.getUnlimitedFilter())

// Get the custom field that you want to update
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def customField = customFieldManager.getCustomFieldObjectByName("Tempo Validator")

Collection<ApplicationUser> users= (Collection) issue.getCustomFieldValue(customField);

if(users != null)
{
for(i in 0..users.size()-1)
{
Object AssigneeValue = users.get(i).getKey()
;

issueObject = ComponentAccessor.getIssueFactory().getIssue()
issueObject.setProjectObject(issue.getProjectObject())
issueObject.setIssueTypeId("10003") //id of subtask
issueObject.setParentId(issue.getId())
issueObject.setSummary(issue.getSummary() + ' ' + users.get(i).getDisplayName() + ' - Assessment')
issueObject.setFixVersions(issue.getFixVersions())
issueObject.setAssigneeId(AssigneeValue)
def subTask = issueManager.createIssueObject(ComponentAccessor.jiraAuthenticationContext.getLoggedInUser(), issueObject)
ComponentAccessor.subTaskManager.createSubTaskIssueLink(issue, subTask, ComponentAccessor.jiraAuthenticationContext.getLoggedInUser())
i++
}
}

Thanks in advance

Richard

2 answers

1 accepted

Suggest an answer

Log in or Sign up to answer
0 votes
Answer accepted
Peter-Dave 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 15, 2020

You mention PostFunction. This is normally something that happens on a single issue.

I don't understand what role your query results play in your script.

Can you elaborate on your goal a bit more?

Are we creating subtasks on the issue that triggered the postfunction? Or on all issues returned by the JQL?

0 votes
Richard Duffy
Contributor
December 15, 2020

Hi @Peter-Dave Sheehan 

I want to create a subtask on the issue which triggers the post-funtion based off the JQL query result. 

For example - Lets say the JQL query result has 5 tickets, each of these tickets has a custom field called Tempo Validator which is a single user picker type (Or I can use multi user)

So based on this example the postfunction will create 5 sub-task which will be assigned to the values of the Tempo Validators from the JQL query

Hope that makes more sense

Thanks

Richard

*updated summary to make it more clear

Peter-Dave 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 16, 2020

You could try something like the following that should work whether the custom field is a single or multi-user picker. If it's a multi, a subtask will be created for each user selected in the custom field.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.bc.issue.search.SearchService
//managers
def searchService = ComponentAccessor.getComponent(SearchService)
def issueManager = ComponentAccessor.issueManager
def customFieldManager = ComponentAccessor.customFieldManager

//some general variables
def tempoValidatorCf= customFieldManager.getCustomFieldObjectsByName('Tempo Validator')[0]
def currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser

//a closure to create the subtask for a given user
def createSubTaskForUser = {ApplicationUser user->
def subTask = ComponentAccessor.issueFactory.issue
subTask.projectObject = issue.projectObject
subTask.issueTypeId = "10003"
subTask.parentId =issue.id
subTask.summary = "$issue.summary $user.displayName - Assessment"
subTask.assignee = user
def subTaskIssue = issueManager.createIssueObject(currentUser, subTask)
ComponentAccessor.subTaskManager.createSubTaskIssueLink(issue, subTaskIssue, currentUser)
}

// The search query
def jql ="project = TEMPO"

def jqlParseResult = searchService.parseQuery(currentUser,jql)
if(jqlParseResult.isValid()){
// Results from query
def results = searchService.search(currentUser, jqlParseResult.query,PagerFilter.getUnlimitedFilter())
//look through each result, load the issue, get the cf value, create sub-tasks
results.results.each{indexIssue->
def filterIssue = issueManager.getIssueObject(indexIssue.id)
def tempoValidatorValue = filterIssue.getCustomFieldValue(tempoValidatorCf)
if(tempoValidatorValue instanceof ApplicationUser){
//this is the case when the customfield is a single-user-picker
createSubTaskForUser(tempoValidatorValue)
} else {
//for multi-user, we'll create a subtask for each selected users
tempoValidatorValue.each{ApplicationUser user-> createSubTaskForUser(user)}
}
}
}
Richard Duffy
Contributor
December 17, 2020

Hi @Peter-Dave Sheehan 

Thank you so much this works very well!

One requirement I forgot was to have the subtask names have the same summary as the JQL tickets + Assignee + Text

So lets say the JQL has 1 ticket with summary "Project Connect" and Assignee "Bill"

The subtask summary would be something like ->

Project Connect - Bill - Validation Task

 

 

Thanks

Richard

Richard Duffy
Contributor
January 10, 2021

Hi @Peter-Dave Sheehan 

I haven't been able too get the summary part working, can you help?

Thanks

Richard 

Peter-Dave 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, 2021

You could try it like this:


import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.bc.issue.search.SearchService
//managers
def searchService = ComponentAccessor.getComponent(SearchService)
def issueManager = ComponentAccessor.issueManager
def customFieldManager = ComponentAccessor.customFieldManager

//some general variables
def tempoValidatorCf= customFieldManager.getCustomFieldObjectsByName('Tempo Validator')[0]
def currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser

//a closure to create the subtask for a given user using an issue (sourceIssue) from the JQL search below
def createSubTaskForUser = {Issue sourceIssue, ApplicationUser user->
   def subTask = ComponentAccessor.issueFactory.issue
   subTask.projectObject = issue.projectObject //this issue is the one where the postfunction is running on
   subTask.issueTypeId = "10003"
   subTask.parentId =issue.id
   subTask.summary = "$sourceIssue.summary $user.displayName - Assessment"
   subTask.assignee = user
   def subTaskIssue = issueManager.createIssueObject(currentUser, subTask)
   ComponentAccessor.subTaskManager.createSubTaskIssueLink(issue, subTaskIssue, currentUser)
}

// The search query
def jql ="project = TEMPO"

def jqlParseResult = searchService.parseQuery(currentUser,jql)
if(jqlParseResult.isValid()){
   // Results from query
   def results = searchService.search(currentUser, jqlParseResult.query,PagerFilter.getUnlimitedFilter())
   //look through each result, load the issue, get the cf value, create sub-tasks
   results.results.each{indexIssue->
      def filterIssue = issueManager.getIssueObject(indexIssue.id)
    def tempoValidatorValue = filterIssue.getCustomFieldValue(tempoValidatorCf)
if(tempoValidatorValue instanceof ApplicationUser){
//this is the case when the customfield is a single-user-picker
createSubTaskForUser(filterIssue, tempoValidatorValue)
} else {
//for multi-user, we'll create a subtask for each selected users
tempoValidatorValue.each{ApplicationUser user-> createSubTaskForUser(filterIssue,user)}
}
}
}

I added a parameter to the closure that created the sub-task to be able to pass the issue from the JQL currently being processed and then use that issue's summary as part of the new sub-task summary. 

Richard Duffy
Contributor
January 11, 2021

Awesome thanks so much @Peter-Dave Sheehan ! It works well.

TAGS
AUG Leaders

Atlassian Community Events