Wednesday, 1 February 2017

Approval Workflow Customization

Hi Everyone,

Today I want to share with you one important point about customization of automation approval workflow.

Firs of all please read this article on Stack Overflow to understand how Acumatica Approval works.
But here I would take Purchase Orders screen as example, because there we already have automation workflow configured.

In the article below, you may notices that all approval logic is encapsulated into the special Data View - EPApprovalAutomation. On the Purchase Orders form it is designed like this:
[PXViewName(Messages.Approval)]
public EPApprovalAutomation<POOrder, POOrder.approved, POOrder.rejected, POOrder.hold, POSetupApproval> Approval;

EPApprovalAutomation is just a class with multiple virtual methods that you can override and customize. 
So we can create our own approval workflow and define it in the graph or graph extension.
public class MyAppprovalAutomation
: EPApprovalAutomation<POOrder, POOrder.approved, POOrder.rejected, POOrder.hold,
       POSetupApproval>
{ }

public class POOrderEntry_Extension : PXGraphExtension<POOrderEntry>
{
       #region DataViews
       [PXViewName(Messages.Approval)]
       public MyApprovalAutomation Approval;
       #endregion
}

However, here we have one issue.
To encapsulate business logic, data view automatically subscribe for some events during initialization:
But because we have added new Approval Automation view, all events will be subscribed twice. That may lead to sending notifications twice or assigning approve twice.
To fix that issue, we need to unsubscribe base events manually. For this task we can use Initialize event of extension. But because some events are private, we have to use reflection.

public override void Initialize()
{
       Type type = Base.Approval.GetType();
       MethodInfo mi = type.GetMethod("Approved_FieldUpdated",
 System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
                  Base.FieldUpdated.RemoveHandler(BqlCommand.GetItemType(typeof(POOrder.approved)),
       typeof(POOrder.approved).Name,
       (PXFieldUpdated)mi.CreateDelegate(typeof(PXFieldUpdated), Base.Approval));
}
After that, only ours events would be executes.

Full code snippet is here:

Have a nice development!

No comments: