Hello!
I need some help about scripted post function. I want to fire an Action (ex: Sent to Review) as a Post Function another transition (ex: Integrate) if a complicated condition goes true.
I have some questions:
1, Is it possible to fire an Action (transition) as a post function of another transition.
I am writing you the whole situation and my expectation. If anybody has idea how to figure out the solution please answer me.
I want to fire automatic transitions on my parent issue depending on sub-task's status, different sub-task types and different statuses. All automatic transition has different condition concern to sub-task's types and statuses and the parent issue is must be in specified status.
Here is what is made:
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.user.util.UserManager
import java.util.logging.Logger;
import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.issue.IssueInputParameters
public void doTransition(String statusId, int transitionId) {
try{
Thread thread = Thread.start {
sleep(1000);
IssueService issueService = ComponentAccessor.getIssueService()
UserManager userManager = (UserManager) ComponentAccessor.getUserManager()
IssueInputParameters issueInputParameters = issueService.newIssueInputParameters();
issueInputParameters.setStatusId(statusId);
IssueService.TransitionValidationResult transitionValidationResult = issueService.validateTransition(ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser(), issue.id, transitionId, issueInputParameters);
if (transitionValidationResult.isValid()){
IssueService.IssueResult transitionResult = issueService.transition(currentUser, transitionValidationResult);
if (!transitionResult.isValid()) {
transitionResult.errorCollection.errorMessages.each {log.error "Error Message: $it"}
transitionResult.errorCollection.errors.each {log.error "Error: $it"}
transitionResult.errorCollection.reasons.each {log.error "Reason: $it"}
}
} else {
transitionValidationResult.errorCollection.errorMessages.each {log.error "Error Message: $it"}
transitionValidationResult.errorCollection.errors.each {log.error "Error: $it"}
transitionValidationResult.errorCollection.reasons.each {log.error "Reason: $it"}
}
}
} catch (Exception e){
log.error(e.getMessage());
}
}
def subtasks = issue.getSubTaskObjects();
def cFieldValue = issue.getCustomFieldValue(ComponentAccessor.getCustomFieldManager().getCustomFieldObject("customfield_22200")) // status before trigger
def goToReproduction = false;
def goToProcessing = false;
def goToIntegrating = false;
def goToVerifying = false;
def goToConcluding = false;
for (int i=0; i < subtasks.size(); i++)
{
def nextIssue = subtasks[i];
if (cFieldValue == 'Categorizing')
{
if (nextIssue.getIssueTypeId() == "13602" && nextIssue.getStatus()?.name != 'New')
{
goToReproduction = true
break;
}
}
else if (cFieldValue == 'Reproduction')
{
if ((nextIssue.getIssueTypeId() == "13603" || nextIssue.getIssueTypeId() == "13701") && nextIssue.getStatus()?.name != 'New')
{
goToProcessing = true
break;
}
}
else if (cFieldValue == 'Processing')
{
if ((nextIssue.getIssueTypeId() == "13603" || nextIssue.getIssueTypeId() == "13701") && nextIssue.getStatus()?.name == 'Closed')
{
goToIntegrating = true
break;
}
}
else if (cFieldValue == 'Integrating')
{
if ((nextIssue.getIssueTypeId() == "13507" && nextIssue.getStatus()?.name != 'New'))
{
goToVerifying = true
break;
}
}
else
{
}
}
if (goToReproduction){
doTransition("3", 21);
}
if (goToProcessing)
{
doTransition("4", 31);
}
if (goToIntegrating)
{
doTransition("5", 41);
}
if (goToVerifying)
{
doTransition("6", 51);
}
if (goToConcluding)
{
doTransition("7", 61);
}Does anybody have better solution then mine, without hack?
As I understand you have several transitions from single status of parent issue and you want automatically select correct one.
For this purpose I usually use respective conditions for transitions. When conditions are well organised user has the only button for transtion.
Bonus: I like to refactor code, here is refactored version of your code:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.user.util.UserManager
import java.util.logging.Logger;
import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.issue.IssueInputParameters
public void doTransition(String statusId, int transitionId) {
try{
Thread thread = Thread.start {
sleep(1000);
IssueService issueService = ComponentAccessor.getIssueService()
UserManager userManager = (UserManager) ComponentAccessor.getUserManager()
IssueInputParameters issueInputParameters = issueService.newIssueInputParameters();
issueInputParameters.setStatusId(statusId);
IssueService.TransitionValidationResult transitionValidationResult = issueService.validateTransition(ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser(), issue.id, transitionId, issueInputParameters);
if (transitionValidationResult.isValid()){
IssueService.IssueResult transitionResult = issueService.transition(currentUser, transitionValidationResult);
if (!transitionResult.isValid()) {
transitionResult.errorCollection.errorMessages.each {log.error "Error Message: $it"}
transitionResult.errorCollection.errors.each {log.error "Error: $it"}
transitionResult.errorCollection.reasons.each {log.error "Reason: $it"}
}
} else {
transitionValidationResult.errorCollection.errorMessages.each {log.error "Error Message: $it"}
transitionValidationResult.errorCollection.errors.each {log.error "Error: $it"}
transitionValidationResult.errorCollection.reasons.each {log.error "Reason: $it"}
}
}
} catch (Exception e){
log.error(e.getMessage());
}
}
boolean goToConcluding = false;
for(Issue subtask: issue.getSubTaskObjects()) {
switch (issue.getCustomFieldValue(ComponentAccessor.getCustomFieldManager().getCustomFieldObject("customfield_22200"))) {
case "Categorizing":
if (subtask.getIssueTypeId() == "13602" && subtask.getStatusObject()?.getName() != 'New') {
doTransition("3", 21);
break;
}
case 'Reproduction':
if ((subtask.getIssueTypeId() == "13603" || subtask.getIssueTypeId() == "13701") && subtask.getStatusObject()?.getName() != 'New') {
doTransition("4", 31);
break;
}
case 'Processing':
if ((subtask.getIssueTypeId() == "13603" || subtask.getIssueTypeId() == "13701") && subtask.getStatusObject()?.getName() == 'Closed') {
doTransition("5", 41);
break;
}
case 'Integrating':
if ((subtask.getIssueTypeId() == "13507" && subtask.getStatusObject()?.getName() != 'New')) {
doTransition("6", 51);
break;
}
}
}
if (goToConcluding){
doTransition("7", 61);
}
Hello Vasiliy!
Thank you very much for your answer and refactoring my code. I am quiet new at scriting, so this things always helps me a lot! ![]()
Yes, you understand well, I have several transitions from a single status and I want to fire the right one depending on sub-tasks type and status, but this transition I want to occur automatically.
More details about the situation.
I have a simple workflow for the parent ticket with one "hidden" status, named "Triggerd". I real process we don't use this status, this is just to help in automatize our complex workflow. In specified sub-task types, on the right transitions I added a post-function to call Trigger transition in parent ticket. (Trigger transition move to Triggered status). And I want my parent ticket to move toward to the right status is I fire this "triggering" transition in sub-task. I don't want to stay the parent ticket at "Triggered" status.
Easier, I want to automatize selecting and firing the right transition in parent ticket, launched with the specified sub-task transition.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Your solution seems to difficalt for me.
I think that it could be easer to have respective postfunction on sub-task transitions. In this case there is no any need to check sub-task type and status.
Try to reorganise you processes and onle then start writing code. If information about your processes is not secret, I could help you to organase it.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I have never heard about respective post-functions. I will look for some information about it.
My process is not a secret but I think would be easier to contact each other on another platform not to disturb other users. Please contact me through my e-mail. mullnerbianka@gmail.com
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Respective is not some type of post-function. I mean appropriate or post-function which do what it should do
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I see......
I need to monitor the sub-tasks because in my process it is possible to have more than one sub-task typed for ex. Reproducing and the parent ticket can't go toward to the next Status (ex:Fixing) until all the Reproducing tickets are not closed.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I think that it is better to add a postfunction on close transition:
import com.atlassian.jira.issue.Issue
for(Issue subtask: issue.getParentObject().getSubTaskObjects()){
if((subtask.getIssueTypeObject().getName().equals("Reproducing")) && (subtask.getResolutionObject()) == null){
return; //we have at least 1 unresolved Reproducing issue
}
}
//Code to trasit parent issue
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.