Acumatica · Customization

Acumatica AR Module — Extension Patterns

Acumatica AR Module — Extension Patterns is one of those Acumatica customisations that every team eventually needs and almost no team does well the first time.

John Kihiu12 min read

AR customizations tend to cluster around two things: getting money applied correctly against invoices, and calculating something — commission, finance charges, credit exposure — that the stock module doesn't compute out of the box. Both are well-supported extension scenarios once you know which DAC actually owns the field you need.

Core DACs and screens

ARInvoice (Invoices and Memos, AR301000) and ARPayment (Payments and Applications, AR302000) are the transactional core, with ARAdjust linking a payment to the invoices it settles. Customer master data is on Customer (extending BAccount) and CustomerClass. The graphs are ARInvoiceEntry and ARPaymentEntry; commission and credit-limit logic typically extends the former since it's evaluated at invoice release time.

Extension points

A PXGraphExtension<ARInvoiceEntry> gives you the usual set: PXCacheExtension<ARInvoice> for new fields, RowSelecting to compute display-only values, RowPersisting to enforce hard rules before save, and action overrides for anything that changes the meaning of Release or Reverse. Credit limit checking already exists in stock Acumatica (the customer's credit limit and terms are checked at order and invoice time) — a common mistake is rebuilding that check from scratch instead of extending the existing hold logic.

Check CustomerCreditVerification before writing your own hold logic

Acumatica already has a customer credit hold mechanism tied to credit limit and days-overdue thresholds. If the ask is "block new invoices for customers over their limit," extend the existing verification rather than adding a parallel RowPersisting check — two systems disagreeing about whether a customer is on hold is a support ticket waiting to happen.

A realistic scenario: commission calculation

Sales commission is one of the most requested AR-adjacent customizations, and it's rarely a stock feature because every company's commission plan is different (tiered rates, salesperson splits, held-back percentages until payment clears). The common pattern is a custom DAC holding commission rules per salesperson or item category, evaluated in a graph extension on ARInvoiceEntry at release time, writing to a custom commission ledger table rather than trying to force the number into an existing AR field.

C# · ARInvoiceEntry EXTENSION
public class ARInvoiceEntry_Commission_Extension : PXGraphExtension<ARInvoiceEntry>
{
    public PXAction<ARInvoice> calculateCommission;
    [PXUIField(DisplayName = "Calculate Commission")]
    [PXButton]
    protected virtual void CalculateCommission()
    {
        ARInvoice invoice = Base.Document.Current;
        if (invoice == null || invoice.Released != true) return;

        foreach (ARTran line in Base.Transactions.Select())
        {
            decimal? rate = CommissionRuleRepository.GetRate(line.SalesPersonID, line.InventoryID);
            if (rate == null) continue;

            var commission = new CommissionLedger
            {
                RefNbr = invoice.RefNbr,
                SalesPersonID = line.SalesPersonID,
                Amount = line.CuryLineAmt * rate / 100m,
                Status = "Pending"
            };
            CommissionLedgerView.Insert(commission);
        }
        Actions.PressSave();
    }
}

Writing to a dedicated ledger rather than a field on ARTran keeps commission history intact even if the invoice is later corrected or reversed — you want an auditable record of what was calculated when, not a value that gets silently overwritten.

Multi-currency and write-offs

Anything touching ARAdjust needs to account for currency: an invoice in EUR paid by a check drawn against a USD cash account goes through currency conversion at the payment's rate, and rounding differences get written off automatically within a configurable tolerance. Customizations that add custom write-off logic (say, auto-writing off small balances under a threshold specific to a customer class) should hook the existing write-off tolerance mechanism rather than compute their own rounding — Acumatica's multi-currency handling has enough edge cases that duplicating it is rarely worth the risk.

Testing considerations

Test AR extensions against at least one multi-currency customer and one customer near their credit limit — these are the two conditions that most often expose a gap between what a customization assumed and what the module actually enforces. A commission calculation that works cleanly on domestic-currency test data can produce silently wrong numbers once a foreign-currency invoice runs through it.

Wrapping up

AR extensions succeed when they treat the module's existing credit, currency, and application logic as infrastructure to build on rather than obstacles to route around. The recurring mistake is duplicating logic Acumatica already enforces instead of hooking into it, which produces two sources of truth that inevitably drift apart.

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.