I need to perform more action after the existing action is performed. For example, After Distribution > Sales Orders > Shipment > Action > Confirm Shipment, I need to populate all tracking numbers into another text box.
Please suggest.
The best thing here in my opinion would be to override the logic of the stock method. That will allow you to add your needed code without touching the base method as well as you being able to validate information before and after the base method is called.
In the case of your example, "Confirm Shipment" action ultimately executes the method "ConfirmShipment" which is defined as below:
public virtual void ConfirmShipment(SOOrderEntry docgraph, SOShipment shiporder)
{
.....
}
In order to customize the logic in here you have a few options.
Create an override method (added to the method queue, base called first then all 'override' methods)
Create an method that calls the stock one first, then your code. - this will in essence "replace" the stock logic but allow you to still call the base method. in doing this, you can run some checks before calling the base.
To do the second you would do the following
Create first the delegate in your code:
public delegate void ConfirmShipmentDelegate(SOOrderEntry docgraph, SOShipment shiporder)
Then define your override method:
[PXOverride]
public virtual void ConfirmShipment(SOOrderEntry docgraph, SOShipment shiporder, ConfirmShipmentDelegate baseMethod = null)
{
// Call our base method first if it exists
if (baseMethod != null)
{
baseMethod(docgraph,shiporder);
}
// Do my stuff here
}
Couple items to note here.
The definition has a third param to our delegate, this allows us to call the stock method and then do further work. It also tells the Acumatica framework our method should take priority over the stock method.
The stock method is called from the baseMethod call in the actual code.
Creating the extension this way allows for upgrades to occur without you having to totally redefine your method every time.
The second method would be just be an override of the stockcode. That is done with the following syntax
[PXOverride]
public virtual void ConfirmShipment(SOOrderEntry docgraph, SOShipment shiporder)
{}
When taking this approach, the stock method is first called, then your override method is called.
both of these would be handled in a graph extension defined as:
public class SOShipmentEntryExt : PXGraphExtension<SOShipmentEntry>
Before attempting either, I would look at the articles in the Wiki on PXOverride as they give further examples/situations for these
Related
What if I override a method on a particular screen.
For example: let's say Journal Transactions Screen, I've overridden the method Release(), I've made it to stop Posting Transactions on the General Ledger with that customization applied, when releasing a document on a screen that produces Journal Transaction Documents that also triggers auto-release, will the customization, the overriden method, will apply first?
From what I've seen, extensions are called first followed by base calls.
If you think the call order ambiguity might lead to errors with your specific code in the handler I'd recommend to explicitly declare and call the base method in the overridden method.
Using Acumatica customization project editor is the easiest way to get the declaration syntax down:
That way there's no doubt with the calling order:
public delegate IEnumerable ReleaseDelegate(PXAdapter adapter);
[PXOverride]
public IEnumerable Release(PXAdapter adapter, ReleaseDelegate baseMethod)
{
// Put your code before calling base
return baseMethod(adapter);
/* Or after calling base
IEnumerable returnValue = baseMethod(adapter);
// put your code to be executed after base here
return returnValue;
*/
}
I need to work with the reusable business objects for Sales tax, discounts, etc. and need to override some of the methods in these graph extensions. For example I am starting with the Opportunities graph. I have a set of order totals that need to calculate into the overall products amount and in the past we just overrode the tax attribute on (I think) tax category. Anyhow I don't see how its possible to use the PXOverrideAttribute on a method from a second level graph extension.
Here is my example:
public class OpportunityMaintExtOne : PXGraphExtension<PX.Objects.CR.OpportunityMaint.SalesTax, PX.Objects.CR.OpportunityMaint>
{
[PXOverride]
public virtual void CalcDocTotals(object row, decimal CuryTaxTotal, decimal CuryInclTaxTotal, decimal CuryWhTaxTotal,
Action<object, decimal, decimal, decimal> del)
{
del?.Invoke(row, CuryTaxTotal, CuryInclTaxTotal, CuryWhTaxTotal);
var someOtherTotal = Base1.Documents.Cache.GetValueAsDecimal<CROpportunityExtension.aMCurySomeOtherTotal>(row);
if (someOtherTotal == 0)
{
return;
}
var curyDocTotal = someOtherTotal + Base1.Documents.Cache.GetValueAsDecimal<CROpportunity.curyProductsAmount>(row);
Base1.Documents.Cache.SetValue<CROpportunity.curyProductsAmount>(row, curyDocTotal);
}
}
What is going on inside of CalcDocTotals in my graph extension is not the focus. It is the fact that I cannot override the OpportunityMaint.SalesTax CalcDocTotals method as I could if the method was in the first level (Base) graph. The SalesTax graph extension has the method as protected but protected methods (if it was in the base graph) are overrideable using the PXOverrideAttribute if you make your method call public which is what I have done. I also tried using a declared delegate in place of the Action but same results (as I expected but wanted to confirm).
My question: Is it possible to override a second, third, etc. level graph extension method using the PXOverrideAttribute?
When I compile the code above and the page loads I get this error:
Method Void CalcDocTotals(System.Object, System.Decimal,
System.Decimal, System.Decimal,
System.Action`4[System.Object,System.Decimal,System.Decimal,System.Decimal])
in graph extension is marked as [PXOverride], but the original method
with such name has not been found in PXGraph
The ability to override extension methods from a higher level extension has been added in 2018R1 Update 4 (18.104.0023). This resolves my question/issue and allows for the code posted in my question to function as is.
You cannot override methods from Extension1 in Extension2 etc as far as I've been able to see in my years with Acumatica. My solution to the problem was thus : Create a helper graph with your basic methodology, create a field or property for it in whatever graph you wish to use it in (Preferably a Lazy initialized one), then in whatever project you must override the logic on, just reference your original project, and create an extension of your helper graph.
I need to change how a Release procedure works. Specifically, I need to change the Release button on the Cash Sales site to use custom fields to populate the Cash Account and Subaccount fields. I found that the release button forwards the process to ARDocumentRelease.ReleaseDoc() which is located in PX.Objects.AR. This led me to believe that I need to customize the function that exists in 'PX.Objects.AR', but I'm not sure if that is doable.
Is it possible to customize functions that exist in the PX.Objects DLL? If not, is it possible for me to force the function in the DLL to receive custom fields for the Cash Account and Subaccount values instead of the base fields?
ARDocumentRelease is the process list page which calls ARReleaseProcess for each document release and is a graph. You can create a graph extension to override the calls it makes which is a virtual call to ReleaseDocProc meaning you can use PXOverride in your graph extension to override the call. Without testing, it could look something like this...
public class ARReleaseProcessExtension : PXGraphExtension<PX.Objects.AR.ARReleaseProcess>
{
[PXOverride]
public virtual List<PX.Objects.AR.ARRegister> ReleaseDocProc(PX.Objects.GL.JournalEntry je, PX.Objects.AR.ARRegister ardoc, List<PX.Objects.GL.Batch> pmBatchList,
PX.Objects.AR.ARDocumentRelease.ARMassProcessReleaseTransactionScopeDelegate onreleasecomplete,
Func<PX.Objects.GL.JournalEntry, PX.Objects.AR.ARRegister, List<PX.Objects.GL.Batch>, PX.Objects.AR.ARDocumentRelease.ARMassProcessReleaseTransactionScopeDelegate, List<PX.Objects.AR.ARRegister>> del)
{
//Code before...
//The base call...
var ret = del?.Invoke(je, ardoc, pmBatchList, onreleasecomplete);
//Code after...
return ret;
}
}
I need to add custom code to the logic which posts transactions on the GL 'Post Transactions' screen. After going through the T300 documentation and looking at the override of 'Release' to use as an example, I cannot find anything in the 'BatchPost' BLC that remotely resembles a posting process event/method that I can override. Where would I find that logic and what's the best way to add my custom code to the Posting process, batch by batch?
I think the best way to override posting process is to override PX.Objects.GL.PostGraph.PostBatchProc(Batch b, bool createintercompany)
All logic related to posting are located there.
Here is an example:
public class PostGraphExt : PXGraphExtension<PostGraph>
{
public delegate Batch PostBatchProcDelegate(Batch b, bool createintercompany);
[PXOverride]
public virtual void PostBatchProc(Batch b, bool createintercompany, PostBatchProcDelegate baseMethod)
{
//your code here
baseMethod(b, createintercompany);
//or here
}
}
I tried to override an exisiting method but after i published I get this error.
Attempt by method 'Wrapper.PX.Objects.AR.Cst_ARPaymentEntry.ARPayment_RowSelectedGeneratedWrapper(PX.Objects.AR.ARPaymentEntry, PX.Data.PXCache, PX.Data.PXRowSelectedEventArgs)' to access method 'PX.Objects.AR.ARPaymentEntry_Extension.ARPayment_RowSelected(PX.Data.PXCache, PX.Data.PXRowSelectedEventArgs)' failed.
when I tried to remove the PXOverride attribute no error occured. I'm using 5.10.072 version.
[PXOverride]
protected void ARPayment_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
{
}
The problem is that you try to override an event handler - not a common virtual method of the BLC. To do this one has to use a different approach. Namely, you need to declare the event handler without the PXOverride attribute, but with an additional argument of type PXRowSelected and then either call it or not based on your internal logic. Here is an example of such a declaration:
protected void ARPayment_RowSelected(PXCache cache, PXRowSelectedEventArgs e, PXRowSelected invokeBaseHandler)
{
/* your custom event handling logic here */
if(/* your custom condition may go here */)
invokeBaseHandler(cache, e);
/* some more of your logic here if needed */
}
Note that if you simply want your handler be executed along with the base one, you don't need the additional argument - simply declare the handler with your code and it will be called after the original handlers.
You may find much more information and explanatiions on this topic in the help article located under Help > Customization > Examples of Functional Customization > Adding or Altering BLC Event Handler in any instance of Acumatica.