Workflow & Automation
Workflow:
Code-list
Used optionId and customfield_id are described in Objects code-list matrix
Entering Probability value (P)
User got transition screen with the radio buttons containing all possible Probability options.
Field is always optional, but there is a Validator during Assess❗transition to check, if this field got not null value.
In this particular customer, Probability had five options, which are represented by values 1 (less probably) to 5 (extremely probable).
As we need to show word representation to customer, but store number value so we can use it later, we are storing number representation value to dedicated Custom Field "Probability Value".
return (issue.getRawValue("customfield_10104")?.optionId == 10209)
We are using this script with post-function "Set Issue Value (JMWE)". In this example, we are storing number "5" to Custom Field "Probability Value" with condition, if word representation is matching.
Those post function is repeated for each and every value of Custom Field, in this case, five times.
Entering Urgency (U)
User got transition screen with the radio buttons containing all possible Urgency options.
Field is always optional, but there is a Validator during Assess❗transition to check, if this field got not null value.
In this particular customer, Urgency had five options, which are represented by values 1 (trivial) to 5 (cricital).
As we need to show word representation to customer, but store number value so we can use it later, we are storing number representation value to dedicated Custom Field "Urgency Value".
return (issue.getRawValue("customfield_10103")?.optionId == 10200)
We are using this script with post-function "Set Issue Value (JMWE)". In this example, we are storing number "5" to Custom Field "Urgency Value" with condition, if word representation is matching.
Those post function is repeated for each and every value of Custom Field, in this case, five times.
Calculating Risk Factor field (F)
Field type is Calculated Number Field (plugin JMCF)
<!-- @@Formula: (issue.get("customfield_10108") != null ? issue.get("customfield_10108") : 0) * (issue.get("customfield_10110") != null ? issue.get("customfield_10110") : 0) -->
Entering Expected Costs (C)
User got transition screen with the radio buttons containing all possible Expected Costs options ranges.
Field is always optional, but there is a Validator during Assess❗transition to check, if this field got not null value.
In this particular customer, Expected Costs had five options, which are represented by 5 ranges, which can found at Objects code-list matrix.
Assigning users to Authorized to Approve (AtA) on behalf of (F) and (C) matrix.
Field Authorized to Approve is Checkbox type and can be filled with of Company Roles described in Objects code-list matrix.
We are setting Custom Field Authorized to Approve to five groups of roles on behalf of Risk Factor and Expected Costs.
Those groups are represented by Authorized to Approve values objectId and can be found in Objects code-list matrix.
The hardcoded values we are comparing Custom Fields to are defined by Customer and are under NDA. Sorry for not sharing, but you can imagine just some thresholds by putting togethers values of Risk Factor and Expected Costs.
Group MS, K, P and superiors
Double.parseDouble(issue.getAsString("customfield_10109")) > 0.5 && Double.parseDouble(issue.getAsString("customfield_10109")) < 2.4 && issue.getRawValue("customfield_10105")?.optionId == 10210
Group VS and superiors
(Double.parseDouble(issue.getAsString("customfield_10109")) > 2.5 && Double.parseDouble(issue.getAsString("customfield_10109")) < 4.5 && issue.getRawValue("customfield_10105")?.optionId == 10210) || (Double.parseDouble(issue.getAsString("customfield_10109")) > 0.5 && Double.parseDouble(issue.getAsString("customfield_10109")) < 2.5 && issue.getRawValue("customfield_10105")?.optionId == 10211)
Group RSZ and superiors
(Double.parseDouble(issue.getAsString("customfield_10109")) > 4.5 && Double.parseDouble(issue.getAsString("customfield_10109")) < 13 && issue.getRawValue("customfield_10105")?.optionId == 10210) || (Double.parseDouble(issue.getAsString("customfield_10109")) > 2.5 && Double.parseDouble(issue.getAsString("customfield_10109")) < 4.5 && issue.getRawValue("customfield_10105")?.optionId == 10211) || (Double.parseDouble(issue.getAsString("customfield_10109")) > 0.5 && Double.parseDouble(issue.getAsString("customfield_10109")) < 2.5 && issue.getRawValue("customfield_10105")?.optionId == 10212)
Group TR, RZP and superiors
(Double.parseDouble(issue.getAsString("customfield_10109")) > 4.5 && Double.parseDouble(issue.getAsString("customfield_10109")) < 13 && issue.getRawValue("customfield_10105")?.optionId == 10211) || (Double.parseDouble(issue.getAsString("customfield_10109")) > 2.5 && Double.parseDouble(issue.getAsString("customfield_10109")) < 4.5 && issue.getRawValue("customfield_10105")?.optionId == 10212) || (Double.parseDouble(issue.getAsString("customfield_10109")) > 0.5 && Double.parseDouble(issue.getAsString("customfield_10109")) < 2.5 && issue.getRawValue("customfield_10105")?.optionId == 10213)
Group RD (have no superiors)
(Double.parseDouble(issue.getAsString("customfield_10109")) > 14 || issue.getRawValue("customfield_10105")?.optionId == 10214) || (Double.parseDouble(issue.getAsString("customfield_10109")) > 4.5 && Double.parseDouble(issue.getAsString("customfield_10109")) < 23 && (issue.getRawValue("customfield_10105")?.optionId == 10212 || issue.getRawValue("customfield_10105")?.optionId == 10213 )) || (Double.parseDouble(issue.getAsString("customfield_10109")) > 2.5 && Double.parseDouble(issue.getAsString("customfield_10109")) < 4.5 && issue.getRawValue("customfield_10105")?.optionId == 10213)
Reflecting group checkboxes as rights (AtA) in transition validator
Predisposition: Global Project Roles are 1:1 set to have very same names as the values of Authorize to Approve (AtA) Custom field.
Because there is no method to return list of roles for currentUser, we are using this logic:
1) We are comparing value in (AtA) with every possible value which is defined by name of Project Role and optionId of Custom Fields Authorized to Approve. AND 2) We are comparing, if currentUser is in same Project Role. (hardcoded) IF Both condition are TRUE, transition is allowed. ELSE Transition is blocked and user got an error message, that he is not authorized to this Approval.
(issue.get("customfield_10111")?.any{it.value == "K: Level 1, Role 2"} && currentUser.isInProjectRole("K: Level 1, Role 2",issue.get("Project"))) || (issue.get("customfield_10111")?.any{it.value == "MS: Level 1, Role 1"} && currentUser.isInProjectRole("MS: Level 1, Role 1",issue.get("Project"))) || (issue.get("customfield_10111")?.any{it.value == "P: Level 1, Role 3"} && currentUser.isInProjectRole("P: Level 1, Role 3",issue.get("Project"))) || (issue.get("customfield_10111")?.any{it.value == "Level 4, Role 1"} && currentUser.isInProjectRole("TR: Level 4, Role 1",issue.get("Project"))) || (issue.get("customfield_10111")?.any{it.value == "VE: NOT IN USE"} && currentUser.isInProjectRole("VE: NOT IN USE",issue.get("Project"))) || (issue.get("customfield_10111")?.any{it.value == "VK: NOT IN USE"} && currentUser.isInProjectRole("VK: NOT IN USE",issue.get("Project"))) || (issue.get("customfield_10111")?.any{it.value == "VS: Level 2, Role 1"} && currentUser.isInProjectRole("VS: Level 2, Role 1",issue.get("Project"))) || (issue.get("customfield_10111")?.any{it.value == "RD: Level 5, Role 1"} && currentUser.isInProjectRole("RD: Level 5, Role 1",issue.get("Project"))) || (issue.get("customfield_10111")?.any{it.value == "RZP: Level 4, Role 2"} && currentUser.isInProjectRole("RZP: Level 4, Role 2",issue.get("Project"))) || (issue.get("customfield_10111")?.any{it.value == "RZS: Level 4, Role 2"} && currentUser.isInProjectRole("RZS: Level 4, Role 2",issue.get("Project")))