[Script Runner] Could we choose which fields get copied from parent in a listener


We a custom field called 'Number of stories'. It is a select list, with the values 1,2,3,4 and 5. It is set on epics.

We created a listener that whenever a somebody choose a value for this field, the same number of stories are created as issues in epic for that epic.

The code is below:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.issue.IssueEvent
import com.onresolve.scriptrunner.canned.jira.utils.ConditionUtils
import com.onresolve.scriptrunner.canned.jira.utils.CopyIssueWithAttachments
import com.onresolve.scriptrunner.canned.jira.workflow.postfunctions.CreateSubTask
import com.onresolve.scriptrunner.canned.jira.workflow.postfunctions.CloneIssue
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.issuetype.IssueType
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.workflow.JiraWorkflow
import com.atlassian.jira.config.StatusManager
import com.atlassian.jira.config.DefaultStatusManager
import com.atlassian.jira.issue.status.Status
import com.atlassian.jira.issue.customfields.option.Option

def changeItems = event.getChangeLog().getRelated("ChildChangeItem")?.find {it.field == "Number of Stories"}
def issueTypes = ComponentAccessor.getConstantsManager().getAllIssueTypeObjects();
def issueManager = ComponentAccessor.getIssueManager();
MutableIssue issue = (MutableIssue)event.issue
ApplicationUser user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def numberOfStoriesField = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName('Number of Stories')
def numberOfStories = issue.getCustomFieldValue(numberOfStoriesField).toString().toInteger()
def linkManager = ComponentAccessor.getIssueLinkManager()
def index = 1
IssueType type = null
for (issueType in issueTypes)
if(issueType.getName() == "Story")
type = issueType

for (index =1; index <= numberOfStories; index++)
MutableIssue newIssue = (MutableIssue)createIssue(issue, user, type)
newIssue.summary = "[Story" +index.toString()+"]" + newIssue.summary
issueManager.updateIssue(user, newIssue, EventDispatchOption.DO_NOT_DISPATCH, false)
def sprint = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName('Sprint')
newIssue.setCustomFieldValue(sprint, null)
issueManager.updateIssue(user, newIssue, EventDispatchOption.DO_NOT_DISPATCH, false)
if(issue.getIssueType().getName() == 'Epic')
def epicLink = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName('Epic Link')
newIssue.setCustomFieldValue(epicLink, issue)
issueManager.updateIssue(user, newIssue, EventDispatchOption.DO_NOT_DISPATCH, false)
linkManager.createIssueLink(issue.getId(), newIssue.getId(),(Long)10003,(Long)1,user)
newIssue.description = issue.description
issueManager.updateIssue(user, newIssue, EventDispatchOption.DO_NOT_DISPATCH, false)

if(issue.getIssueType().getName() == 'Problem Report' && issue.getStatus().getName() == 'Working')
def optionsManager = ComponentAccessor.getOptionsManager()
def phaseField = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName('CA Phase')
def stateField = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName('CA State')
Option phaseOption = optionsManager.getOptions(phaseField.getRelevantConfig(issue)).getOptionForValue("Realize",null);
Option stateOption = optionsManager.getOptions(stateField.getRelevantConfig(issue)).getOptionForValue("I50_Design_Defined",null);
def aux = ComponentAccessor.getIssueManager().getIssueByCurrentKey(issue.getKey())
issueManager.updateIssue(user, aux, EventDispatchOption.DO_NOT_DISPATCH, false)
issueManager.updateIssue(user, aux, EventDispatchOption.DO_NOT_DISPATCH, false)

issue.setCustomFieldValue(numberOfStoriesField, null)
issueManager.updateIssue(user, issue, EventDispatchOption.DO_NOT_DISPATCH, false)

def createIssue(Issue issue,ApplicationUser user, IssueType type)
def issueManager = ComponentAccessor.getIssueManager()
def params = [
issue : issue,
(CloneIssue.FIELD_TARGET_PROJECT) : issue.getProjectObject().getKey(),
checkLink = {link->false}
checkAttachment = {a -> a.filename.endsWith(".txt")}

def aux = new CopyIssueWithAttachments().doScript(params)
StatusManager statusManager = ComponentAccessor.getComponentOfType(StatusManager.class)
String status = ""
if(issue.getProjectObject().getKey() != 'HW')
status = "10600"
status = "10800"
Status statusObject = statusManager.getStatus(status)
MutableIssue newIssue = ComponentAccessor.getIssueManager().getIssueObject(aux.newIssue.toString())
issueManager.updateIssue(user, newIssue, EventDispatchOption.ISSUE_UPDATED, false)
JiraWorkflow workflow = ComponentAccessor.getWorkflowManager().getWorkflow(issue.getProjectObject().getId(), type.getId())
ComponentAccessor.getWorkflowManager().migrateIssueToWorkflow(newIssue, workflow,statusObject )
issueManager.updateIssue(user, newIssue, EventDispatchOption.ISSUE_UPDATED, false)
return newIssue

What we would like to ask is if this can be changed somehow so that we can choose which fields are copied to the story from the epic.
More exactly, the assignee gets copied, and also some fields referring to the Definition of Done for the Epic, which are not at all relevant for the story.
We currently delete these values from the story by purging them at creation via a post function, but that removes the values whenever somebody manually creates an issue (or via CSV).

Thank you.


1 answer

0 votes


It depends on how flexible you want it to be. For example, you could add a select list with options which would mean a copy template. I mean suppose you have a select list called Template. Then you provide options there like Template1, Template2, Template2. Then in your listener you analyze the Template field together with the Number of stories field. If Template1 is chosen then you copy, for example, only assignee, if Template2 then you copy Assignee and the summary field and so on.

Suggest an answer

Log in or Sign up to answer
Community showcase
Published Feb 07, 2019 in Marketplace Apps

A Timeless Love Story

It started as any story starts, on a normal, rainy day.   Admin meets App, and her name was Klok2, and like any first relationship we were both trying to make it work but neither one knew what...

445 views 8 26
Read article

Atlassian User Groups

Connect with like-minded Atlassian users at free events near you!

Find a group

Connect with like-minded Atlassian users at free events near you!

Find my local user group

Unfortunately there are no AUG chapters near you at the moment.

Start an AUG

You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs

Groups near you