/
Support for ScriptRunner script

Support for ScriptRunner script

Customer Requirement

I need of a method to get ApprovalMappings object and then  related approval users and approval groups to populate an User Picker(Multiple) Custom Field and a Group Picker(Multiple) Custom Field.

Solution

  • Create the Custom fields that will be populated when the workflow transition runs:

  • Navigate on Workflow associated to the Approval Mapping
  • Add a Script Post-Function [ScriptRunner] and select Custom script post-function

  • Insert the Groovy Script code into the in-line editor, Save and Publish the workflow:
import com.atlassian.activeobjects.external.ActiveObjects
import com.atlassian.crowd.embedded.api.Group
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.issuetype.IssueType
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.project.Project
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.plugin.PluginAccessor

import com.opensymphony.workflow.loader.ActionDescriptor

import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.herzum.jira.plugin.approval.manager.impl.ApprovalServiceManagerImpl
import com.herzum.jira.plugin.approval.config.ao.Approval
import com.herzum.jira.plugin.approval.config.ao.ApprovalMapping

@WithPlugin("com.herzum.jira.plugin.approval.herzum-approval-plugin")

def workflow = ComponentAccessor.workflowManager.getWorkflow(issue.projectObject.id, issue.issueType.id)
def actions = workflow.getAllActions()
def cfApprovalGroups = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectsByName("Approval Groups").first()
def cfApprovalUsers = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectsByName("Approval Users").first()

List<ApprovalMapping> approvalMappings = getApprovalMapping(issue.projectObject.id, issue.issueType.id)

List<String> workflowStatusesIds = []
workflow.linkedStatusObjects.each {
    workflowStatusesIds.add(it.id)
}

List<ApprovalMapping> toRemove = []
approvalMappings.each {
	if (!workflowStatusesIds.contains(it.destinationStatusId) || it.isDelete) {
		toRemove.add(it)
	}
}
approvalMappings.removeAll(toRemove)

String strApprovalGroups = ""
String strApprovalUsers = ""

for (ApprovalMapping approvalMapping: approvalMappings) {
    Long mappedProjectId = approvalMapping.projectId
    Long mappedIssueTypeId = Long.valueOf(approvalMapping.issueTypeId)
    Long mappedTransitionId = Long.valueOf(approvalMapping.transitionId)
    ActionDescriptor mappedAction = getActionById(actions, mappedTransitionId)
    
    if (approvalMapping.sourceStatusId.equals(issue.status.id.toString())) {
        String mappedProjectName = ComponentAccessor.projectManager.getProjectObj(mappedProjectId).name
        String mappedIssueTypeName = getIssueTypeById(ComponentAccessor.projectManager.getProjectObj(mappedProjectId), mappedIssueTypeId).name
        Approval[] approvals = approvalMapping.approvals

        for (Approval approval : approvals) {
            if (!approval.groups.isEmpty()) {
                strApprovalGroups += ", " + approval.groups.replaceAll("&", ", ")
            }
            if (!approval.users.isEmpty()) {
                strApprovalUsers += ", " + approval.users.replaceAll("&", ", ")
            }
        }

        if (!strApprovalGroups.isEmpty() && strApprovalGroups.startsWith(", ")) {
            strApprovalGroups = strApprovalGroups.substring(2)
        }

        if (!strApprovalUsers.isEmpty() && strApprovalGroups.startsWith(", ")) {
            strApprovalUsers = strApprovalUsers.substring(2)
        }

        List<Group> approvalGroups = (List<Group>) issue.getCustomFieldValue(cfApprovalGroups)
        List<ApplicationUser> approvalUsers = (List<ApplicationUser>) issue.getCustomFieldValue(cfApprovalUsers)

        if (approvalGroups == null) {
            approvalGroups = []
        }
        
        if (approvalUsers == null) {
            approvalUsers = []
        }
        
        if (!strApprovalGroups.isEmpty()) {
            // removed space becouse it caused Custom field population failure
            strApprovalGroups.split(",").each {
                approvalGroups.add(ComponentAccessor.groupManager.getGroup(it.toString()))
            }
        }

        if (!strApprovalUsers.isEmpty()) {
            strApprovalUsers.split(", ").each {
                approvalUsers.add(ComponentAccessor.userManager.getUserByName(it.toString()))
            }
        }
        
        cfApprovalGroups.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(cfApprovalGroups), approvalGroups), new DefaultIssueChangeHolder())
        cfApprovalUsers.updateValue(null, issue, new ModifiedValue(issue.getCustomFieldValue(cfApprovalUsers), approvalUsers), new DefaultIssueChangeHolder())
    }
}

public List getApprovalMapping(Long projectId, String issueTypeId) {
    def approvalServiceManager = ComponentAccessor.getOSGiComponentInstanceOfType(ApprovalServiceManagerImpl.class);     
    ApprovalMapping[] approvals = (ApprovalMapping[])  approvalServiceManager.getApprovalMappings().findAll {
        it.projectId == projectId && it.issueTypeId.equals(issueTypeId)
    }.toArray()
    if (approvals.length > 0)
        return new ArrayList(Arrays.asList(approvals)); 
    return new LinkedList();
}

public IssueType getIssueTypeById(Project project, Long issueTypeId) {
    return project.issueTypes.find { it.id.toString().equals(issueTypeId.toString()) }
}

public IssueType getIssueTypeByName(Project project, String issueTypeName) {
    return project.issueTypes.find { it.name.equals(issueTypeName) }
}

public ActionDescriptor getActionById(Collection<ActionDescriptor> actions, Long id) {
    return actions.find { it.id.toString().equals(id.toString()) }
}

How it works

Assuming the following Requested Approvals:

On transitioning the issue, the Approval Groups and Approval Users Custom fields are populated automatically with the Users and the Groups configured as requested Approvals:

In this section

Related Documentation

Here you can find some links to our customer documentation relating to the configuration screens and other items described in this page:

Still need help?

We would love to help.

Related content

Multiple approval requests within an issue based on variable input
Multiple approval requests within an issue based on variable input
More like this
Approval mapping for team-managed projects
Approval mapping for team-managed projects
More like this
Combine user picker field and groups to come up with a single list of valid approvers
Combine user picker field and groups to come up with a single list of valid approvers
More like this
Autopopulate user picker field based on expression
Autopopulate user picker field based on expression
More like this
Approvals Administration
Approvals Administration
More like this