This is something I'm asked on most projects when we get to the topic of approvals.
- Client: "WOW these BC approval workflows look good, and I expect the approval will be automatically delegated if the user has their outlook out-of-office on, right?"
- Me: "About that..."
Contina does a good effort on managing out-of-office Setting up Approval Sharing, but it's a config that's inside BC, and it doesn't cover all document types.
Most users simply expect out-of-office to be something you setup once in outlook and it's shared to all the other MS apps.
I've confessed in the past that I rather use BC approvals over Power Automate approvals. Possibly that's driven by me simply being able to setup and test anything from simple to big hairy approvals in BC a lot faster than in PA.
Yes, there is an automatic delegation in BC workflows. It works on a count down, it will auto delegate after x many days. But it is very rarely used, if ever. Why? Consider the real word situation. Someone asked you to approve something, but you can't right away. Could be a number of reasons why; you need to look something up, check with someone who is away etc etc. Maybe you just need to sit on it for a bit. The last thing you want is the approval going to someone else in these situations!
To solve the problem above I wanted to take a blended approach; use BC for the approvals and PA for its low-code access to Exchange Online / Outlook for the out of office status of a user.
Solution
- Create Approval workflow of any kind in BC [Config]
- Create API query for approval entries & users emails [AL code]
- Create API page for the 'delegate' action as an OData bound action [AL code]
- Create a PA flow that checks the Outlook Out-of-Office status of the approver of open approval entries and delegates these [Low-code]
The key part here was to have PA fetch only the open approval entries and then loop though and only delegate those where the approval user was sending automatic replies / had set out-of-office.
This solution was put together with help from my good buddy Lee Noble who sorted the code for the OData bound action. Thank you Lee!
BC Approval
I've kept it simple in this example, but because the delegation simply works based on approval entries created it should work for any kind of approval you (or you customers) dream up!
I've used the standard template for Purchase Order approval (because it takes only a few clicks to active)!
Vanilla PO Approval from the standard template |
Bare bones approval user setup - just to highlight a few important points. As you may know only the Approval Admin can delegate 'anything' so be sure to create the PA flow that's going to be doing delegating in the name of that account.
It's possible that the OData bound / API calling of 'delegate' wont have the same restriction, but I've yet to test that.
Lets take a moment to welcome our new CDX friends Alan and Alicia |
Just to cover this process end-to-end. Here are the approval entries for a PO, for more that 100 (my purchase limit as the 'ADMIN' user). So 2 lines, 1 approved by me and one sits with my manager (the user set in the Approver ID column in the Approval User Setup page).
So this approval sits with Alan.. But what's this, seems he is away for a bit..
You don't know Mordac? |
AL Objects
Query API
To make Power Automate work really well with BC its normally necessary to expose more fields than those you get in the standard API 2.0. Thankfully that's very easy to do.
The table Approval Entries has what we need, in terms of the open approvals and the ApproverID, which is the BC user name.
To make my PA flow all the more easy, I have created a Query API, and joined in the User Setup table to make the users email addresses from the Approval User Setup Page (User Setup Table) available also.
OData Bound Action API
This was for me a step further into AL coding than I had managed before, and I got some help! Following the advice from Yun Zhu got me part of the way, but it was Lee who sorted the final working code which is shown below.
With the objects published to your sandbox you can now
- View the Approval Entries using 'Get Record'
- Trigger the delegate action using 'Run Action'
Download the source code and example complied app here: andywingate/D365BC-Out-of-Office-PA-flow
PA Flow
Here is a quick look at the simple PA flow I created. This is just an example based on a scheduled flow. You could use 'When a record is created' or a combination.
I quite like the schedule as it keeps it simple and works for the 'now' situation with a small delay. But also works if an approver goes on leave after the approval request was created. So its a 1 flow catch all.
PA approval that will delegate any open approvals if the Approval user has their out of office message on |
- Recurrence: Not much explanation needed here, just set to run as often as makes sense. Every 5 mins or something like that.
- Find Records: Here im using the query with an OData filter to fetch all the Approval Entry lines with status open
- Get mail tips: For each row of the open approvals, now we need to check if the Approval user is away or not. The best way to do this is by getting the mail tips. I added the Approval users email address in the query so its part of the row.
- Compose: The output from 'Get mail tips' is an array which a bit of a pain, we just want to see if there are any or not. So after a lot fiddling around this is what I've found to work.
['automaticReplies/message']
- Condition: Now we check if the automatic replies message is blank or not. If it is not blank, then the person is away and we need to delegate. If it is blank, then we leave the approval entry alone. The 'Outputs' was simply the dynamic content from the Compose step.
- Run action: Finally if we do want to delegate then we can pass the original systemId from the Find records into the OData bound action
Here are 3 approval entries. I've set Alan (ALANS) as out of office but not Alicia (ALICIAT)
I'll run the flow with a manual test. We expect 2 of the three to be delegated but not the last one.
An example where the approver was not away (ALICIAT); the flow ran but the condition returned false; so no delegation.
One of the other lines:
Here it was for Alan, who is away and the line got delegated.
Here is an export of the simple PA flow if you want to check that out: D365BC-Out-of-Office-PA-flow/BCOOODelegation_20241110164045.zip at main · andywingate/D365BC-Out-of-Office-PA-flow
Summary
I hope you find this useful, please give it a try and consider sharing any more interesting flows using the base tools I've provided here.
What do you think?
Please let me know your thoughts in the comments
Connect or follow me on LinkedIn to get all my updates Andrew Wingate | LinkedIn