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:
- String/number field on an entity? Use Acumatica Attributes (CS205000). No code needed.
- Custom report/view? Use Generic Inquiries. No code needed.
- Data sync dedup key? Attributes work for most entities.
- New database column + business logic? You need a customization project. Continue below.
- 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
}
}
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.