Can I customize the Release action in Cash Sales? - acumatica

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;
}
}

Related

Question on Overriding a method in Customization

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;
*/
}

Overriding second level graph extension method in Acumatica

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.

How to add custom code to the 'Post' action from the GL Post Transactions screen

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
}
}

Extend existing event

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

Automatically "Capture CC payment" when confirming shipments

I have been asked the question by one of my customers that they would like to automatically "Capture CC Payment" for Sales orders at the time that the shipper is confirmed.
I know that in Acumatica, there is the batch processing methods to handle doing this in bulk but they'd still like to have it automatically do it as mentioned above.
My initial thoughts were a Customization that will use an Automation Step when the shipper is confirmed to load the order and execute the "Capture CC Payment" step.
More or less a customization step that is composed of
1) A custom method in the shipper screen that loads the order(s) in question and then executes the "Capture CC Payment" button/function
2) An automation step assigned to the shipper at the time of confirmation that executes the above method.
Is this the best way of handling this request or is there another pre-existing method that I might have overlooked?
The customer is currently on 4.20.2115 with no real interest in going to 5.1 anytime soon.
Thank you
If you have a hummer in your hands, everything is a nail :). I can propose you solution from C# prospective. As a solution, I propose you to override method confirm in extension class with usage of delegate. I don't know about which form you are talking about, but lets assume, that form has graph SubmitterManager. Lets also assume, that you want to track method CreatePayment, which has paramethers string, IDictionary, IDictionary. Then you can create graph extension SubmitterManagerExt, and use PXOverride attribute with delegate in the following way:
public class SubmitterManagerExt : PXGraphExtension<SubmitterManager>
{
[PXOverride]
public bool CreatePayment(string viewName,
IDictionary keys,
IDictionary values,
Func<string, IDictionary,
IDictionary, bool> method)
{
// Call your method CreatePayment
bool result = method(viewName, keys, values);
if(result)
{
// here you can add some C# code, which will do something
// with created payments
}
}
return result;
}
}

Resources