Business Central Power Automate Document Approvals – Cancel
Have you noticed when using Power Automate for BC document approvals you have the same approval buttons? One for sending and one for cancelling. The sending one works fine. Cancel on the other hand isn’t doing what we need. The approvers will still have an outstanding approval and the flow will keep waiting to run. Eventually when it does run it will fail as the request has been cancelled BC side. If no one approves and the rest of the flow doesn’t run then you have a flow run ongoing until it expires…These things are ok. I just think it makes the administration more difficult.

My goal with this post is to have the standard cancel action to actually cancel my Power Automate approval and my Power Automate flow run. Full housekeeping . Let’s cover some basics first:


With Power Automate you might be using different methods to get the approval dealt with – MS Approvals, Teams, Outlook, other. I will look to solve the MS Approvals scenario as it’s the most common.
So what do we need? Well first thing is a record of information from Power Automate back in BC. So for starters a table extension to the “Workflow Webhook Entry” table. This is where the data from the “Flow Entries” page (above) lives. We have 3 fields as I want to capture details on numerous attributes so I can cancel all the relevant parts.
tableextension 50100 PA_Approvals extends "Workflow Webhook Entry"
{
fields
{
field(50100; "Power Automate Approval ID"; Guid)
{
Caption = 'Power Automate Approval ID';
DataClassification = CustomerContent;
}
field(50101; "Power Automate Flow ID"; Guid)
{
Caption = 'Power Automate Flow ID';
DataClassification = CustomerContent;
}
field(50102; "Power Automate Run_ID"; Text[100])
{
DataClassification = CustomerContent;
Caption = 'Power Automate Run ID';
}
Alongside our new fields we are going to need an API page so we can make updates to the BC data. Just showing the properties as this is the important part. I made only my new fields editable
page 50100 PA_Approvals
{
APIGroup = 'jaGroup';
APIPublisher = 'ja';
APIVersion = 'v2.0';
Caption = 'paApprovals';
DelayedInsert = true;
EntityName = 'paApproval';
EntitySetName = 'paApprovals';
PageType = API;
SourceTable = "Workflow Webhook Entry";
ODataKeyFields = "Workflow Step Instance ID";
ModifyAllowed = true;
InsertAllowed = false;
Permissions = tabledata "Workflow Webhook Entry" = RIMD;
More AL DEV follows but let’s tackle the Power Automate Document approval next. Start off with the standard template for whichever document you need this for. I’ve chosen Purchase Orders.

The compose action “Workflow ID” contains the expression workflow()?[‘name’] so that I can record the GUID of the workflow. The “Workflow Run ID” contains the expression workflow()?[‘run’][‘name’] so that I can record the text string name of the flow run. The template for a BC document approval comes with a “Start and Wait” approval. I’ve removed this and added the “Create an approval” so that I can find out and record the ID of the created approval. You then need the “Wait for an approval” so the flow has the response. The final change/addition is the HTTP step.


So all that remains is the cancellation. For the data in BC to end up back in Power Automate a codeunit is required:
codeunit 50100 PA_CancelApproval
{
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Workflow Webhook Management", 'OnCancelWorkflow', '', false, false)]
local procedure CancelPowerAutomateApprovalEntry(WorkflowWebhookEntry: Record "Workflow Webhook Entry")
var
begin
if IsNullGuid(WorkflowWebhookEntry."Power Automate Approval ID") then
exit
else
SendToFlow(WorkflowWebhookEntry."Power Automate Approval ID", WorkflowWebhookEntry."Power Automate Flow ID", WorkflowWebhookEntry."Power Automate Run_ID");
end;
local procedure SendToFlow(ApprovalID: Guid; FlowID: Guid; RunID: Text)
Var
client: HttpClient;
cont: HttpContent;
header: HttpHeaders;
response: HttpResponseMessage;
Jobject: JsonObject;
tmpString: Text;
Begin
Jobject.Add('ApprovalID', ApprovalID);
Jobject.Add('FlowID', FlowID);
Jobject.Add('RunID', RunID);
Jobject.WriteTo(tmpString);
cont.WriteFrom(tmpString);
cont.ReadAs(tmpString);
cont.GetHeaders(header);
header.Remove('Content-Type');
header.Add('Content-Type', 'application/json');
client.Post('<Add your URL here', cont, response);
end;
The idea here is that another Power Automate flow will be setup to receive a POST. Note that you will need to add the URL to your Power Automate flow for this to work.

Here are the main steps to the flow. Note that the final step is a custom connector. Use this excellent blog to create/download the connector: Everything to know about Power Automate REST API to manage and administer your flows – Mohamed Ashiq Faleel








Use of a webhook could be done here as well. I opted not to use that as you need something in place to renew the webhook and it would have to POST the information to flow I chose anyway. Hardcoding the endpoint is a bit but it is simple
This was originally posted here.
*This post is locked for comments