Power Automate Approvals: Majority / percentual approval
Approvals in Power Automate have two options: First to respond or Everyone must approve. There isn’t an option that states that the majority (or a percentage of the total approvers) must approve, like we had in SharePoint Designer workflows.
Does that mean that it isn’t possible to have a majority / percentual approval flow? Well, with a workaround it is. In this blogpost, I will describe how to configure this.
Basic Approval understanding
Before proceeding, it is advisable to have a good basic understanding of how approvals work in general.
You can check my blog series about Long running approvals for this, and specifically Part 2 in which I explain the technical (data) structure of approvals within Dataverse.
Licensing
We will be working with Dataverse, so you will need a premium Power Automate license for this or you need to use Logic Apps for the handling of the approval outcome.
Configuring majority / percentual approval process
Now that you know where the approval data is stored, it is time to proceed with configuring the majority / percentual approval process.
First, let me explain what we want to do in simple steps:
- Send out an approval to multiple approvers
- Process incoming responses
- Filter out unrelated approvals
- Calculate the percentage of responses against the number of approvals that have been sent out
- Check if majority / percentage has been reached
- Check majority outcome
We will be using a parent/child flow construction as described in the Long running approvals series.
Sending out the approval
Sending out the approval works just like any other approval you’ve configured.
In your parent flow, make sure to use the Start an approval action and not the Start and wait for an approval action, because we don’t want the parent flow to process the outcome of the approval immediately.
Configure the approval as you want, with multiple approvers. Also, make sure to select the Everyone must respond Approval type.
Identify approval
If you have multiple approval processes running in your environment and you want to make sure your child flow only processes this approval, provide an additional identifier in your approval title or approval details so that you can distinguish this approval from any other approvals in your child flow.
This identifier will always be visible, so don’t put any confidential or confusing information in this. Another option would be to add a non-fictive approver in the Assigned to (that should never approve), but that would mean a more complex configuration on the majority / percentage calculation.
If you have a separate environment for your approval process and this is the only approval flow in there, this step is not necessary.
Processing the responses
After the approval has been sent out, the child flow needs to be configured so that we can identify the response’s majority / percentual outcome.
As described in the Long running approval series, we need to trigger on an addition in the Dataverse table ‘Approval Responses’.
For this configuration to work properly, we need to initialize three variables at the start of our flow:
- varDesiredPercentage (float): fixed number which contains the majority / percentual number you want to reach (for 50%, you use 0.5)
- varReachedPercentage (float): will contain the percentage of approvals that has been reached so far.
- varOutcome (string): will contain the final outcome of the approval (approved/rejected)
Checking whether the approval should be processed
If you’ve provided an identifier to your approval as described in the previous section, you need to retrieve the approval details from the Approvals table and add a condition that filters out every approval that doesn’t match this identifier.
If the identifier isn’t found in the approval title/details, the flow should be cancelled:
This means that the flow does trigger on every response that has been given on an approval in your environment. Unfortunately, we cannot use a trigger condition for this, because the approval title/details are stored inside the Approvals table and not in the Approval Responses table.
Calculate percentage of responses
To get the percentage of all responses that have been given so far, we need to get the related approval data from two Dataverse tables:
- Approval Requests; which contains all the requests that have been sent out to each approver
- Approval Responses; which contains all the responses that have been given from each approver
To get the related approval requests and the related approval responses, you need to use the following Filter rows query for your List rows actions:
Approval Requests
msdyn_flow_approvalrequestidx_approvalid eq '<Approval Id Index>'
Approval Responses:
msdyn_flow_approvalresponseidx_approvalid eq '<Approval Id Index>'
Where <Approval ID Index> is selected from the Dynamic Content of your trigger.
If you divide the number of responses by the number of requests, you will get the percentage of responses. You can write this percentage (using the div() expression) into the varReachedPercentage variable:
Please note that your list rows count (using the length() expression) gets processed as an integer when using it anywhere else in your flow. You should specifically identify it as a float by using the float() expression as you can see in the screenshot above.
Determine the percentual outcome has been reached
Having a certain percentage of response doesn’t automatically mean that you’ve reached a majority response. When having 3 approvers and one of them responded with Approved and one responded with Rejected, you have reached 67% response, but no majority yet because the Approved / Rejected is split 50/50. So in this case, you still have to wait for the third approver to respond.
For this, you need to check the following:
- Has the configured desired percentage been reached?
- Does the number of certain responses outweigh the other response option? In this case it will be Approve and Reject.
To do this, I filtered the Approval Responses (from the List rows action) twice, using the Filter array action:
- Filter out Approve responses
- Filter out Reject responses
After that, I configured a nested condition setup as follows:
- Check if the desired percentage has been reached and a majority of Approve has been reached (by comparing the number of items from the filtered approved responses and the number of items from the filtered rejected responses). If so, the varOutcome variable will be set to Approve.
- If not, a second check will be performed to see if the desired percentage has been reached and a majority of Reject has been reached (the other way around as opposed to the Approve condition). If so, the varOutcome variable will be set to Reject.
- If not, it means that neither Approve or Reject has reached a majority yet and the flow needs to be cancelled.
Please note that you have to use the Approve / Reject outcomes as the Approval requires. So not Approved / Rejected.
Stop approval process after outcome has percentage has been reached
Since the Approval has been configured as ‘Everyone must approve’, the approval will keep running even though the configured percentage has been reached. That’s why we need to ‘trick’ the Approval by manually updating its data in Dataverse.
For this, we need to alter the Approvals table row that is related to this approval using the Update a row action.
The columns that needs to be updated are:
- Status: Inactive (from dropdown)
- Status Reason: Completed (from dropdown)
- Stage: Complete (from dropdown)
- Completed On: utcNow() (expression)
- Result: varOutcome variable
I’ve stripped out some columns for my screenshot because there are a lot of them. Otherwise the screenshot would become too large.
When this flow runs and a majority / percentual approval response has been reached, the Approvals row will be updated. After this, it won’t be possible to respond to the approval anymore. The approval request will be removed from the Approval Center in Power Automate and the Approvals app in Teams.
It will even automatically update the Adaptive Card in Outlook for you:
And when navigating to the related approval from any other type of link, the approver gets notified that the approval has already been completed as well:
Child flow configuration
If you’ve followed the steps above, your flow should like something like this:
Conclusion
This configuration may come in handy for those of you who want to have a majority / percentual approval process.
But keep in mind that you need to think about thoroughly it before configuring it. An few examples:
- Having only 2 approvers means that you may never have a majority outcome, because one approver can approve and the other can reject. That means that your response is split 50/50 and the flow won’t give you a definitive outcome for this.
- Sending an Approval to a Group instead of multiple people doesn’t work, because a Group Approval will always be processed as a ‘First to respond’ Approval. The first person from that Group who responds to the Approval will be the final one.