Customer master data looks like the simplest thing to extend in Acumatica — add a field, put it on a tab, done — but customer records touch credit control, tax calculation, pricing, and CRM simultaneously, which means a field-level customization here has more downstream readers than its scope suggests.
Core DACs and screens
Customer extends the shared BAccount DAC (the same base record backing vendors and CRM business accounts), maintained through the Customers screen (AR303000) via the CustomerMaint graph. CustomerClass drives defaults — terms, credit limit, GL accounts — that get copied onto a new customer at creation and can diverge from the class afterward, which matters when you're deciding whether a customization belongs at the class level or the individual customer level.
Extension points
A PXCacheExtension<Customer> is the standard way to add fields — a custom risk rating, an external CRM ID, an industry classification. Because Customer shares its base table with BAccount, and BAccount is also the base for Vendor and CRM business accounts, it's worth deciding explicitly whether a new field is customer-specific or actually belongs on the shared BAccount level — getting this wrong means the field either doesn't show up where a vendor-side or CRM-side screen expects it, or shows up everywhere including places it doesn't make sense.
A field added via PXCacheExtension<Customer> only appears on customer-context screens by default, which is usually what's wanted, but the underlying table storage is shared with BAccount. Before assuming a customization is isolated to AR, check whether the same business account is ever accessed through the Vendor or CRM business account screens (common when a company is both a customer and a vendor) and confirm the field's behavior there is intentional, not accidental.
A realistic scenario: custom credit review status
A common customer-management ask: a credit review workflow with more granularity than the stock credit hold (under review, conditionally approved, hard hold), driving different behavior at order entry than a binary hold flag allows.
public class CustomerMaint_CreditReview_Extension : PXGraphExtension<CustomerMaint>
{
#region CustomerExt
public class CustomerExt : PXCacheExtension<Customer>
{
[PXDBString(1, IsFixed = true)]
[PXStringList(new[] { "A", "U", "C", "H" },
new[] { "Approved", "Under Review", "Conditional", "Hold" })]
[PXDefault("A")]
public string CreditReviewStatus { get; set; }
public abstract class creditReviewStatus : PX.Data.BQL.BqlString.Field<creditReviewStatus> { }
}
#endregion
protected virtual void Customer_RowUpdated(PXCache sender, PXRowUpdatedEventArgs e)
{
var row = (Customer)e.Row;
var ext = sender.GetExtension<CustomerExt>(row);
if (ext?.CreditReviewStatus == "H")
{
row.CreditHold = true; // keep the stock hold flag in sync so SO/AR still enforce it
}
}
}
Syncing the custom status back onto the stock CreditHold flag is the important part — it means every place in Acumatica that already checks credit hold (order entry, invoice release) keeps working without needing to know the new status field exists, rather than requiring every consuming screen to be individually updated to understand the richer status.
Tax and pricing linkage
Customer records drive tax zone defaults and price/discount schedule assignment — a customization adding customer segmentation (a new customer category, say) should check whether that segmentation is meant to also drive pricing or tax behavior, since those are configured separately and won't pick up a new custom field automatically.
Testing considerations
Test against a business account that's linked to both a customer and a vendor record (common for reciprocal trading relationships) to confirm a Customer-scoped extension behaves as expected on the shared BAccount data, and test the credit status sync against an actual order entry attempt, not just a save on the customer screen.
Wrapping up
Customer field extensions are simple in mechanics and easy to get subtly wrong in scope, because of the shared BAccount base. Decide deliberately whether a field is customer-only or account-wide, and keep any custom status in sync with the stock fields other screens already depend on.
Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.