acuamitca.com logo ACUAMITCA
~/blog/article

Override Processing Screen Views in Acumatica: A Practical Guide

Acumatica 8 mins read July 20, 2026

When customizing Acumatica ERP, there are times when you need to modify the behavior of standard processing screens. One common requirement is to filter data based on business rules that aren't part of the out-of-the-box functionality. In this article, we'll explore how to override the data source of a processing screen using the PXOverride attribute.

⚡ Scenario: A client needed to restrict the AP Document Release screen to only show documents belonging to the current user's branch. This customization ensures users only see and release documents from their own branch.


The Challenge

The Acumatica AP Document Release screen (APDocumentRelease) displays a list of payables documents ready for release. By default, it shows all documents across all branches. However, in a multi-branch environment, it's often necessary to restrict users to only documents from their assigned branch.

The standard screen doesn't provide a built-in branch filter. To add this functionality without modifying the base code, we need to use Acumatica's Customization and Extension capabilities.


The Solution: PXOverride

The solution uses the PXOverride attribute to intercept the data retrieval method of the processing screen. This allows us to filter the results before they're displayed to the user.

The Complete Code

using System.Collections;
using PX.Data;
using PX.Objects.AP;

public class EMPAPDocumentReleaseExt
    : PXGraphExtension<APDocumentRelease>
{
    public delegate IEnumerable APDocumentListDelegate();

    [PXOverride]
    public virtual IEnumerable apdocumentlist(
        APDocumentListDelegate baseMethod)
    {
        int? currentBranchID = Base.Accessinfo.BranchID;

        foreach (object row in baseMethod())
        {
            BalancedAPDocument document =
                PXResult.Unwrap<BalancedAPDocument>(row);

            if (document?.BranchID == currentBranchID)
            {
                yield return row;
            }
        }
    }
}

Code Walkthrough

1. Graph Extension

public class EMPAPDocumentReleaseExt
    : PXGraphExtension<APDocumentRelease>

The class extends the APDocumentRelease graph, which is the underlying data access layer for the processing screen. By inheriting from PXGraphExtension, we can add or override functionality without modifying the original source code.

2. Delegate Declaration

public delegate IEnumerable APDocumentListDelegate();

This declares a delegate that matches the signature of the method we're going to override. The delegate allows us to call the original method from within our overridden version.

3. The PXOverride Attribute

[PXOverride]
public virtual IEnumerable apdocumentlist(
    APDocumentListDelegate baseMethod)

The PXOverride attribute tells the Acumatica framework that this method should replace the original apdocumentlist method. The baseMethod parameter gives us access to the original implementation.

4. Branch Filtering Logic

int? currentBranchID = Base.Accessinfo.BranchID;

The current user's branch ID is retrieved from Base.Accessinfo.BranchID. This ensures we only show documents that match the user's branch.

foreach (object row in baseMethod())
{
    BalancedAPDocument document =
        PXResult.Unwrap<BalancedAPDocument>(row);

    if (document?.BranchID == currentBranchID)
    {
        yield return row;
    }
}

The code iterates through all documents returned by the base method, checks if the document's branch matches the user's branch, and yields only the matching rows.

💡 Key Insight: The yield return statement creates an iterator that lazily evaluates the collection. This is more efficient than creating a new collection, especially for large datasets.


Understanding PXResult.Unwrap

The PXResult.Unwrap<BalancedAPDocument>(row) method is crucial to understanding this code. Here's why:

  • What it does: Extracts the actual BalancedAPDocument object from a PXResult wrapper
  • Why it's needed: The apdocumentlist method returns PXResult objects that contain multiple DACs (Data Access Classes)
  • How it works: PXResult.Unwrap extracts the specific DAC type you need

Alternative Approach: Modifying the BQL

For better performance, especially with large datasets, you can filter at the database level instead of in memory:

[PXOverride]
public virtual IEnumerable apdocumentlist(
    APDocumentListDelegate baseMethod)
{
    int? currentBranchID = Base.Accessinfo.BranchID;

    // Use a BQL delegate to add the filter
    var delegateWithFilter = new APDocumentListDelegate(() =>
    {
        foreach (PXResult<BalancedAPDocument> result in
            baseMethod().Cast<PXResult<BalancedAPDocument>>())
        {
            BalancedAPDocument doc = result;
            if (doc.BranchID == currentBranchID)
            {
                yield return result;
            }
        }
    });

    return delegateWithFilter();
}

Best Practices

✅ Use PXOverride for Non-Intrusive Customization

Always prefer PXOverride over modifying base code. It makes upgrades easier and keeps your customizations maintainable.

✅ Consider Performance

For large datasets, filter at the database level using BQL delegates rather than in-memory filtering.

✅ Use Meaningful Class Names

Prefix your extension classes with your company code (e.g., EMP) to identify them as customizations.

✅ Test Thoroughly

Always test with users in different branches to ensure the filtering works as expected.


Common Pitfalls to Avoid

❌ Ignoring Null Values

Always check for null when accessing properties of unwrapped objects to avoid NullReferenceException.

❌ Not Considering Performance

In-memory filtering on thousands of records can cause performance issues. Consider database-level filtering.

❌ Forgetting the Delegate

The delegate must be correctly declared and used. Without it, you can't call the base method.

❌ Hardcoding Values

Avoid hardcoding branch IDs or other values. Always use runtime values like Base.Accessinfo.BranchID.


When to Use This Pattern

This pattern can be applied to various scenarios in Acumatica:

  • Branch-Based Filtering: Restrict documents to the user's branch
  • Department Restrictions: Show only documents from specific departments
  • User-Specific Data: Display only records created by the current user
  • Security Filters: Implement row-level security based on user roles
  • Custom Business Logic: Apply any custom filtering logic to processing screens

Conclusion

Overriding processing screen data sources using PXOverride is a powerful technique for Acumatica customization. It allows you to add business-specific filtering without modifying the base code, keeping your customizations maintainable and upgrade-safe.

The example we've explored demonstrates how to add branch-based filtering to the AP Document Release screen. This same pattern can be adapted to filter data in any processing screen based on your business requirements.

📌 Key Takeaway: PXOverride with delegate-based method overriding provides a clean, non-intrusive way to customize Acumatica processing screens. Always prefer this approach over direct code modifications for better maintainability and upgrade compatibility.

🔍 Further Reading: Consider exploring the PXOverride attribute for other customization scenarios like overriding Persist methods, event handlers, or other graph operations.