Skip to main content
Solved

Getting Error on 2022 R2 when closing Opportunity

  • 8 August 2023
  • 3 replies
  • 88 views

I have a problem when closing out an opportunity (OpportunityMaint) graph. 

It is giving the dreaded “Another process has added/updated/deleted the ‘{0}’ record. Your changes will be lost.”

In the past I have handled this by simply using:

PXTimeStampScope.SetRecordComesFirst(typeof(OpportunityMaint), true);

But I can’t figure out how to override the Closed as Won method. In source code, it seems Acumatica is now adding a “workflow” class but extending the OpportunityMaint class:

class OpportunityWorkflow : PX.Data.PXGraphExtension<OpportunityMaint>

And within that, it defines the options for closing an opportunity:

var formOpen = CreateForm("FormOpen", OpenReasons, OpportunityReason.Qualified);

var formWon = CreateForm("FormWon", WonReasons);

var formLost = CreateForm("FormLost", LostReasons);

 

But I can’t override it. 

I tried creating this:

 

  "PXOverride]
        public void CloseAsWon(PXAdapter adapter, Action<PXAdapter> baseMethod)
        {
            using (PXTimeStampScope ts = new PXTimeStampScope(null))
            {
                PXTimeStampScope.SetRecordComesFirst(typeof(OpportunityMaint), true);
                // Call the base CloseAsWon action logic.
                baseMethod?.Invoke(adapter);
            }
        }

 

Which compiles but errors out at runtime with an error:

Method Void CloseAsWon(PX.Data.PXAdapter, System.Action`1cPX.Data.PXAdapter]) in graph extension is marked as dPXOverride], but the original method with such name has not been found in PXGraph

 

What is the secret for overriding this? Anyone know?

3 replies

Badge +12

The correct way to override an action involves a delegate:

public delegate void OriginalActionDelegate();

[PXOverride]
public void OriginalAction(OriginalActionDelegate baseMethod)
{
baseMethod();
}

But with further inspection, I found that the original action (from OpportunityMaint) looks like this:

public PXAction<CROpportunity> CloseAsWon;
[PXButton, PXUIField(DisplayName = "Close as Won", MapViewRights = PXCacheRights.Select, MapEnableRights = PXCacheRights.Update)]
protected virtual IEnumerable closeAsWon(PXAdapter adapter)
{
foreach (CROpportunity current in adapter.Get<CROpportunity>())
{
if (current != null)
{
CROpportunity.Events.Select(ev => ev.OpportunityWon).FireOn(this, current);
CROpportunity.Events.Select(ev => ev.OpportunityClosed).FireOn(this, current);
}
yield return current;
}
}

Since the override signature needs to match the original, the correct code to override the action should be this:

public delegate IEnumerable closeAsWonDelegate(PXAdapter adapter);

[PXOverride]
public IEnumerable closeAsWon(PXAdapter adapter, closeAsWonDelegate baseMethod)
{
// other code

var result = baseMethod(adapter);

// other code

return result;
}

One note is that in this particular situation, the original method is a protected method. This would ordinarily prevent it from being overridden (or rather require a more complicated override), but since it is also virtual, it is allowed to be overridden in derived classes.

Userlevel 4
Badge

Wow, Daryl… I owe you a beer for sure. Thank you so much for the help!

Badge +12

Sure thing. If you make it to the Summit this year, I’ll do my best to allow you to make good on that 😁

Reply