Acumatica · Acumatica

Acumatica GL Journal Transaction Screen — A Deep Dive

Acumatica GL Journal Transaction Screen — A Deep Dive — a complete, field-tested reference by John Kihiu, Acumatica developer in Nairobi.

John Kihiu12 min read

Acumatica GL Journal Transaction Screen — A Deep Dive is the screen the user actually lives in. Every other piece of Acumatica — the workflows, the reports, the integrations — exists to feed this screen or be fed by it. If you do not understand this screen, you do not understand the module. This guide is the field-tested walkthrough I wish someone had given me the first time I had to customise it.

What the screen actually does

Most Acumatica screens look similar at first glance — a form view, a tab, a grid. The difference is in the document lifecycle, the events that fire as you move through the tabs, and the state machine that controls what is editable. This screen is a document-entry screen: each row in the grid is a line item, the header aggregates the lines, and the release action posts the document to the sub-ledger.

Read the header before you read the lines

Whenever you are debugging a document-entry screen, look at the header first. The header carries the document type, status, customer, dates, and totals. The lines are downstream of the header. If the lines look wrong, the header is the first place to look — most "line bug" tickets are actually "header state bug" tickets in disguise.

The header fields that matter

Not every field on the header is used in every workflow. The fields that are reliably used in customisations are:

FieldWhy it mattersCommon customisation
Document typeDrives status, numbering, postingAdd a custom document type for a tenant-specific flow
Reference NbrExternal identifier; idempotency keyStamp with an order ID from an external system
StatusControls what is editable; part of the workflowAuto-set a custom status from a business event
DateDrives period, ageing, FXDefault to the customer's order date
Customer / VendorDrives pricing, terms, GL accountsFilter by a custom field on the customer record
BranchDrives ledgers, tax zones, restrict usersDefault to the current branch
C# · HEADER FIELD DEFAULTING
protected void _(Events.FieldDefaulting<Batch, Batch.docDate> e)
{
    var row = e.Row;
    if (row?.CustomerID != null)
    {
        var customer = (Customer)PXSelect<Customer,
            Where<Customer.bAccountID, Equal<Required<Customer.bAccountID>>>>
            .Select(Base, row.CustomerID);
        if (customer?.LastOrderDate != null)
        {
            e.NewValue = customer.LastOrderDate;
            e.Cancel = true;
        }
    }
}

For deeper coverage of DAC fields and the defaulting pattern, see the DAC fundamentals article and the field attributes guide.

The tabs, and what they each do

The tab structure on this screen is more than layout — it is the navigation contract. Each tab loads a related set of records; each has its own data view; each can be hidden, shown, or disabled based on the header state. The conventions for the tabs on this screen, from left to right:

Custom tab gone after upgrade

If you add a custom tab and the tab disappears after an upgrade, the most common cause is the tab ID not being a unique key. Always use a namespace-prefixed tab ID (e.g. tabUsrCustom not tabCustom1). Acumatica uses the ID to identify the tab across versions.

The lines grid: the one you will spend the most time on

The lines grid is where the work is. The patterns that matter:

C# · LINE-LEVEL EVENT
protected void _(Events.RowSelected<BatchLine> e)
{
    var row = e.Row;
    if (row == null) return;
    var doc = Base.Document.Current;
    if (doc == null) return;
    PXUIStateAttribute.SetEnabled<BatchLine.qty>(
        e.Cache, row, doc.Hold == false && doc.Status == "N");
}

For the full event pattern catalog, see the events explained article.

The toolbar actions

The toolbar on this screen carries the document lifecycle actions. The standard ones are Hold, Remove Hold, Submit for Approval, Approve, Reject, Release, Copy, Print, Email, and Cancel. Each is a graph action with a server-side handler. Adding a custom action to the toolbar is a common customisation:

C# · CUSTOM TOOLBAR ACTION
public PXAction<Batch> SubmitToCustomWorkflow;
[PXButton(CommitChanges = true)]
[PXUIField(DisplayName = "Submit to Custom Workflow")]
protected void submitToCustomWorkflow()
{
    var row = Base.Document.Current;
    if (row == null) return;
    Base.Document.Cache.SetValueExt<Batch.Status>(row, "C");
    Base.Document.Cache.SetValueExt<Batch.CustomField>(row, "SUBMITTED");
    Base.Document.Update(row);
    Base.Actions.PressSave();
}

For more on actions and the workflow glue, see the workflow engine guide.

Release: what actually happens

The Release action is the most important button on the screen. It is also the most dangerous — once released, a document cannot be edited in place. Most customisations need to either add a pre-release validation or extend what release does (e.g. stamp a custom field, post to a custom table).

C# · EXTEND RELEASE
[PXOverride]
public virtual void Release(Batch doc)
{
    if (doc.CuryOrderTotal <= 0)
        throw new PXException("Cannot release a document with zero total.");
    Base.Release(doc);
    var ext = doc.GetExtension<BatchExt>();
    if (ext != null)
    {
        Base.Document.Cache.SetValueExt<BatchExt.usrReleasedAt>(doc, DateTime.UtcNow);
        Base.Document.Update(doc);
        Base.Actions.PressSave();
    }
}

For more on overrides, see the PXGraph vs PXGraphExtension guide.

Performance on this screen

This screen's performance is dominated by three things:

  1. The number of lines (rows in the grid). 10 lines render instantly; 1,000 lines take 4 seconds; 10,000 lines take 30 seconds.
  2. The number of event handlers firing on each render. Every RowSelected on the lines fires per row per render.
  3. The number of PXSelect calls in those handlers. Each one is a database round-trip.
Profile, then optimise

Before you change anything, profile. Add timing logs to the event handlers, run the screen on production-scale data, and look at where the time goes. Optimising the wrong handler is the most expensive mistake.

For the full performance playbook, see the performance tuning guide and the SQL Server indexing guide.

Common customisation recipes

Three customisations I have implemented on this screen repeatedly, and the patterns they follow:

  1. Default the branch from the user. If the user is restricted to a single branch, default the branch field to that branch and hide the selector. Saves clicks, prevents misposting.
  2. Add a custom approval step. If the standard approval map does not match the business process, add a custom approval step. Configure in the workflow, then add a button on the toolbar that triggers it.
  3. Stamp an external reference. If the document is created from an external system (e-commerce, portal, EDI), set the UsrExternalRef field on creation. Use it as the idempotency key.

For related reading, see the graph extension patterns, the cache attach pitfalls, and the events explained.

Wrapping up

That is the screen, top to bottom. The patterns here apply to most document-entry screens in Acumatica — the same structure, the same lifecycle, the same customisation playbook. Internalise the pattern, and the next screen you are asked to customise will be a 2-day job instead of a 2-week job.