Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

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

Richard Duffy 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
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
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 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
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
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 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 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
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
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 January 11, 2021

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

TAGS
AUG Leaders

Atlassian Community Events