Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Earn badges and make progress

You're on your way to the next level! Join the Kudos program to earn points and save your progress.

Deleted user Avatar
Deleted user

Level 1: Seed

25 / 150 points

Next: Root


1 badge earned


Participate in fun challenges

Challenges come and go, but your rewards stay with you. Do more to earn more!


Gift kudos to your peers

What goes around comes around! Share the love by gifting kudos to your peers.


Rise up in the ranks

Keep earning points to reach the top of the leaderboard. It resets every quarter so you always have a chance!


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