I have a custom user picker field on both the parent and sub-task. When a sub-task is created, I would like to copy the user specified in the parent task to the same field in the sub-task. The field is called "Projektleiter".
I tried using the example in the ScriptRunner documentation but it doesn't work. Here's what I have.
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.customfields.option.Option
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.web.util.OutlookDate
import com.atlassian.jira.web.util.OutlookDateManager
import com.onresolve.jira.groovy.user.FieldBehaviours
import com.onresolve.jira.groovy.user.FormField
import groovy.transform.BaseScript
import java.sql.Timestamp
import static com.atlassian.jira.issue.IssueFieldConstants.*
@BaseScript FieldBehaviours fieldBehaviours
FormField field = getFieldById(getFieldChanged())
FormField parent = getFieldById("parentIssueId")
Long parentIssueId = parent.getFormValue() as Long
if (!parentIssueId || field.getFormValue()) {
// this is not a subtask, or the field already has data
return
}
def issueManager = ComponentAccessor.getIssueManager()
def parentIssue = issueManager.getIssueObject(parentIssueId)
def customFieldManager = ComponentAccessor.getCustomFieldManager()
OutlookDate outlookDate = ComponentAccessor.getComponent(OutlookDateManager).getOutlookDate(Locale.getDefault())
// REMOVE OR MODIFY THE SETTING OF THESE FIELDS AS NECESSARY
getFieldById(COMPONENTS).setFormValue(parentIssue.componentObjects*.id)
// IF YOU DON'T WANT CUSTOM FIELDS COPIED REMOVE EVERYTHING BELOW HERE
// IF YOU ONLY WANT SOME FIELDS INHERITED ADD THEM TO THE LIST BELOW, OR LEAVE EMPTY FOR ALL
// eg ['Name of first custom field', 'Name of second custom field']
List copyCustomFields = ['Projektleiter']
List<CustomField> parentFields = customFieldManager.getCustomFieldObjects(parentIssue)
for (def cf in parentFields) {
if (copyCustomFields && !copyCustomFields.contains(cf.name)) {
return
}
def parentValue = cf.getValue(parentIssue) as List<Option>
if (!parentValue) {
return
}
getFieldById(cf.id).setFormValue(parentValue)
log.debug("parentValue: ${parentValue?.class} for type ${cf.name}")
if (parentValue instanceof Timestamp) {
getFieldById(cf.id).setFormValue(outlookDate.formatDMY(parentValue))
} else if (parentValue instanceof Option) {
getFieldById(cf.id).setFormValue(parentValue.optionId)
} else if (parentValue instanceof List && parentValue[0] instanceof Option) {
getFieldById(cf.id).setFormValue(parentValue*.optionId)
} else {
getFieldById(cf.id).setFormValue(parentValue)
}
}
Maybe it's different for a user field. Can somebody help?
Thanks and BR.
The value of a user picker field is not List<Option>. You have to use ApplicationUser as class. Or List<ApplicationUser> if it's a multi user picker.
def parentValue = cf.getValue(parentIssue) as ApplicationUser
The part including and below if (parentValue instanceof Timestamp) { can be removed.
Best,
Henning
Hi Henning
Thanks for your help so far.
After adding "as ApplicationUser", I get the error "Unable to resolve class ApplicationUser". The field is only a single user picker.
Do I have to import something maybe for it to work?
Thanks and BR
Marius
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Yes, you have to import the ApplicationUser class.
import com.atlassian.jira.user.ApplicationUser
Henning
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Ok, I took a look at the original script and I think there is only one thing missing for handling user fields. I added it to the script:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.customfields.option.Option
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.web.util.OutlookDate
import com.atlassian.jira.web.util.OutlookDateManager
import com.onresolve.jira.groovy.user.FieldBehaviours
import com.onresolve.jira.groovy.user.FormField
import groovy.transform.BaseScript
import java.sql.Timestamp
import static com.atlassian.jira.issue.IssueFieldConstants.*
@BaseScript FieldBehaviours fieldBehaviours
FormField field = getFieldById(getFieldChanged())
FormField parent = getFieldById("parentIssueId")
Long parentIssueId = parent.getFormValue() as Long
if (!parentIssueId || field.getFormValue()) {
// this is not a subtask, or the field already has data
return
}
def issueManager = ComponentAccessor.getIssueManager()
def parentIssue = issueManager.getIssueObject(parentIssueId)
def customFieldManager = ComponentAccessor.getCustomFieldManager()
// REMOVE OR MODIFY THE SETTING OF THESE FIELDS AS NECESSARY
getFieldById(SUMMARY).setFormValue(parentIssue.summary)
getFieldById(PRIORITY).setFormValue(parentIssue.getPriorityObject().id)
OutlookDate outlookDate = ComponentAccessor.getComponent(OutlookDateManager).getOutlookDate(Locale.getDefault())
getFieldById(DUE_DATE).setFormValue(outlookDate.formatDMY(parentIssue.getDueDate()))
getFieldById(COMPONENTS).setFormValue(parentIssue.componentObjects*.id)
getFieldById(AFFECTED_VERSIONS).setFormValue(parentIssue.affectedVersions*.id)
getFieldById(FIX_FOR_VERSIONS).setFormValue(parentIssue.fixVersions*.id)
getFieldById(ASSIGNEE).setFormValue(parentIssue.assigneeId)
getFieldById(ENVIRONMENT).setFormValue(parentIssue.environment)
getFieldById(DESCRIPTION).setFormValue(parentIssue.description)
getFieldById(SECURITY).setFormValue(parentIssue.securityLevelId)
getFieldById(LABELS).setFormValue(parentIssue.labels)
// IF YOU DON'T WANT CUSTOM FIELDS COPIED REMOVE EVERYTHING BELOW HERE
// IF YOU ONLY WANT SOME FIELDS INHERITED ADD THEM TO THE LIST BELOW, OR LEAVE EMPTY FOR ALL
// eg ['Name of first custom field', 'Name of second custom field']
List copyCustomFields = []
List<CustomField> parentFields = customFieldManager.getCustomFieldObjects(parentIssue)
for (def cf in parentFields) {
if (copyCustomFields && !copyCustomFields.contains(cf.name)) {
return
}
def parentValue = cf.getValue(parentIssue)
if (!parentValue) {
return
}
log.debug("parentValue: ${parentValue?.class} for field ${cf.name}")
if (parentValue instanceof Timestamp) {
getFieldById(cf.id).setFormValue(outlookDate.formatDMY(parentValue as Timestamp))
} else if (parentValue instanceof Option) {
getFieldById(cf.id).setFormValue((parentValue as Option).optionId)
} else if (parentValue instanceof List && parentValue[0] instanceof Option) {
getFieldById(cf.id).setFormValue((parentValue as List<Option>)*.optionId)
} else if (parentValue instanceof ApplicationUser) {
getFieldById(cf.id).setFormValue((parentValue as ApplicationUser).name)
} else {
getFieldById(cf.id).setFormValue(parentValue)
}
}
I think setting a user field via setFormValue() has to use the username (ApplicationUser.name) and not the ApplicationUser object.
Please make your changes and try it again.
Best regards,
Henning
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
There was a small error in the last if condition.
I removed that particular else if part because I think it's not necessary for my case and then saved the script. However, when I opened the parent task and clicked on Create Sub-Task the field Projektleiter is still empty.
I also noticed that the assignee has not been set either. Summary, Components, Priority and Due Date have been successfully set. Not that I necessarily want the assignee to be set. I just think it's suspicious that both user fields seem to have issues.
BR
Marius
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Do you see DEBUG messages in the atlassian-jira.log? If not could you try to add
import org.apache.log4j.Level
log.setLevel(Level.DEBUG)
to the code at the beginning and try again.
Henning
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I've added both lines and also this one.
log.debug("--------------------This is to test Behaviours Logging----------------")
Unfortunately, this test message is the only debug message I'm able to find in the log file after trying to create a sub-task.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Mmh, so we need more debug messages. Try before both return statements.
Is the customfield name correct? Maybe translated?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Added:
log.debug("1. Return")
and
log.debug("2. Return")
After testing, I can see the message "1. Return" in the log file. However, I tried commenting out these to if conditions before and it wouldn't copy the user either way. But still odd that it enters the first if condition.
The name is correct. It's in German.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I know, I'm a native German speaker. My question was because if the user has a different language selected and the customfield is translated, it may not match.
Nevertheless let's try to see what the list of customfields of the parent issue contains. Please add
log.debug "ParentFields: ${parentFields*.name}"
after List<CustomField> parentFields = customFieldManage... and try again.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Ah, I see. We're currently not working with translations. Everything is usually in German.
Here's the log message.
ParentFields: [Beobachter, Checkliste, Hide Comment Field, Kasse, Lieferant(en) & Partner, Projektleiter, issueFunction]*.name
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
For every field besides Projektleiter there should be a "1. Return" debug message.
Please change log.debug("1. Return") to
log.debug("1. Return: $cf.name")
and add
log.debug "ParentValue: $parentValue"
below def parentValue = cf.getValue(parentIssue).
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I think we got it!
After applying your changes:
--------------------This is to test Behaviours Logging----------------
ParentFields: [Beobachter, Checkliste, Hide Comment Field, Kasse, Lieferant(en) & Partner, Projektleiter, issueFunction]*.name
1. Return: Beobachter
I then tried and replaced the return statement with 'continue':
--------------------This is to test Behaviours Logging----------------
ParentFields: [Beobachter, Checkliste, Hide Comment Field, Kasse, Lieferant(en) & Partner, Projektleiter, issueFunction]*.name
1. Return: Beobachter
1. Return: Checkliste
1. Return: Hide Comment Field
1. Return: Kasse
1. Return: Lieferant(en) & Partner
ParentValue: VollrathM(vollrathm)
parentValue: class com.atlassian.jira.user.DelegatingApplicationUser for field Projektleiter
1. Return: issueFunction
The field is now filled correctly! :)
What do you think? Is this the correct way?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Yes! That's easy (as always :-)).
Someone changed the source in the documentation.. in version 5.0.7 it's using "parentFields.each { CustomField cf ->" instead of the for loop (since v5.0.8 of the documentation). Within each{} a "return" leaves the closure only for one element. In a for loop it has nothing special to say, so it leaves the script...
I normaly don't use for loops so I didn't catched it :-) Well done!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I filed a bug at Adaptavist.
Is the assignee working now?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I think it has to be
getFieldById(ASSIGNEE).setFormValue(parentIssue.assignee?.name)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Henning
Unfortunately, the assignee still does not work. However, since my original post is solved, I'll go ahead and mark your answer as accepted :)
Thank you again for your support. I'm glad we got it working.
BR
Marius
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I would like to add to your script one if before options
if (parentValue instanceof List && ((List)parentValue)[0] instanceof ApplicationUser) {
getFieldById(cf.id).setFormValue((parentValue as List<Option>)*.name)
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.