Possible Solution for a Multi-approval field?

Issue #117 resolved
Will created an issue

Would you have a recommendation using the Toolbox's features to create a custom field that will allow a set of users located around the world (4 people) to 'sign-off' on a ticket, and when all of them have signed off the issue will display an 'Approved' flag or something like that?

Possibly integrate clever notifications to these users too if feasible. There is no particular order in which these users need to approve. Currently we have a custom checkbox field which each region represented as an option. Users visit the issue, click edit, checkmark their region, then save. This feels clunky and I think there may be a better way using Workflow Toolbox.

Official response

  • Fidel Castro Armario repo owner

    Now, I explain how to implement the solution in 9 steps:

    1) Create 5 project roles: "Region A Approval", "Region B Approval", "Region C Approval", "Region D Approval" and "Bypass Approvals".

    2) Create a check-boxes custom field called "Approval", with 4 options: "Region A", "Region B", "Region C" and "Region D". In this example "Approval" custom field has field code %{14203}, but it depends on each particular JIRA instance.

    3) Include custom field in view screen, but not in create and edit screens.

    4) Insert 2 reflexive transitions (same source and destination status) in each of the statuses from which approvals are allowed to be done: "Approve Issue" and "Revoke Approval".

    5) Insert "Boolean condition with math, date-time or text-string terms" condition in all "Approve Issue" transitions, using the following configuration: Condition-Approve.png

    Boolean expression used is:

    isInRole(%{00020}, "Region A Approval") AND "Region A" not in %{14203} OR isInRole(%{00020}, "Region B Approval") AND "Region B" not in %{14203} OR isInRole(%{00020}, "Region C Approval") AND "Region C" not in %{14203} OR isInRole(%{00020}, "Region D Approval") AND "Region D" not in %{14203}

    Notice that:

    • %{00020} is field code for Current user virtual field.
    • %{14203} is field code for Approvals custom field.

    6) Insert "Set a field as a function of other fields" post-function in all "Approve Issue" transitions, using the following configuration: Post-function-Approve.png

    Setting rules used are:

    [isInRole(%{00020}, "Region A Approval") AND "Region A" not in %{14203}]+ Region A

    [isInRole(%{00020}, "Region B Approval") AND "Region B" not in %{14203}]+ Region B

    [isInRole(%{00020}, "Region C Approval") AND "Region C" not in %{14203}]+ Region C

    [isInRole(%{00020}, "Region D Approval") AND "Region D" not in %{14203}]+ Region D

    7) Insert "Boolean condition with math, date-time or text-string terms" condition in all "Revoke Approval" transitions, using the following configuration: Condition-Revoke.png

    Boolean expression used is:

    isInRole(%{00020}, "Region A Approval") AND "Region A" in %{14203} OR isInRole(%{00020}, "Region B Approval") AND "Region B" in %{14203} OR isInRole(%{00020}, "Region C Approval") AND "Region C" in %{14203} OR isInRole(%{00020}, "Region D Approval") AND "Region D" in %{14203}

    8) Insert "Set a field as a function of other fields" post-function in all "Revoke Approval" transitions, using the following configuration: Post-function-Revoke.png

    Setting rules used are:

    [isInRole(%{00020}, "Region A Approval") AND "Region A" in %{14203}]- Region A

    [isInRole(%{00020}, "Region B Approval") AND "Region B" in %{14203}]- Region B

    [isInRole(%{00020}, "Region C Approval") AND "Region C" in %{14203}]- Region C

    [isInRole(%{00020}, "Region D Approval") AND "Region D" in %{14203}]- Region D

    9) Insert "Boolean validator with math, date-time or text-string terms" validator in transition "Start Development" with the following configuration: Start-Development-Validator.png

    Boolean expression used is:

    numberOfSelectedItems({14203}) = availableItems({14203}) OR isInRole(%{00020}, "Bypass Approvals")

Comments (16)

  1. Fidel Castro Armario repo owner

    I have some questions before describing the whole solutions:

    1. How are the 4 users who 'sign-off' the issue determined? Do you use 4 different project roles, or are they preset in certain custom field?
    2. Is the 'sign-off' done when the issue is in certain unique status? In case the issue can be in more than one status, how many?
    3. Do you find desirable to restrict certain transitions until the issue has been approved (i.e, signed-off by the 4 users)?
  2. Will reporter

    How are the 4 users who 'sign-off' the issue determined?

    Currently they are just in a single jira group titled 'global_approvers'

    Is the 'sign-off' done when the issue is in certain unique status? In case the issue can be in more than one status, how many?

    They may come in and approve (OR revoke their approval by un-checkmarking) during several (3 or so) statuses. At some point when they've all approved the issue will go in to a new status, 'In Development' after-which they will no longer be involved.

    Do you find desirable to restrict certain transitions until the issue has been approved (i.e, signed-off by the 4 users)?

    That would really good but not required.

  3. Fidel Castro Armario repo owner

    More questions:

    1. May "global_approvers" group contain more than 4 users? In affirmative case, is allowing any 4 different users from the group to 'sign-off' correct?
    2. Do you find suitable a solution where you add 2 reflexive transitions (same origin and destination statuses) called "Approve issue" and "Revoke approval" to each 3 statuses (i.e., 3 x 2 = 6 additional transitions)? These transitions only would be visible to users in groups "global_approvers".
    3. If you are planing to let issue go to "In Development" status only when it's approved, perhaps the answer to question 3 in my former post should have been "yes", doesn't it?

    By the way, I recommend you to use a project role and assign it to group "global_approvers".

    In workflows it's much better to work with project roles, instead of groups, since it greatly improve workflow reusability in other projects, simply by assigning the project role to another group.

    As a general rule of thumb: Don't mention groups in your workflows (conditions, validators and post-functions). Use project roles instead.

  4. Will reporter
    1. Yes. There are 4 regions, but there may be multiple users per region, any one of which can check-mark their region as approved. If a second user from Region A visits the issue and notices their region is already approved, they will just ignore and take no action. Sign-off is an honor system, we trust no one person will check-mark all regions or the wrong region. It works so far but may be prone to error. If needed, I wouldn't mind breaking these groups in to Region A approvers, Region B approvers, etc. As well as separate approval custom fields per region.

    2. I wouldn't mind creating these validated transitions

    3. Correct. But sometimes a region will be unneeded or unresponsive so there needs to be at least one person or project role on our local tea that can bypass any hard coded requirements for all reigions to have signed-off to proceed to 'In Dev.'

    Thanks for your tips on project roles, too.

  5. Fidel Castro Armario repo owner

    Two questions:

    1. May I suppose that usually each approver only belongs to one region? In case a user belongs to more than one region, he will approve at once all the regions he belongs to.
    2. Do you prefer I implement the solution using project roles (then you will be able to assign groups to project roles), or user groups directly in the workflow?
  6. Will reporter

    Approvers would only belong to one region.

    Using project roles would be preferable now that you've described the benefit of them over groups.

  7. Fidel Castro Armario repo owner

    Now, I explain how to implement the solution in 9 steps:

    1) Create 5 project roles: "Region A Approval", "Region B Approval", "Region C Approval", "Region D Approval" and "Bypass Approvals".

    2) Create a check-boxes custom field called "Approval", with 4 options: "Region A", "Region B", "Region C" and "Region D". In this example "Approval" custom field has field code %{14203}, but it depends on each particular JIRA instance.

    3) Include custom field in view screen, but not in create and edit screens.

    4) Insert 2 reflexive transitions (same source and destination status) in each of the statuses from which approvals are allowed to be done: "Approve Issue" and "Revoke Approval".

    5) Insert "Boolean condition with math, date-time or text-string terms" condition in all "Approve Issue" transitions, using the following configuration: Condition-Approve.png

    Boolean expression used is:

    isInRole(%{00020}, "Region A Approval") AND "Region A" not in %{14203} OR isInRole(%{00020}, "Region B Approval") AND "Region B" not in %{14203} OR isInRole(%{00020}, "Region C Approval") AND "Region C" not in %{14203} OR isInRole(%{00020}, "Region D Approval") AND "Region D" not in %{14203}

    Notice that:

    • %{00020} is field code for Current user virtual field.
    • %{14203} is field code for Approvals custom field.

    6) Insert "Set a field as a function of other fields" post-function in all "Approve Issue" transitions, using the following configuration: Post-function-Approve.png

    Setting rules used are:

    [isInRole(%{00020}, "Region A Approval") AND "Region A" not in %{14203}]+ Region A

    [isInRole(%{00020}, "Region B Approval") AND "Region B" not in %{14203}]+ Region B

    [isInRole(%{00020}, "Region C Approval") AND "Region C" not in %{14203}]+ Region C

    [isInRole(%{00020}, "Region D Approval") AND "Region D" not in %{14203}]+ Region D

    7) Insert "Boolean condition with math, date-time or text-string terms" condition in all "Revoke Approval" transitions, using the following configuration: Condition-Revoke.png

    Boolean expression used is:

    isInRole(%{00020}, "Region A Approval") AND "Region A" in %{14203} OR isInRole(%{00020}, "Region B Approval") AND "Region B" in %{14203} OR isInRole(%{00020}, "Region C Approval") AND "Region C" in %{14203} OR isInRole(%{00020}, "Region D Approval") AND "Region D" in %{14203}

    8) Insert "Set a field as a function of other fields" post-function in all "Revoke Approval" transitions, using the following configuration: Post-function-Revoke.png

    Setting rules used are:

    [isInRole(%{00020}, "Region A Approval") AND "Region A" in %{14203}]- Region A

    [isInRole(%{00020}, "Region B Approval") AND "Region B" in %{14203}]- Region B

    [isInRole(%{00020}, "Region C Approval") AND "Region C" in %{14203}]- Region C

    [isInRole(%{00020}, "Region D Approval") AND "Region D" in %{14203}]- Region D

    9) Insert "Boolean validator with math, date-time or text-string terms" validator in transition "Start Development" with the following configuration: Start-Development-Validator.png

    Boolean expression used is:

    numberOfSelectedItems({14203}) = availableItems({14203}) OR isInRole(%{00020}, "Bypass Approvals")

  8. Will reporter
    • changed status to open

    Hi, I marked this resolved but there's been a change and I'd like to simplify this for a second project.

    This second related project reuses the same fields, "Regional Sign-off (A)" (and we have A, B, C, D regions.) That's four yes/no radio button fields

    Anyone with access to the tracker can update them and doesn't require any special access/role/group membership. I just want to create a condition that unless all 4 are marked 'Yes' that the issue cannot proceed to the In Progress status from the New status.

  9. Fidel Castro Armario repo owner

    In this case you only have to implement step 9 of former solution, i.e., you should insert "Boolean validator with math, date-time or text-string terms" validator in transition "Start Progress" with the following configuration boolean expression:

    numberOfSelectedItems(%{nnnnn}) = availableItems(%{nnnnn})

    replacing nnnnn with the corresponding field code of "Regional Sign-off (A)" custom field in your particular JIRA instance.

  10. Will reporter

    I forgot to mention that this check should only be made if issuetype = 'Change' since other issuetypes use the same workflow but don't require the condition and don't use the fields on their screens. We have 4 fields, one per region. So there is Regional Sign-off (A) Regional Sign-off (B) Regional Sign-off (C) Regional Sign-off (D) ...all in one issue that can each be marked as 'Yes' at any time by editing the issue. (Done when they learn a region has signed off)

    I should add that the system "None" option has been removed from these radio buttons by making them Required fields and setting their default values to "No". Seems that the markup you provided just checks if one field has been set to anything besides null.

    I don't want Bug type issues to be affected by the condition, they should remain allowed to proceed.

  11. Fidel Castro Armario repo owner

    Just use the following boolean expression:

    %{00014} = "Change" IMPLIES (%{aaaaa} = "Yes" AND %{bbbbb} = "Yes" AND %{ccccc} = "Yes" AND %{ddddd} = "Yes")

    replacing aaaaa, bbbbb, ccccc and ddddd with the corresponding field codes for "Regional Sign-off (A)", "Regional Sign-off (B)", "Regional Sign-off (C)" and "Regional Sign-off (D)".

  12. Will reporter

    Perfect ,thanks! I had worked out all but "%{00014} = "Change" IMPLIES (..."

    I will get the hang of this one day. Thanks for your support.

  13. Fidel Castro Armario repo owner

    You could also use the following equivalent expression:

    %{00014} != "Change" OR (%{aaaaa} = "Yes" AND %{bbbbb} = "Yes" AND %{ccccc} = "Yes" AND %{ddddd} = "Yes")

    since A IMPLIES B is equivalent to !A OR B

  14. Log in to comment