Workflow · Workflow

Acumatica Workflow — Banking Transaction Approval

Acumatica Workflow — Banking Transaction Approval is one of the most common workflow customisations in Acumatica.

John Kihiu12 min read

Banking approval covers two genuinely different things clients ask for under the same name, and conflating them produces the wrong workflow: approving payments (a cash outflow, usually a check or EFT batch on Payments and Applications, AP302000, or a Payment Batch) versus approving a change to bank account details (the vendor or employee's banking information itself, on the Vendor or Employee screen). Banking-fraud prevention actually depends on getting both right, and they need entirely separate workflows.

Payment release approval — the cash-outflow control

This is closest in shape to bill approval, but the trigger point matters more here: gating at bill entry doesn't stop a fraudulent payment if someone can still create and release a Payment directly. The control needs to sit on the Payments and Applications graph (APPayment DAC), gating the Release action itself, independent of whether the underlying bill was already approved:

C#
public static void Configure(WorkflowContext<APPaymentEntry, APPayment> context)
{
    var graph = context.Graph;
    graph.WithTransitions(transitions => transitions
        .AddGroupFrom<APPayment.status.Balanced>(g => g
            .Add(t => t
                .To<APPayment.status.PendingApproval>()
                .IsTriggeredOn(a => a.Actions.Release)
                .When(APPayment.curyOrigDocAmt.IsGreaterEqual(10000m)
                      | APPayment.paymentMethodID.IsEqual("WIRE")))  // wires always reviewed
            .Add(t => t
                .To<APPayment.status.Open>()
                .IsTriggeredOn(a => a.Actions.Release)
                .When(APPayment.curyOrigDocAmt.IsLess(10000m)
                      & APPayment.paymentMethodID.IsNotEqual("WIRE")))));
}

Note the payment method condition alongside amount — wire transfers are irreversible in a way checks and even EFT batches often aren't, and clients doing banking approval properly nearly always want every wire reviewed regardless of amount, not just large ones.

Bank detail change approval — the actual fraud vector

This is the control that matters more and gets built less often: a change to a vendor's or employee's bank account number is the classic business-email-compromise fraud pattern (an attacker impersonates a vendor, requests a "routine" bank detail update, then the next legitimate-looking payment goes to the fraudster's account). This isn't a document workflow at all — it's a workflow on the Vendor or Employee master's banking sub-tab, and it needs to freeze payment eligibility until a human independently verifies the change out-of-band:

C#
protected virtual void VendorBankAccount_RowUpdated(PXCache cache,
    PXRowUpdatedEventArgs e)
{
    var bankAcct = (VendorBankAccount)e.Row;
    var oldAcct = (VendorBankAccount)e.OldRow;
    if (bankAcct?.AccountNbr != oldAcct?.AccountNbr)
    {
        var vendor = Base.BAccount.Current;
        vendor.Status = VendorStatus.Hold;   // freeze until verified
        Base.BAccount.Update(vendor);
        // fire a workflow transition / notification to AP management
        // requiring callback verification before Hold is lifted
    }
}
This is the control most implementations skip entirely

I ask about this explicitly on every AP-heavy engagement because it's rarely in the original requirements — clients think about approving spend, not about approving changes to where the spend gets sent. If a vendor's bank details can change and the vendor's payment-eligibility status doesn't react to that change, you have a gap that has cost real companies real money. Bring it up even if it isn't asked for.

Segregation of duties applies even harder here

The person who processes AP data entry should not be the person who can clear a bank-detail-change hold — this is the same segregation-of-duties concern as vendor approval, but the stakes are higher because the failure mode is a completed wire transfer, not a mis-entered invoice. I set the clearing action's role restriction independently from general AP data-entry roles, and log the verification method (phone callback to a known number, not the number on the change request itself) as a required note before the hold can be lifted.

Wrapping up

"Banking approval" is really two workflows: payment release approval (amount- and method-sensitive, similar in shape to bill approval) and bank-detail-change approval (a master-data freeze triggered by any change to payment routing information, verified out-of-band). The second one is the actual fraud control and the one most implementations never build unless someone specifically asks — ask.

John Kihiu
Acumatica ERP Developer · Laravel Engineer

Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.