Come for the products,
stay for the community

The Atlassian Community can help you and your team get more value out of Atlassian products and practices.

Atlassian Community about banner
Community Members
Community Events
Community Groups

Status Order Groomer (ScriptRunner Script)

Hi everyone, I made a status order grooming script that orders all statuses in the following order by the statusCategory: To Do -> In Progress -> Done.

Currently, to do what this script does, you will have to click the up or down arrow many times!

Sharing this code so that you guys can better admin your Jira!

Reply below if there are improvements or bugs. 

import com.atlassian.jira.config.StatusManager
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.status.Status
import groovy.transform.Field
import org.apache.log4j.Level
import org.apache.log4j.Logger

@Field StatusManager statusManager = ComponentAccessor.getComponentOfType(StatusManager.class)
@Field Random random = new Random()

//Status Categories
@Field final String CAT_TO_DO = "new"
@Field final String CAT_INPROGRESS = "in progress"
@Field final String CAT_DONE = "complete"

// set up logger
@Field Logger logger = Logger.getLogger("Util Groom Statuses");


* Groom specific status category first
* @param statusCategory the status category to be groomed
void processStatusCategory(String statusCategory) {
List<Status> statuses = statusManager.getStatuses()

int count = 0
statuses.each {
//Get current Id and position
Status currentStatus = it
String currentCategory = it.getStatusCategory().getName()
Long currentPosition = it.getSequence()

if (count.equals(0)) {
if (!currentStatus.getStatusCategory().getName().equalsIgnoreCase(CAT_TO_DO)) {
Status firstTodo = statuses.find{it.getStatusCategory().getName().equalsIgnoreCase(CAT_TO_DO)}
Long firstMove = firstTodo.getSequence() - 1
move(firstMove, firstTodo)

if (currentStatus.getStatusCategory().getName().equalsIgnoreCase(statusCategory) && !isInCorrectBlock(currentStatus)) {
//Get the status category
Long moveToPosition = getMoveToPosition(currentCategory)
logger.debug ("Last Position: $moveToPosition")

//Get the number of moves needed
Long moves = currentPosition - moveToPosition
logger.debug ("Moves needed $moves")

//perform move
move(moves, currentStatus)

* Get the last position or first position of the TO DO or COMPLETE category
* Used to calculate how many moves are required
* @param category the category we are getting the moves required
* @return
Long getMoveToPosition(String category) {
logger.debug("Get Position for category: $category")
List<Status> statuses = statusManager.getStatuses()
Long position = null
switch (category.toUpperCase()) {
case CAT_TO_DO.toUpperCase():
position = statuses.find{!it.getStatusCategory().getName().equalsIgnoreCase(CAT_TO_DO)}.getSequence()
case CAT_INPROGRESS.toUpperCase():
position = statuses.find{!it.getStatusCategory().getName().equalsIgnoreCase(CAT_TO_DO) && !it.getStatusCategory().getName().equalsIgnoreCase(CAT_INPROGRESS)}.getSequence()
case CAT_DONE.toUpperCase():
position = statuses.last().getSequence()
logger.debug("Last position for $category is $position")
return position

* Move the status up or down based on the signage of the moves required
* @param moves signed Long for how many moves required. Positive move means moving up. Negative means
* down moves.
* @param status the status to be moved
void move(Long moves, Status status) {
logger.debug("Starting Moves. Initial position: " + status.getSequence())
int i = 0
while (i < Math.abs(moves)){
if (moves > 0) {
else {
logger.debug("Final position: " + status.getSequence())

* Check to see if the statuses is correctly grouped with its category
* @param status the status to be checked
* @return true if the status is grouped together
boolean isInCorrectBlock(Status status) {
//If it is TO_DO there should be no other categories before it
//If it is Inprogress there should be only inprogress before or after it, followed by only TO_DO or COMPLETE
//IF it is COMPLETE there should only be COMPLETE after it
boolean output = false
List<Status> statuses = statusManager.getStatuses()
List<Status> reversedOrderStatuses = statuses.reverse()
Long currentPosition = status.getSequence()

Long todoBoundaryPosition = statuses.find{!it.getStatusCategory().getName().equalsIgnoreCase(CAT_TO_DO)}.getSequence()
Long inProgressBoundaryPosition = statuses.find{!it.getStatusCategory().getName().equalsIgnoreCase(CAT_TO_DO) && !it.getStatusCategory().getName().equalsIgnoreCase(CAT_INPROGRESS)}.getSequence()
Long todoDonePosition = reversedOrderStatuses.find{!it.getStatusCategory().getName().equalsIgnoreCase(CAT_DONE)}.getSequence()

switch (status.getStatusCategory().getName().toUpperCase()) {
case CAT_TO_DO.toUpperCase():
if (currentPosition < todoBoundaryPosition) {
output = true
case CAT_INPROGRESS.toUpperCase():
if ( currentPosition >= todoBoundaryPosition && currentPosition <= inProgressBoundaryPosition) {
output = true
case CAT_DONE.toUpperCase():
if ( currentPosition > todoDonePosition) {
output = true
logger.debug("Check If Status in Correct Block: Current Position($currentPosition), ${status.getName()}:CurrentCat(${status.getStatusCategory().getName()}), todoBoundaryPosition(${todoBoundaryPosition}) todoDonePosition(${todoDonePosition}), Output ($output)" )
return output

* Randomizes Statuses for testing
void randomizeStatuses() {
List<Status> statuses = statusManager.getStatuses()

statuses.each {0
Long moves = random.longs(-30, 30).findFirst().getAsLong()
move(moves, it)
logger.debug("Random move ${it.getName()} moved $moves")





Log in or Sign up to comment
Community showcase
Published in Jira Software

Upcoming changes to epic fields in company-managed projects

👋 Hi there Jira Community! A few months ago we shared with you plans around renaming epics in your company-managed projects. As part of these changes, we highlighted upcoming changes to epics on...

14,877 views 37 49
Read article

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you