This is my first shot at a scripted field and I have no clue where to start. An answer to the subject will go a long way in getting me where I'm trying to go.
Ultimately, I want to count all issues within an epic or all subtasks within an issue. Then I want to count all issues with a specific status - lets assume closed - and divide this by the total number of subtasks to get a rough % Complete.
For Stories linked to the Epics try this:
import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.issue.Issue import com.atlassian.jira.issue.link.IssueLinkManager import com.atlassian.jira.issue.link.IssueLinkType import com.atlassian.jira.issue.link.IssueLinkTypeManager Issue issue = issue IssueLinkTypeManager issueLinkTypeManager = ComponentAccessor.getComponent(IssueLinkTypeManager) IssueLinkManager issueLinkManager = ComponentAccessor.issueLinkManager Collection<IssueLinkType> storyLinkTypes = issueLinkTypeManager.getIssueLinkTypesByName('Epic-Story Link') if (storyLinkTypes) { Long storyLinkTypeId = storyLinkTypes[0].id def linkedStories = issueLinkManager.getOutwardLinks(issue.id).findAll{it.linkTypeId==storyLinkTypeId}*.destinationObject int numStories = linkedStories?.size()?:0 if (numStories>0) { int numClosedStories = linkedStories?.count{it?.statusObject?.name=='Closed'}?:0 return (numClosedStories/numStories) as Double } else { return 0 as Double } } else { return 0 as Double }
This is not tested by me, so you should try this in a test environment first.
The first part, getting the linkTypeId could be replaced by the id of the link type in your system if you don't want to use the script in different systems (test, live, etc.).
I just noticed some strange behavior. When I close or reopen an issue, the modal/transition window that pops up doesn't go away when clicking the button.
Any idea what might be causing this? I removed the scripted field to confirm it's the cause.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks for this goes out to Henning Tietgens.
I'm sure i've mangled his code, but here's what I ended up with.
Goal: calculate a % of Tasks Complete on the host issue by looking at sub-tasks in the case of stories/issues and stories within an epic in the case of Epics.
First I'm checking whether if the host issue is an Epic or not. If it is, use the linked stories approach to calculate the %Complete. Otherwise, use the sub-task approach:
import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.issue.Issue import com.atlassian.jira.issue.link.IssueLinkManager import com.atlassian.jira.issue.link.IssueLinkType import com.atlassian.jira.issue.link.IssueLinkTypeManager Issue issue = issue IssueLinkTypeManager issueLinkTypeManager = ComponentAccessor.getComponent(IssueLinkTypeManager) IssueLinkManager issueLinkManager = ComponentAccessor.issueLinkManager Collection<IssueLinkType> storyLinkTypes = issueLinkTypeManager.getIssueLinkTypesByName('Epic-Story Link') if (issue.issueTypeObject.name == "Epic"){ if (storyLinkTypes) { Long storyLinkTypeId = storyLinkTypes[0].id def linkedStories = issueLinkManager.getOutwardLinks(issue.id).findAll{it.linkTypeId==storyLinkTypeId}*.destinationObject double numStories = linkedStories?.size()?:0 if (numStories>0) { double numClosedStories = linkedStories?.count{it?.statusObject?.name=='Closed'}?:0 double percentcomplete = (numClosedStories/numStories)*100 return percentcomplete.round(2) as double } else { return 0 as double } } } else{ double numSubtasks = issue.getSubTaskObjects()?.size()?:0 if (numSubtasks>0) { double numClosedSubtasks = issue.getSubTaskObjects()?.count{it?.statusObject?.name=='Closed'}?:0 double percentcomplete = (numClosedSubtasks/numSubtasks)*100 return percentcomplete.round(2) as double } else { return 0 as double } }
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Does this work? You return object of different classes: String, Double and int.
If you want to use the field for reports it should be a number field (so return a Double).
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Did you get any errors in the log?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Unfortunately, I have no access to the logs.
Current field config is:
Template: Number Field
Configured searcher: Number Searcher
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
It works, but I'll be happy to "fix" anything that's wrong. I did find that when I transition an issue to closed the modal just stays up when I have this scripted field enabled.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
What's the config of the custom field searcher and template for your scripted field?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Found the answer. I thought re-indexing might help so I ran one and got an error that referenced doubles. I just needed to ensure I set both sections to return doubles as you pointed out above.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Rather than this, why dont you use the Epic Charts?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Unfortunately, I need to be able to report on this field.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi all,
I can see this topic is as old as hills and something definitely changed but I am facing a problem with the code posted by @Henning Tietgens .
I am trying to get a field that shows the <Done>/<All> tickets in Epic (including Bugs, US and Tasks) where Done is statusCategory = Done
I started from the very basic solution: https://community.atlassian.com/t5/Jira-Software-questions/JIRA-Need-count-of-stories-under-an-epic/qaq-p/961579
but I always get an error:
At the end I will just change the percentage to String: Done/All
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi, you're getting the status category of the issue and after that count every subtask of the issue where the status category of the issue (not the subtask) is Done. Is that what you want? In this case on simple if statement after getting sc would be enough.
if (sc.name == 'Done') {
If you want the status category of the subtask you need to change {sc.getName()... to {it.status.statusCategory.name == 'Done'}.
If you write "as Integer" at the end of the last line the static type error should go away.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Henning, thank you for your replay. I am almost there.
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.link.IssueLinkManager
import com.atlassian.jira.issue.link.IssueLinkType
import com.atlassian.jira.issue.link.IssueLinkTypeManager
Issue issue = issue
IssueLinkTypeManager issueLinkTypeManager = ComponentAccessor.getComponent(IssueLinkTypeManager)
IssueLinkManager issueLinkManager = ComponentAccessor.issueLinkManager
Collection<IssueLinkType> storyLinkTypes = issueLinkTypeManager.getIssueLinkTypesByName('Epic-Story Link')
if (storyLinkTypes) {
Long storyLinkTypeId = storyLinkTypes[0].id
def linkedStories = issueLinkManager.getOutwardLinks(issue.id).findAll{it.linkTypeId==storyLinkTypeId}*.destinationObject
int numStories = linkedStories?.size()?:0
if (numStories>0) {
def numClosedStories = linkedStories?.count{it.status.statusCategory.name == 'Done'}?:0
// return (numClosedStories/numStories) as Double
return numClosedStories+"/"+numStories as String
} else {
return 0 as Double
}
} else {
return 0 as Double
}
It returns the 0/32 (0 is the number of Done tickets - false I have 12 "/" 32 is a number of all tickets under Epic and this is true
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I was able to find the problem, for Jira there is no such a category as Done (we are using it) for Atlassian it is COMPLETE. So the code is as follows:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.link.IssueLinkManager
import com.atlassian.jira.issue.link.IssueLinkType
import com.atlassian.jira.issue.link.IssueLinkTypeManager
Issue issue = issue
IssueLinkTypeManager issueLinkTypeManager = ComponentAccessor.getComponent(IssueLinkTypeManager)
IssueLinkManager issueLinkManager = ComponentAccessor.issueLinkManager
Collection<IssueLinkType> storyLinkTypes = issueLinkTypeManager.getIssueLinkTypesByName('Epic-Story Link')
if (storyLinkTypes) {
Long storyLinkTypeId = storyLinkTypes[0].id
def linkedStories = issueLinkManager.getOutwardLinks(issue.id).findAll{it.linkTypeId==storyLinkTypeId}*.destinationObject
int numStories = linkedStories?.size()?:0
if (numStories>0) {
def numClosedStories = linkedStories?.count{it.status.statusCategory.name == 'Complete'}?:0
return numClosedStories+"/"+numStories as String
} else {
return 0 as Double
}
} else {
return 0 as Double
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Ok, perfect. You should double check the return types. Something is wrong, because sometimes it's String sometimes Double. This should be the same, I suspect
return ""
or
return null
instead of
return 0 as Double
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
When I try the above script, I get an error:
variable [issue] is undeclared
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Unfortunately, no access to logs at the moment.
I made the changes you recommended:
Template: Number Field
Configured searcher: Number Searcher
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You can also make an Issue Statistics gadget based on the JQL that uses Epic Link.
For example see https://jira.atlassian.com/issues/?jql=%22Epic%20Link%22%20%3D%20GHS-5232%20and%20status%20%3D%20Resolved
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks for the suggestion! This is an approach I use in dashboards and sometimes in Confluence pages. The problem I'm tasked with is providing a field that's reportable so it can be included on an excel export.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Ah alright. In that case the scripted field solution from Henning Tietgens is the best solution.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
For a Script Runner scripted field you can try this:
int numSubtasks = issue.getSubTaskObjects()?.size()?:0 if (numSubtasks>0) { int numClosedSubtasks = issue.getSubTaskObjects()?.count{it?.statusObject?.name=='Closed'}?:0 return (numClosedSubtasks/numSubtasks) as Double } else { return 0 as Double }
Configure as nuber template and searcher.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Very close... it doesn't appear to work for epics and their sub issues.
Is the above script based on Groovy?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Yes, it's groovy. Ok, so your talking about Stories linked to Epics, not subtasks?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Spend the day sharpening your skills in Atlassian Cloud Organization Admin or Jira Administration, then take the exam onsite. Already ready? Take one - or more - of 12 different certification exams while you’re in Anaheim at Team' 25.
Learn more
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.