Skip to main content
Solved

How to fully replace a FieldVerifying handler from another customization in Acumatica 2025 R2?

  • December 17, 2025
  • 6 replies
  • 51 views

Hi all,

I'm having the following scenario: We have a base customization that adds a FieldVerifying handler in ArcContractMaint for ArcContract.CounterpartyID. We have a second customization that must completely replace that validation logic. We need the original handler to NOT run before or after our handler.
The instance version we are using is: Acumatica 2025 R2

Base handler we want to replace:
 

protected virtual void _(Events.FieldVerifying<ArcContract, ArcContract.counterpartyID> e)
{
ArcContract row = e.Row;
bool flag = row == null || e.NewValue == null;
if (!flag)
{
FeaturesSet current = PXSelectBase<FeaturesSet, PXSelect<FeaturesSet, Where<True, Equal<True>>, OrderBy<Desc<FeaturesSet.status>>>.Config>
.SelectWindowed(this, 0, 1, Array.Empty<object>());
bool? visibilityRestriction = current.VisibilityRestriction;
bool flag2 = false;
bool flag3 = visibilityRestriction.GetValueOrDefault() == flag2 & visibilityRestriction != null;
if (!flag3)
{
bool isBAccountRestricToCurBranch = false;
int? curyBranchID = PXAccess.GetBranchID();
int? orgBAccountID = this.GetOrgBAccountID(curyBranchID);
bool flag4 = row.PurchaseSale == "P";
if (flag4)
{
foreach (PXDataRecord rec in PXDatabase.SelectMulti<BAccount>(new PXDataField[]
{
new PXDataField("VOrgBAccountID"),
new PXDataFieldValue("VOrgBAccountID", orgBAccountID),
new PXDataFieldValue("BAccountID", e.NewValue)
}))
{
isBAccountRestricToCurBranch = true;
}
}
else
{
bool flag5 = row.PurchaseSale == "S";
if (flag5)
{
foreach (PXDataRecord rec2 in PXDatabase.SelectMulti<BAccount>(new PXDataField[]
{
new PXDataField("COrgBAccountID"),
new PXDataFieldValue("COrgBAccountID", orgBAccountID),
new PXDataFieldValue("BAccountID", e.NewValue)
}))
{
isBAccountRestricToCurBranch = true;
}
}
}
bool flag6 = !isBAccountRestricToCurBranch;
if (flag6)
{
e.NewValue = null;
throw new PXSetPropertyException<ArcContract.counterpartyID>(
"Chosen counterparty ID is not associated with current branch. Make some adjustments on AP303000/AR303000 screen.",
new object[] { row });
}
}
}
}

My current extension:
 

using PX.Common;
using PX.Data;
using PX.Objects.CR;
using PX.Objects.CS;
using PX.Objects.GL.DAC;
using System;
using Branch = PX.SM.Branch;

namespace CurrentCustomizationExt
{
[PXLocalizable]
public static class Messages
{
public const string CounterpartyNotAssociatedWithBranch =
"[PCExt] Chosen counterparty is not associated with current branch. Please adjust visibility restrictions on AP303000/AR303000 screen.";
}

public class ArcContractMaintExt : PXGraphExtension<ArcContractMaint>
{
public static bool IsActive() => true;

[PXOverride]
protected virtual void _(Events.FieldVerifying<ArcContract, ArcContract.counterpartyID> e)
{
ArcContract row = e.Row;
if (row == null || e.NewValue == null)
{
return;
}

int? counterpartyID = e.NewValue as int?;
if (counterpartyID == null && e.NewValue is int intVal)
{
counterpartyID = intVal;
}

if (counterpartyID == null)
{
return;
}

FeaturesSet features = PXSelect<FeaturesSet,
Where<True, Equal<True>>,
OrderBy<Desc<FeaturesSet.status>>>
.SelectWindowed(Base, 0, 1);

bool isVisibilityRestrictionEnabled = features?.VisibilityRestriction == true;

if (!isVisibilityRestrictionEnabled)
{
return;
}

int? branchID = row.BranchID ?? Base.Accessinfo.BranchID ?? PXAccess.GetBranchID();
int? orgBAccountID = GetOrgBAccountIDFromBranch(branchID);

bool isValid = ValidateCounterpartyOrganizationMatch(row.PurchaseSale, counterpartyID, orgBAccountID);

if (!isValid)
{
throw new PXSetPropertyException<ArcContract.counterpartyID>(
Messages.CounterpartyNotAssociatedWithBranch);
}
}

// helper methods omitted for brevity
}
}

I have tried overriding the handler with delegate but it gives the following error: “Invalid argument type in the event handler ”. At the code current state, its kind of overriding it almost correctly but even when the Counterparty value is valid, its executing the old event handler after mine and throws the exception even when the value is valid

Best answer by aleksandrsechin

I thought you had a core graph, customization 1 for this graph, and a new customization 2 where you need to override the event handler from customization 1.

If I understand correctly now, you have a custom graph with an event handler and a new customization. In that case, all you need to do is override the event handler as follows:

public class ArcContractMaintExt : PXGraphExtension<ArcContractMaint>
{
protected virtual void _(Events.FieldVerifying<ArcContract, ArcContract.counterpartyID> e, PXFieldVerifying baseHandler)
{
if (!(e.Row is ArcContract row)) return;
}
}

Defining the event handler in the graph extension with a signature that includes PXFieldVerifying will override the base event handler. You can call the base logic, if needed, by using baseEvent.Invoke(e.Cache, e.Args).

However, if you don’t need the base logic, simply don’t call it (as shown in the code snippet above), and it will be skipped.

6 replies

Forum|alt.badge.img+3

Hi ​@nikola74
You need to define a second-level graph extension and override the event handler there. Here’s an example:

public class SecondExtSOOrderEntryExt : PXGraphExtension<FirstExtSOOrderEntry, SOOrderEntry>
{
protected virtual void _(Events.FieldVerifying<SOLine, SOLine.qty> e, PXFieldVerifying baseEvent)
{
if (!(e.Row is SOLine row)) return;

//Your code.
}
}

If you further need to call the base method, you can do it this way:
baseEvent.Invoke(e.Cache, e.Args);

However, if you don’t need it at all now, do not call it and leave the code as shown in the snippet above.


  • Author
  • Freshman I
  • December 17, 2025

Hi ​@nikola74 
You need to define a second-level graph extension and override event handler there. Here is an example:

public class SecondExtSOOrderEntryExt : PXGraphExtension<FirstExtSOOrderEntry, SOOrderEntry>
{
protected virtual void _(Events.FieldVerifying<SOLine, SOLine.qty> e, PXFieldVerifying baseEvent)
{
if (!(e.Row is SOLine row)) return;

//Your code.
}
}

 

Do you mean that it has to be something like this?
 

// Target graph extension has protected method
public class SOOrderCustomerCredit : PXGraphExtension<SOOrderEntry>
{
protected void ApplyCreditVerificationResult(PXCache sender, SOOrder row,
CreditVerificationResult res, PXCache arbalancescache)
{
// Protected implementation
}
}

// Step 1: Abstract extension to expose the protected method
[PXProtectedAccess(typeof(SOOrderCustomerCredit))]
public abstract class SOOrderCustomerCreditProtectedExt
: PXGraphExtension<SOOrderCustomerCreditExt, SOOrderCustomerCredit, SOOrderEntry>
{
[PXProtectedAccess]
protected abstract void ApplyCreditVerificationResult(
PXCache sender, SOOrder row, CreditVerificationResult res, PXCache arbalancescache);
}

// Step 2: Your override extension
[PXProtectedAccess]
public abstract class SOOrderCustomerCreditExt
: PXGraphExtension<SOOrderCustomerCredit, SOOrderEntry>
{
public static bool IsActive() => true;

public delegate void ApplyCreditVerificationResultDelegate(
PXCache sender, SOOrder Row, EventArgs e, Customer customer, CreditVerificationResult res);

[PXOverride]
public virtual void ApplyCreditVerificationResult(
PXCache sender, SOOrder Row, EventArgs e, Customer customer, CreditVerificationResult res,
ApplyCreditVerificationResultDelegate del)
{
// Custom logic - modify result if needed
CreditVerificationResult newResult = res;

// Call original
del?.Invoke(sender, Row, e, customer, newResult);
}
}

 


Forum|alt.badge.img+3

No. What are the names of your:

1. graph

2. first graph extension (where you already have the event handler)

3. second graph extension (the new one, where you want to override the event handler)?


  • Author
  • Freshman I
  • December 17, 2025

No. What are the names of your:

1. graph

2. first graph extension (where you already have the event handler)

3. second graph extension (the new one, where you want to override the event handler)?

If I’m understanding correctly what you’re saying, 1 and 2 are the same thing, meaning.. the graph with the old event handler I’m trying to override which is:

public class ArcContractMaint : PXGraph<ArcContractMaint, ArcContract>, IVoucherEntry

and the 3rd is the graph extension I’m working on

public class ArcContractMaintExt : PXGraphExtension<ArcContractMaint>

is that correct?


Forum|alt.badge.img+3

I thought you had a core graph, customization 1 for this graph, and a new customization 2 where you need to override the event handler from customization 1.

If I understand correctly now, you have a custom graph with an event handler and a new customization. In that case, all you need to do is override the event handler as follows:

public class ArcContractMaintExt : PXGraphExtension<ArcContractMaint>
{
protected virtual void _(Events.FieldVerifying<ArcContract, ArcContract.counterpartyID> e, PXFieldVerifying baseHandler)
{
if (!(e.Row is ArcContract row)) return;
}
}

Defining the event handler in the graph extension with a signature that includes PXFieldVerifying will override the base event handler. You can call the base logic, if needed, by using baseEvent.Invoke(e.Cache, e.Args).

However, if you don’t need the base logic, simply don’t call it (as shown in the code snippet above), and it will be skipped.


  • Author
  • Freshman I
  • December 17, 2025

I thought you had a core graph, customization 1 for this graph, and a new customization 2 where you need to override the event handler from customization 1.

If I understand correctly now, you have a custom graph with an event handler and a new customization. In that case, all you need to do is override the event handler as follows:

public class ArcContractMaintExt : PXGraphExtension<ArcContractMaint>
{
protected virtual void _(Events.FieldVerifying<ArcContract, ArcContract.counterpartyID> e, PXFieldVerifying baseHandler)
{
if (!(e.Row is ArcContract row)) return;
}
}

Defining the event handler in the graph extension with a signature that includes PXFieldVerifying will override the base event handler. You can call the base logic, if needed, by using baseEvent.Invoke(e.Cache, e.Args).

However, if you don’t need the base logic, simply don’t call it (as shown in the code snippet above), and it will be skipped.

This worked perfectly. Thank you!
What I was doing wrong was that I was using [PXOverride] and it was forcing me to match the event handler but to completely override it, apparently I needed to remove the [PXOverride] and pass the PXFieldVerifying baseHandler in the parameters of the event handler just as you said in your response.