Hello and thank you in advance. I have been seeing many similar answered questions but none of the suggested scripts were able to be parsed in ScriptRunner Console. Especially when adding EventDispatchOption class for being able to execute issueManager.issueUpdate().
The goal is listen to a change in one or more of these fields: Original Estimate, "Start Date" and "Target End" (the last two are custom fields)
Since both custom fields are a date picker and the oEstimate isn't I fail to run simple math operations such as minus() and plus().
I wanted to do something like this:
I only have ScriptRunner. (Automation plugin requires Pro edition that we don't have)
Hi @Noam Tal -- Welcome to the Atlassian Community!
As a reminder, the Atlassian Community is not a free labor pool to implement requests.
Instead when you have a question, please show what you have already done to try to solve a problem (including any images/information of your solution attempts), describe the challenges you are facing, and describe what assistance you are seeking.
When you find you regularly have needs for complicated solutions for Atlassian tools and do not know where to start, I recommend talking to your team about learning more through study / experimentation and hiring a full time Jira administrator.
Kind regards,
Bill
Hire admin like me, for example :)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Fair enough, as I am rather new to ScriptRunner scripting, and this was my first question I didn't know what are the dos or don't.
I was able to create several items already, but didn't know why in so many cases 'issue' was showing as not declared.
@Evgenii , I am actually rolling this idea out.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Noam Tal
In your description, you mentioned:-
Hello and thank you in advance. I have been seeing many similar answered questions but none of the suggested scripts were able to be parsed in ScriptRunner Console.
From what you have described, you are trying to copy the Listener or Post-Function code into the ScriptRunner console and run it directly. Please confirm.
If this is the case, it will implicitly fail. When using a Listener or Post-Functions, the editor has bound variables such as event or issue; through which you can invoke the project or other variables.
However, in the ScriptRunner console, this is not doable. It is a barebone editor to which you must first declare the variables. The only variable that is bound to the ScriptRunner console is the log variable to do logging.
Could you please share the sample code that you have tested with so I can provide a better solution.
Thank you and Kind regards,
Ram
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Ram Kumar Aravindakshan _Adaptavist_ Thanks much for this input.
I am trying to create a listener that listens to an update event.
I have got several insights about that and I am in a mood to try fiddling that on my own for a bit. I'll share my code later on.
Thanks again
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi, @Noam Tal
Can you add more details about 3 and 4 points from your list? What calculations are needed there?
I understood 2 first points, and can make script for them, but 3 and 4 are still unclear
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks Evgeniy for reaching out.
In bullet #3, I can see now why it was not understood. this case does not require changing the oEstimate of course :)
The use case is when an item was planned to start on a DATE but after a few days we realized that it can actually start 10 days later, I would like to update the targetEnd and keep the oEstimate
In bullet #4, there are many occasions where a developer needs more days to work on an item. In those cases, then the targetEnd date is changed, meaning that the gap between startDate has grown. I thought it would make sense to update the oEstimate accordingly
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Ok, understood. I'll make a draft today
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Noam Tal made draft, adapt it to your environment
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Evgeniy,
That is so awesome that you could assist so quickly!
I have a few questions,
Lastly, there was a problem running it due to this error in line 43:
[Static type checking] - Cannot assign value of type java.lang.Object to variable of type com.atlassian.greenhopper.service.sprint.Sprint
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
It's very strange, I'm sure I posted answer and my post disappeared. I'll repeat it tomorrow.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
1. No, it's entry from change item , that contains information about field, that was changed. It looks like:
[[GenericEntity:ChangeItem][newvalue,288000][field,timeoriginalestimate][oldstring,144000][newstring,288000][id,10106][fieldtype,jira][oldvalue,144000][group,10102]]
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Changed way of getting issue sprint, added some validators:
/*
* Created 2023.
* @author Evgeniy Isaenkov
* @github https://github.com/Udjin79/SRUtils
*/
package Examples.Listeners
import com.atlassian.greenhopper.service.sprint.Sprint
import com.atlassian.greenhopper.service.sprint.SprintIssueService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.issue.index.IssueIndexingService
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.user.util.UserManager
import com.onresolve.scriptrunner.runner.customisers.JiraAgileBean
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import java.sql.Timestamp
@WithPlugin('com.pyxis.greenhopper.jira')
@JiraAgileBean
SprintIssueService sprintIssueService
IssueManager issueManager = ComponentAccessor.getIssueManager()
CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager()
UserManager userManager = ComponentAccessor.getUserManager()
IssueIndexingService issueIndexingService = ComponentAccessor.getComponent(IssueIndexingService)
// Configuring main variables
def changeItem = event.changeLog.getRelated("ChildChangeItem")
MutableIssue issue = issueManager.getIssueObject(event.getIssue().id) as MutableIssue
Sprint sprint
// Configuring service user, which will make changes
ApplicationUser user = userManager.getUserByName("serviceAccount")
// Configuring date string format, which we receive in change data
String formatPattern = "yyyy-MM-dd'T'HH:mm:ssZ"
List fieldNames = ["timeoriginalestimate", "Start Date", "Target End"]
if (changeItem['field'] && changeItem['field'].first() in fieldNames) {
String fieldName = changeItem['field'].first()
// set ID's of your custom fields
CustomField startDate = customFieldManager.getCustomFieldObject(11111)
CustomField targetEnd = customFieldManager.getCustomFieldObject(11112)
Long startDateValue = (issue.getCustomFieldValue(startDate) as Timestamp).getTime()
Long targetEndValue = (issue.getCustomFieldValue(targetEnd) as Timestamp).getTime()
def sprintData = sprintIssueService.getActiveSprintForIssue(user, issue)
if (sprintData) {
sprint = sprintData.getValue().first()
}
Long originalEstimate = issue.getOriginalEstimate()
if (sprint && (!startDateValue || !targetEndValue)) {
issue.setCustomFieldValue(startDate, sprint.getStartDate().getMillis())
issue.setCustomFieldValue(targetEnd, sprint.getEndDate().getMillis())
issue.setOriginalEstimate((targetEndValue - startDateValue) / 1000 as Long)
}
if (startDateValue && targetEndValue && originalEstimate && fieldName == "Start Date") {
Long changeOld = (Date.parse(formatPattern, (String) changeItem['oldvalue'].first()) as Date).getTime()
Long changeNew = (Date.parse(formatPattern, (String) changeItem['newvalue'].first()) as Date).getTime()
Long diff = changeNew - changeOld
issue.setCustomFieldValue(targetEnd, targetEndValue + diff)
}
if (startDateValue && targetEndValue && originalEstimate && fieldName == "Target End") {
Long changeOld = (Date.parse(formatPattern, (String) changeItem['oldvalue'].first()) as Date).getTime()
Long changeNew = (Date.parse(formatPattern, (String) changeItem['newvalue'].first()) as Date).getTime()
Long diff = changeNew - changeOld
issue.setOriginalEstimate(issue.originalEstimate + (diff / 1000) as Long)
}
if (!originalEstimate && startDateValue && targetEndValue) {
issue.setOriginalEstimate((targetEndValue - originalEstimate) / 1000 as Long)
}
issueManager.updateIssue(user, issue, EventDispatchOption.DO_NOT_DISPATCH, false)
issueIndexingService.reIndex(issue)
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Evgenii
That too doesn't work out of the box but that is really OK with me as it lays a nice surface to work and play with.
I already used log.warn() to see what went wrong, and saw that Sprint was null, than when I assigned a value to it I still got null, so I checked the field and it appears that our project's Sprint is a custom filed. For the test I was able to read all the attributes of this field and they contain all the Sprint data.
Anyway, please let's leave it for now as I wish to resolve that on my own as much as I can. That is like a riddle that challenges me.
I really appreciate your goodwill. In the meanwhile I have put the listener in Disabled mode until I have time to get back to it.
Thanks again!!
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.