Acumatica · Customization

Acumatica CRM Module — Extension Patterns

Acumatica CRM 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

CRM in Acumatica sits closer to the sales and marketing process than the accounting core, and its customizations tend to reflect that — lead scoring, opportunity stage automation, and integrations with marketing tools, rather than the transaction-integrity concerns that dominate financial module work.

Core DACs and screens

Contacts and leads live on Contact and CRLead, business accounts on the shared BAccount, and opportunities on CROpportunity. Leads are worked from the Leads screen (CR301000 territory) and converted into contacts/opportunities through a conversion action; opportunities are managed on a screen typically numbered around CR304000/CR306000 depending on version, backed by graphs LeadMaint and OpportunityMaint.

Extension points

Custom fields on Contact/CRLead/CROpportunity are the most common and lowest-risk CRM customization — cache extensions surfaced on the relevant screen tabs. Stage automation (moving an opportunity forward or flagging it stale based on activity) is typically a graph extension reacting to changes on CROpportunity's stage field, or, increasingly, handled through Acumatica's business process automation / workflow configuration rather than hand-written event handlers, which is worth checking first since it changes less across upgrades.

Lead conversion is a multi-object operation — extend the action, not the DAC

Converting a lead creates or links a BAccount, Contact, and optionally a CROpportunity in one action. Custom logic that should run "when a lead becomes a customer" belongs in an extension of the conversion action itself, not in a RowPersisting handler on CRLead — the DAC's row events fire well before the conversion has actually created the downstream records you probably need to reference.

A realistic scenario: lead scoring

A common CRM ask: assign a numeric score to a lead based on a combination of fields (company size, source, engagement activity count) so sales can prioritize follow-up. This is typically a scheduled process or a save-time calculation on CRLead that writes to a custom score field, sourced from a rule table rather than hardcoded weights so marketing can tune it without a code change.

C# · LeadMaint EXTENSION
public class LeadMaint_Scoring_Extension : PXGraphExtension<LeadMaint>
{
    protected virtual void CRLead_RowPersisting(PXCache sender, PXRowPersistingEventArgs e)
    {
        var lead = (CRLead)e.Row;
        if (lead == null) return;

        int score = 0;
        score += ScoringRules.GetWeight("CompanySize", lead.NoOfEmployees);
        score += ScoringRules.GetWeight("Source", lead.LeadSourceDescr);
        score += ActivityLogRepository.CountActivities(lead.ContactID) * 2;

        var ext = sender.GetExtension<CRLeadExt>(lead);
        if (ext != null) ext.LeadScore = Math.Min(score, 100);
    }
}

Capping the score and pulling weights from a configurable rule table rather than an if/else chain means the scoring model can be retuned as marketing learns what actually predicts conversion, without touching code each time.

Integration with marketing and support tools

CRM is frequently the module wired into an external marketing automation or support ticketing tool, and that integration surface (webhooks, business events, or a REST/GraphQL connector) is a bigger source of "CRM customization" work than changes to the DACs themselves. Business Events (covered separately) are usually the right entry point for pushing lead/opportunity changes outward, rather than embedding an HTTP call directly in a graph extension's save path.

Testing considerations

Test lead conversion and opportunity stage changes with a lead that already has an existing matching BAccount (a returning company under a new contact) as well as a genuinely new one — conversion logic behaves differently when it's linking to an existing account versus creating one, and customizations built against only the "brand new company" case often mishandle the returning-company path.

Wrapping up

CRM extensions are comparatively low-risk to the financial ledger but high-value to the sales process when done well. Hook conversion actions rather than DAC row events for anything spanning lead-to-account-to-opportunity, keep scoring and automation rules configurable, and route outward integration through Business Events rather than inline calls.

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.