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)