Hey there!
I just wanted to share my solution for clearing the Resolution on a status transition (if moved from Done to To-Do or In-Progress) and wanted to ask for some feedback - perhaps I've missed something, or I'm doing something very silly.
The reason I haven't used Post Functions to clear the resolution is to have 1 script that covers all cases and avoid having to setup and maintain multiple post-functions (e.g. if a new status is added, it's covered automatically).
Using ScriptRunner I've created a Listener that listens to All Issue Events for my particular project (there didn't seem to be one for just listening to status transitions).
Here's the script:
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.status.category.StatusCategory
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption
/*
A status Transition listener that clears the Resolution status if an issue is
moved from a "Complete" status category any of the to the other categories ("To-Do" / "In Progress").
*/
// The issue provided to us in the binding
MutableIssue issue = event.issue as MutableIssue
// Not an epic? We only care about those. Early exit.
if (issue.getIssueType().getName() != "Epic") {
return
}
// No changelog (e.g. an edit with only a comment)? Early exit.
if (event.getChangeLog() == null) {
return
}
def statusChangeItems = ComponentAccessor.getChangeHistoryManager().getChangeItemsForField(issue, 'status')
// No status changes? It's a new issue. Early exit.
if (statusChangeItems.isEmpty()) {
return
}
def lastTransitionChangeItem = statusChangeItems?.last()
def fromStatus = lastTransitionChangeItem.fromString
def toStatus = lastTransitionChangeItem.toString
// No status change? Early exit.
if (fromStatus == toStatus) {
return
}
def eventFiredTimestamp = event.getChangeLog().created
def changeItemTimestamp = lastTransitionChangeItem.created
// If the last status change was at the exact same time as the event we can (somewhat?)
// safely deduce that this event was fired because of a status transition
if(changeItemTimestamp != eventFiredTimestamp) {
return
}
StatusCategory fromStatusCategory = null
StatusCategory toStatusCategory = null
def workflow = ComponentAccessor.getWorkflowManager().getWorkflow(issue)
// Find category of status by name
workflow.getLinkedStatusObjects().each {
if ("${it.name}" == fromStatus) {
fromStatusCategory = it.statusCategory
}
if ("${it.name}" == toStatus) {
toStatusCategory = it.statusCategory
}
}
// Couldn't find status categories from status name? (Shouldn't happen..)
if (fromStatusCategory == null || toStatusCategory == null) {
log.warn ("Could not find category for from- (${fromStatus}), or to-, status (${toStatus}).")
return
}
// Not a transition from a "Complete" (green) status? Not interested. Early exit.
if (fromStatusCategory.getKey() != StatusCategory.COMPLETE) {
return
}
// Transition to "Complete" status? Don't want to clear resolution. Early exit.
if (toStatusCategory.getKey() == StatusCategory.COMPLETE) {
return
}
// Let's clear that resolution!
def issueManager = ComponentAccessor.getIssueManager()
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
issue.setResolution(null)
issueManager.updateIssue(user, issue, EventDispatchOption.DO_NOT_DISPATCH, false)
Recommended Learning For You
Level up your skills with Atlassian learning
Learning Path
Get started with Jira Software
New to Jira Software? These short, self-paced courses will teach you what you need to know to get up and running quickly.
The Beginner's Guide to Agile in Jira
Learn what agile, kanban, and scrum are and how agile works in Jira Software.
Realizing the Power of Jira Reporting and Dashboards
Use out-of-the box reporting and dashboard capabilities to view and assess progress and bottlenecks within projects.