Hi there AppWorks fans,
Welcome to a new installment of AppWorks tips.
For this week we continue our customer case post from last week…
Case description: Create an approval flow which makes it possible for a pre-selected approvers list to “sign-off” the requested entity instance as ‘Approved’. The approvers should retrieve sign-off tasks in parallel-mode, and it should be possible to check if a certain number of users already approved within the approval due-date.
Last week we made the final solution work from end to end, so nothing more to do!? For sure not as there is a lot of low-hanging fruit to improve, and we always need to clean up and make things nice (we as good developers!).
Let get right into it…
First a plan…What do we want to improve? Let’s click again through the solution crafted so far and write down the improvements:
- Implementing a due-date for the final approval task (otherwise it might never end!)
- Make sure the ‘Approval’ flow only starts once as we can now start it again and again…
- Hide the ‘Complete task’ action once clicked by the approver, so it can only be clicked once (we now get an error the second time…Not very nice!?)
- Hide the normal ‘Task’ actions in the ‘Teams tasks’ list when marking a task
- Style the BPMs with colors and comments
Implementing a due-date for the approval tasks
We keep it simple with an implementation where we just check if the parent ‘Approvals’ task isn’t finished on time, we hand it over to the ‘Process initiator’ with a notification task where we ask to restart the approval flow.
We’ve already created a post out of such a functionality, so let’s plot that post onto this use-case with a BPM change like this:
In quick steps:
Right-click the ‘Approvers’ activity and group it as ‘Until’
Add the
true()
condition for the ‘Until’ group in the properties. This way it will continue till it breaks, but we break it directly in the first run!Add a ‘Delay’ construct within the properties (‘Duration’ tab) a static value of 1 minute (for now!)
Add those two “End” constructs and make them of type ‘Break loop’ in the properties
The ‘Updatetodo’ is a webservice call (from the exposed ‘todo’ webservices BB) with a mapping like this. For now, we just set a (misused) property value to a ‘static’ value, but you can make it as fancy as you like (probably something with a ‘todo_status’ property!?)
The ‘Notify on re-approval’ activity is a manual task (by default) assigned to the flow initiator with the layout ‘DefaultLayout’ of the ‘todo’ entity (like the ‘Approvers’ task). The manual activity only has one extra condition in the properties. We only require this task when the ‘todo’ instance is not approved,…This is when the (misused) ‘todo_name’ property doesn’t match ‘APPROVED’ (check that small decision icon on the activity):
not(contains(ns2:UpdatetodoOutput/ns2:UpdatetodoResponse/ns3:todo/ns3:todo_name/text(), "APPROVED"))
Make sure the arrow flows are connected to the correct constructs!
Let’s do a save, a publication and some tests with PIM in the background…
Test | Outcome | DONE? |
---|---|---|
Start approval flow and don’t do anything | - After 1 minute we retrieve a personal task in the process initiator inbox - The ‘todo_name’ property is unchanged |
✅ |
Start approval flow and all selected approvers do a ‘Complete task’ | - If done within 1 minute it should be fine - The ‘todo_name’ property is set to ‘APPROVED’ |
✅ |
Start approval flow and not all selected approvers do a ‘Complete task’ | - After 1 minute we retrieve a personal task in the process initiator inbox - The ‘todo_name’ property is unchanged |
✅ |
Nice…Next improvement…
Make business rules fancy with conditions
Let’s start to make sure the ‘Approval’ flow only starts once! For this to happen we go back to the ‘todo’ entity where we jump into the already defined rule ‘a_start_approval_flow’. We’ll add a condition which looks like this (again a misuse of the ‘todo_name’ property, but you should be able to come up with something nicer by now!):
The next thing we need to do is updating the ‘todo_name’ as first step in the approval flow. Jump to the BPM modeler and add a new activity which calls the ‘Updatetodo’ webservice…
…with a mapping from the ‘rootEntityInstanceId’ to the ‘ItemId’ and a hardcoded ‘todo_name’ value:
Now, let’s publish the entity together with the updated BPM and see what happens in runtime!?
…
It works almost! The only thing which is not working is a refresh of the page, so the button is removed. When you refresh the page yourself, it’s working fine. Why is that? Well, because our BPM is a ‘Long lived’ flow there is no direct interaction with the runtime environment. On the other hand we are not allowed to make it ‘Short lived’ because of the manual task! Now what? Back to the action rule where we have the option to do some page redirection like this:
After a publication and a retest, it’s working fine!
Yes I know…when you open the entity and update the ‘Name’ field, you get the action back, but it’s just a demo…Normally we would use a fancy property which is not updatable like this!
Next…
Hide the ‘Complete task’ action
When we have our task available and open it from the ‘Teams’ inbox, we can click the ‘Complete task’ action, but we can hit it again and again with nasty errors (because our name is already “linked” on the ‘Approvers’ list). Let’s also update this action rule, so it’s only visible once! For this we go to the related ‘lifecycleTask’ entity where we update the ‘a_complete_task’ rule with a check if our current user ID is not yet available in the list:
For you to copy:
!(item.task_approvers[].Properties.UserId).contains(User.Properties.UserId)
You also see I’m moving back to the previous location as I can’t stay at the task. If the last ‘Approver’ from the list did an approval, the task will be gone and we end-up with an error. This also solves the issue on the action button which is gone from the view. So, if you reopen the task (when you’re not the last approver), you won’t see that button again!
Other low-hanging fruit
Let’s continue with some other nice improvements like hiding the ‘Task’ actions in the ‘Teams tasks’ list when marking a task:
We don’t need these actions (except for the ‘Open’ action) as the task gets completed by our BPM. A “Security” BB on the ‘LifecycleTask’ entity will do the trick in this case (the failure-approach is in the comment below!). We just apply the ‘Identity User’ role (as all users are applied with it) and make sure we only make available the relevant actions. The only disadvantage is the first ‘Open’, then ‘Approve’ approach! It’s what it is as we are limited with capabilities of the platform.
I would expect to have a “List” BB available on the ‘LifecycleTask’ entity where I could configure the action bar to be shown, but it’s not available. Then I tried to create one on my own (with a ‘all_tasks’ List BB), but never made it till a level where I could filter out the ‘Team’ tasks!? I also placed this list in the ‘Category’ of ‘My Inbox’, but then things really start to brake. This is how it looked, but this approach was not working…Maybe an enhancement on the product to have a default list BB available on the LifecycleTask’ entity?
Next one!
Maybe you’ve noticed the ‘IN_PROGRESS’ value isn’t restored with the original value when the BPM gets ‘Aborted’ after the approvals were not done on time!?…Have a check again! 👀
This is a BPM issue in the approval flow itself which we introduced ourselves with the first due-date improvement! We added a new activity where we update the ‘todo’ entity instance with name ‘IN_PROGRESS’, but we first need to save that name with a ‘Readtodo’ service call; save it in a process variable and restore it when timer expires. So like this:
The crafting for those 2 activities is done like this…
Readtodo
We first make a mapping from the ‘rootEntityInstanceId’ in the process properties to the ‘ItemId’ of the webservice call. This provides us a response which we can read from the ‘Post Assignments’ tab to set a process variable…WAIT…I have a brain crash!! We don’t need a process variable as we can just get a grip of this response directly from the ‘Updatetodo Original’ call….NICE! So, leave only this first mapping and continue…
Updatetodo ORIGINAL
Well…It wouldn’t get as simple as this screen:
Nice…Let’s save, publish, and do a first test! My timer is set back to 1 minute, so I can wait… 🤗
That’s a green flag for me!
… What else? There is just one thing left! Cleaning up and commenting our BPMs…
This looks much nicer…correct?
This will be the other final BPM:
The color coding I use:
- Mapping activity: WHITE
- Sub process activity: PURPLE
- Service activity (default): BLUE
- Manual activity: ORANGE
The template text I use:
1
2
3
4 Name: bpm_dynamic_approval_flow
Description: This BPM handles a dynamic approvals list with the related 'Identity Package' entities.
Creator: Antal Bos
Date: 27/07/2021
“Case closed” with a nice ‘DONE’ this time. We improved our customer case, so nasty errors are gone and things work more intuitive for the end-user in runtime. These 2 posts showed you how to implement a customer case, and the approach to solve things. You could also clearly see the typical development cycle where we first make sure it all works end-to-end and finally we improve things in the end. Nothing more to say…We learned a lot again of the capabilities of the platform, and it’s all explained for you to consume from…If you have any comments on other nice improvements to show…Let me know. Happy low-coding, and I see you in the next post, next week!
Don’t forget to subscribe to get updates on the activities happening on this site. Have you noticed the quiz where you find out if you are also “The AppWorks guy”?