Zmiana statusu na poprzedni

Aby zmienić status zgłoszeń na poprzedni na podstawie zapytania JQL w Jira Script Runner, możesz użyć następującego kodu w języku Groovy:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue

def jqlQuery = "your_jql_query_here"
def searchResults = ComponentAccessor.getSearchService().search(ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser(), ComponentAccessor.getJqlQueryParser().parseQuery(jqlQuery), 10000, 0)
searchResults.getResults().each { issue ->
    def statusName = issue.getStatus().getName()
    def statusCategory = issue.getStatus().getStatusCategory().getKey()
    def previousStatusName = ""
    if (statusCategory != "new" && statusCategory != "indeterminate") {
        def statusManager = ComponentAccessor.getStatusManager()
        def statusCategoryManager = ComponentAccessor.getStatusCategoryManager()
        def status = statusManager.getStatusByName(issue.getProjectObject(), statusName)
        def previousStatus = statusCategoryManager.getPreviousStatus(status)
        if (previousStatus) {
            previousStatusName = previousStatus.getName()
            issue.setStatusObject(previousStatus)
            ComponentAccessor.getIssueManager().updateIssue(ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser(), issue, MutableIssue.NO_ISSUE_UPDATE)
            log.debug("Changed status of issue ${issue.getKey()} from ${statusName} to ${previousStatusName}")
        } else {
            log.debug("Issue ${issue.getKey()} does not have a previous status")
        }
    } else {
        log.debug("Issue ${issue.getKey()} is in a new or indeterminate status category")
    }
}

Powyższy kod pobiera wyniki wyszukiwania dla podanego zapytania JQL, a następnie dla każdego znalezionego zgłoszenia pobiera nazwę bieżącego statusu oraz kategorię tego statusu. Jeśli status nie jest kategorią „nowy” lub „nieokreślony”, to pobiera poprzedni status dla bieżącego statusu, a następnie ustawia ten poprzedni status jako nowy status dla zgłoszenia. W przeciwnym razie, dla zgłoszenia w kategorii „nowy” lub „nieokreślony”, skrypt przeskakuje do następnego zgłoszenia.

Podczas wykonywania skryptu, w logach Jira wyświetlane będą informacje na temat zmienionych statusów dla każdego zgłoszenia.

Walidator – czy pole jest uzupełnione

Oto przykładowy skrypt walidatora w Jirze, który sprawdza, czy pole ma wartość:

import com.opensymphony.workflow.InvalidInputException

def fieldName = "Nazwa pola" // podaj nazwę pola
def fieldValue = issue.getCustomFieldValue(issue.getCustomFieldByName(fieldName))

if (fieldValue == null || fieldValue.toString().trim().isEmpty()) {
    throw new InvalidInputException("Pole " + fieldName + " jest wymagane.")
}

W tym skrypcie należy zdefiniować nazwę pola, które chcesz sprawdzić (fieldName), a następnie pobrać jego wartość z bieżącej sprawy (issue) za pomocą metody getCustomFieldValue(). Następnie skrypt sprawdza, czy wartość pola jest pusta lub null za pomocą metody isEmpty() i trim(). Jeśli wartość jest pusta lub null, skrypt zwróci wyjątek InvalidInputException z odpowiednim komunikatem. Możesz zapisać ten skrypt jako walidator w Jirze i używać go do sprawdzania, czy pole jest wypełnione.

Oto przykładowy skrypt walidatora w Jirze, który sprawdza, czy pole ma wartość. W tym przypadku nazwę pola wybieramy z listy dostępnych pól w projekcie:

import com.opensymphony.workflow.InvalidInputException
import com.atlassian.jira.component.ComponentAccessor

def customFieldManager = ComponentAccessor.getCustomFieldManager()
def field = customFieldManager.getCustomFieldObjectByName("Nazwa pola") // podaj nazwę pola
def fieldValue = issue.getCustomFieldValue(field)

if (fieldValue == null || fieldValue.toString().trim().isEmpty()) {
    throw new InvalidInputException("Pole " + field.name + " jest wymagane.")
}

W tym skrypcie używamy menedżera pól niestandardowych (customFieldManager), aby pobrać obiekt pola o nazwie „Nazwa pola” (podaj właściwą nazwę pola). Następnie pobieramy wartość pola z bieżącej sprawy (issue) za pomocą metody getCustomFieldValue(). Skrypt sprawdza, czy wartość pola jest pusta lub null za pomocą metod isEmpty() i trim(). Jeśli wartość jest pusta lub null, skrypt zwróci wyjątek InvalidInputException z odpowiednim komunikatem, zawierającym nazwę pola. Możesz zapisać ten skrypt jako walidator w Jirze i używać go do sprawdzania, czy pole ma wartość.

Walidator – czy zadanie ma załącznik

Oto przykładowy skrypt walidatora w Jirze, który sprawdza, czy w bieżącej sprawie (issue) znajduje się załącznik:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.attachment.AttachmentManager

def attachmentManager = ComponentAccessor.getAttachmentManager()
def attachments = attachmentManager.getAttachments(issue)

if (attachments.isEmpty()) {
    throw new InvalidInputException("This issue requires an attachment.")
}

Skrypt ten pobiera menedżera załączników (attachmentManager) i sprawdza, czy istnieją załączniki w bieżącej sprawie (issue) za pomocą metody getAttachments(). Jeśli lista załączników jest pusta, skrypt zwróci wyjątek InvalidInputException z odpowiednim komunikatem. Możesz zapisać ten skrypt jako walidator w Jirze i używać go do sprawdzania, czy w sprawie znajduje się załącznik.

Walidator – ilość znaków konkretnego pola

Oto przykładowy skrypt walidatora w Jirze, który sprawdza, czy pole opisu (description) ma co najmniej 50 znaków:

import com.opensymphony.workflow.InvalidInputException
import com.atlassian.jira.component.ComponentAccessor

def descriptionField = ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName("Description")

def description = issue.getCustomFieldValue(descriptionField)
if(description?.length() < 50){
    throw new InvalidInputException("Description field must have at least 50 characters.")
}

Skrypt ten pobiera pole opisu (description) dla bieżącej sprawy (issue) i sprawdza, czy długość tego pola jest większa niż 50. Jeśli długość jest mniejsza, skrypt zwróci wyjątek InvalidInputException z odpowiednim komunikatem. Możesz zapisać ten skrypt jako walidator w Jirze i używać go do sprawdzania, czy pole description ma wymaganą długość.

Suma wartości pól

Aby pobrać wartości pól z danego zgłoszenia w Jira za pomocą Script Runner i wykonać sumę tych pól, można użyć metody getValue() z obiektu Issue w celu pobrania wartości pola, a następnie dodać te wartości do siebie.

Przykładowy kod w Groovy, który pobiera wartości pól „customfield_10000” i „customfield_10001” z zgłoszenia o kluczu „ABC-123” i wykonuje ich sumę:

import com.atlassian.jira.component.ComponentAccessor

def issueKey = "ABC-123"
def issue = ComponentAccessor.getIssueManager().getIssueObject(issueKey)

def customFieldManager = ComponentAccessor.getCustomFieldManager()
def field1 = customFieldManager.getCustomFieldObjectByName("Field 1")
def field2 = customFieldManager.getCustomFieldObjectByName("Field 2")

def value1 = issue.getCustomFieldValue(field1) as Double
def value2 = issue.getCustomFieldValue(field2) as Double

def sum = value1 + value2

log.info("Sum of Field 1 and Field 2 for issue ${issueKey} is ${sum}")

W powyższym kodzie, najpierw uzyskujemy dostęp do menedżera pól niestandardowych Jira za pomocą ComponentAccessor.getCustomFieldManager(). Następnie pobieramy obiekty pól niestandardowych, których wartości chcemy pobrać, używając getCustomFieldObjectByName() i przekazując nazwy pól jako argumenty.

Następnie pobieramy wartości pól niestandardowych dla danego zgłoszenia, używając getCustomFieldValue() na obiekcie Issue. Ponieważ wartości pól niestandardowych mogą mieć różne typy, w tym przykładzie zakładamy, że oba pola są typu Double.

Na końcu dodajemy wartości pól i zapisujemy wynik do zmiennej sum. W przykładzie wykorzystujemy metodę log.info() do wyświetlenia wyniku.

Aby wykonać sumowanie wartości pól z kilku zgłoszeń w Jira za pomocą Script Runner, można użyć metody getIssues() z klasy SearchService do znalezienia i pobrania listy obiektów zgłoszeń, które pasują do określonych kryteriów wyszukiwania. Następnie można iterować po liście zgłoszeń i sumować wartości pól.

Przykładowy kod w Groovy, który znajduje i sumuje wartości pól „customfield_10000” i „customfield_10001” dla wszystkich zgłoszeń w projekcie o kluczu „PROJ” i wyświetla wynik:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.search.SearchException
import com.atlassian.jira.jql.builder.JqlQueryBuilder
import com.atlassian.jira.web.bean.PagerFilter

def jqlQuery = JqlQueryBuilder.newBuilder()
        .where()
        .project("PROJ")
        .buildQuery()

def searchService = ComponentAccessor.getComponent(SearchService)
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def issues = searchService.search(user, jqlQuery, PagerFilter.getUnlimitedFilter()).issues

def customFieldManager = ComponentAccessor.getCustomFieldManager()
def field1 = customFieldManager.getCustomFieldObjectByName("Field 1")
def field2 = customFieldManager.getCustomFieldObjectByName("Field 2")

def sum = 0.0

for (Issue issue in issues) {
    def value1 = issue.getCustomFieldValue(field1) as Double
    def value2 = issue.getCustomFieldValue(field2) as Double
    sum += value1 + value2
}

log.info("Sum of Field 1 and Field 2 for all issues in project PROJ is ${sum}")

W powyższym kodzie najpierw tworzymy zapytanie JQL, które znajduje wszystkie zgłoszenia w projekcie o kluczu „PROJ”. Następnie używamy searchService.search() do wykonania wyszukiwania i pobrania listy obiektów zgłoszeń, które pasują do zapytania.

Następnie pobieramy obiekty pól niestandardowych, których wartości chcemy pobrać, i iterujemy po liście zgłoszeń, sumując wartości pól. Na końcu wynik zapisujemy do zmiennej sum. W przykładzie wykorzystujemy metodę log.info() do wyświetlenia wyniku.

Aby wpisać wynik sumowania pól do nowego pola niestandardowego w Jira za pomocą Script Runner, można użyć metody setCustomFieldValue() na obiekcie MutableIssue w celu ustawienia wartości pola.

Przykładowy kod w Groovy, który znajduje i sumuje wartości pól „customfield_10000” i „customfield_10001” dla wszystkich zgłoszeń w projekcie o kluczu „PROJ” i zapisuje wynik do pola „customfield_10002” w pierwszym znalezionym zgłoszeniu:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.search.SearchException
import com.atlassian.jira.jql.builder.JqlQueryBuilder
import com.atlassian.jira.web.bean.PagerFilter

def jqlQuery = JqlQueryBuilder.newBuilder()
        .where()
        .project("PROJ")
        .buildQuery()

def searchService = ComponentAccessor.getComponent(SearchService)
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser()
def issues = searchService.search(user, jqlQuery, PagerFilter.getUnlimitedFilter()).issues

def customFieldManager = ComponentAccessor.getCustomFieldManager()
def field1 = customFieldManager.getCustomFieldObjectByName("Field 1")
def field2 = customFieldManager.getCustomFieldObjectByName("Field 2")
def targetField = customFieldManager.getCustomFieldObjectByName("Field 3")

def sum = 0.0

for (Issue issue in issues) {
    def value1 = issue.getCustomFieldValue(field1) as Double
    def value2 = issue.getCustomFieldValue(field2) as Double
    sum += value1 + value2
}

def firstIssue = issues.first()
def mutableIssue = ComponentAccessor.getIssueManager().getIssueObject(firstIssue.id) as MutableIssue
mutableIssue.setCustomFieldValue(targetField, sum)
ComponentAccessor.getIssueManager().updateIssue(user, mutableIssue, EventDispatchOption.ISSUE_UPDATED, false)

log.info("Sum of Field 1 and Field 2 for all issues in project PROJ is ${sum}. Result saved in Field 3 for issue ${firstIssue.key}")

W powyższym kodzie po obliczeniu sumy, najpierw pobieramy obiekt pola niestandardowego, do którego chcemy zapisać wynik (w przykładzie używamy nazwy „Field 3”). Następnie pobieramy pierwsze znalezione zgłoszenie i tworzymy obiekt MutableIssue z tego zgłoszenia. Ustawiamy wartość pola niestandardowego na obliczoną sumę za pomocą setCustomFieldValue() i zapisujemy zmiany za pomocą ComponentAccessor.getIssueManager().updateIssue(). W przykładzie wykorzystujemy metodę log.info() do wyświetlenia wyniku.

Aby wpisać wynik sumowania pól do konkretnego zgłoszenia w Jira za pomocą Script:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue

def issue = ComponentAccessor.getIssueManager().getIssueByCurrentKey("ISSUE-123")
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def field1 = customFieldManager.getCustomFieldObjectByName("Field 1")
def field2 = customFieldManager.getCustomFieldObjectByName("Field 2")
def targetField = customFieldManager.getCustomFieldObjectByName("Field 3")

def value1 = issue.getCustomFieldValue(field1) as Double
def value2 = issue.getCustomFieldValue(field2) as Double
def sum = value1 + value2

issue.setCustomFieldValue(targetField, sum)
issue.store()

log.info("Sum of Field 1 and Field 2 for issue ISSUE-123 is ${sum}. Result saved in Field 3.")

W powyższym kodzie pobieramy zgłoszenie o kluczu „ISSUE-123” i obliczamy sumę pól „Field 1” i „Field 2”. Następnie ustawiamy wartość pola „Field 3” na obliczoną sumę i zapisujemy zmiany. W przykładzie wykorzystujemy metodę log.info() do wyświetlenia wyniku.

JQL functions

Aby utworzyć własne funkcje JQL w Jira, wykonaj poniższe kroki:

  1. Otwórz Script Console w Jira.
  2. Utwórz nowy plik groovy, w którym zdefiniujesz funkcję.
  3. Wprowadź skrypt do uruchomienia.
  4. W skrypcie wprowadź składnię JQL, aby zdefiniować funkcję.
  5. Skonfiguruj funkcję, aby zwracała poprawne wyniki.
  6. Zapisz plik i uruchom skrypt, aby przetestować funkcję.
  7. Zainstaluj wtyczkę ScriptRunner, jeśli jeszcze nie jest zainstalowana.
  8. Otwórz stronę zarządzania wtyczką ScriptRunner.
  9. Wybierz sekcję „JQL Functions” i dodaj nową funkcję.
  10. Wpisz nazwę funkcji, jej opis i kod groovy.
  11. Przetestuj funkcję, wykonując zapytanie JQL, które wykorzystuje nową funkcję.

Przykładowa funkcja JQL w Jira, która zwraca wszystkie problemy, których ostatnia aktualizacja była wykonana przez podanego użytkownika, może wyglądać następująco:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder

def user = args[0]

def issueManager = ComponentAccessor.getIssueManager()
def searchProvider = ComponentAccessor.getComponentOfType(com.atlassian.jira.issue.search.SearchProvider.class)
def queryParser = ComponentAccessor.getComponentOfType(com.atlassian.jira.jql.parser.JqlQueryParser.class)

def query = queryParser.parseQuery("issueFunction lastUpdatedByUser($user)")
def results = searchProvider.search(query, ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser(), com.atlassian.jira.web.bean.PagerFilter.getUnlimitedFilter())

def issues = results.issues.collect { issueManager.getIssueObject(it.id) }

return issues.findAll { issue ->
    def changeHistoryManager = ComponentAccessor.getChangeHistoryManager()
    def changeItems = changeHistoryManager.getChangeItemsForField(issue, "updated")
    def lastChange = changeItems.last()

    lastChange?.getTo()?.equals(user)
}

W powyższym przykładzie funkcja JQL nazywa się „lastUpdatedByUser” i przyjmuje jeden argument „user”. Funkcja wyszukuje wszystkie problemy, które są filtrowane przez zapytanie „issueFunction lastUpdatedByUser($user)”, a następnie sprawdza, czy ostatnia aktualizacja została wykonana przez podanego użytkownika.