Skip to main content

Acumatica Customization Guide

How to write DAC extensions, graph extensions, and deploy them via AcuOps CI/CD.

Decision Tree

Before writing code, check if a simpler path exists:

  1. String/number field on an entity? Use Acumatica Attributes (CS205000). No code needed.
  2. Custom report/view? Use Generic Inquiries. No code needed.
  3. Data sync dedup key? Attributes work for most entities.
  4. New database column + business logic? You need a customization project. Continue below.
  5. UI layout change only? Need a project, but code-only (no SQL).

DAC Extension Template

using PX.Data;
using PX.Objects.PO;

namespace YourNamespace
{
public class POOrderExt : PXCacheExtension<POOrder>
{
public static bool IsActive() => true;

#region UsrCustomField
[PXDBDate]
[PXUIField(DisplayName = "Custom Date")]
public virtual DateTime? UsrCustomField { get; set; }
public abstract class usrCustomField : PX.Data.BQL.BqlDateTime.Field<usrCustomField> { }
#endregion
}
}
warning

Always include public static bool IsActive() => true; — without it, the extension is silently disabled.

Graph Extension Template

using PX.Data;
using PX.Objects.PO;

namespace YourNamespace
{
public class POOrderEntry_Extension : PXGraphExtension<POOrderEntry>
{
public static bool IsActive() => true;

protected void _(Events.RowSelected<POOrder> e)
{
if (e.Row == null) return;
// Your business logic here
}
}
}

Project XML Format

The CI/CD pipeline requires the Acumatica import format:

<Customization>
<Graph ClassName="YourNamespace.POOrderExt"
Source="#CDATA" IsNew="True" FileType="CSharp">
<CDATA name="Source"><![CDATA[
// Your C# code here
]]></CDATA>
</Graph>
</Customization>

Anti-Patterns

Never use <Table> elements

<Table IsNewColumn="True"> causes NullReferenceException if columns already exist. Use <Sql> with ALTER TABLE instead.

Never reference CRM DACs in non-CRM graphs

CRRelation, CRPMTimeActivity, and CRActivity have field-level [PXSelector] attributes referencing CRM views. Adding these to non-CRM graphs like POOrderEntry crashes the screen at runtime — even though CI/CD smoke tests pass.

If you need relations or activities on PO screens, create fully custom DACs and tables.

Always co-publish

Include ALL active customization project names in the publishBegin request. Omitting a project deactivates it.

Verification

After deploy, verify with the schema endpoint:

GET /entity/default/24.200.001/{Entity}/$adHocSchema

If your fields appear in custom.{ViewName}.{FieldName}, the deploy succeeded.