How can I override the ReleasePayments process / process all method? - acumatica

I'd like to add some custom code to the process of the Release Payments screen. If I create a customization project and add a Graph extension to the CODE section, I can't find any method with a name similar to 'Release Payments' to override in the list to select from (even though it exists as public in the BLC):
and if I try to manually code the override, I get an error that it can't find that method.
So basically, my question is, how do I intercept the process on the Release Payments screen?

I have had success with overriding the ARReleaseProcess.ReleaseDocProc like below. All the AR documents (invoices, payments, etc.) call the ARReleaseProcess.ReleaseDocProc during the release and that function does the main process. The below code is basically calling what that function was supposed to do and adding the delegate for when the release is completed.
public class ARReleaseProcessExt: PXGraphExtension<ARReleaseProcess>
{
public static bool IsActive()
{
return true;
}
public void OnReleaseComplete(ARRegister doc)
{
try
{
if (doc!=null && doc.DocType== ARDocType.Payment)
{
///ADD your code here
}
}
catch(Exception exc)
{
/// handler errors.
}
}
#region ReleaseDocProc
public delegate List<ARRegister> ReleaseDocProcDelegate(JournalEntry je, ARRegister ardoc, List<Batch> pmBatchList, ARDocumentRelease.ARMassProcessReleaseTransactionScopeDelegate onreleasecomplete);
[PXOverride]
public List<ARRegister> ReleaseDocProc(JournalEntry je, ARRegister ardoc, List<Batch> pmBatchList, ARDocumentRelease.ARMassProcessReleaseTransactionScopeDelegate onreleasecomplete, ReleaseDocProcDelegate del)
{
onreleasecomplete += OnReleaseComplete;
return del(je, ardoc, pmBatchList, onreleasecomplete);
}
#endregion
}
The override is a little different in case of AP module as the signature of the function is different there.
public class APReleaseProcess_Extension : PXGraphExtension<PX.Objects.AP.APReleaseProcess>
{
#region Event Handlers
public delegate List<APRegister> ReleaseDocProcDelegate(JournalEntry je, APRegister doc, Boolean isPrebooking, ref List<INRegister> inDocs);
[PXOverride]
public List<APRegister> ReleaseDocProc(JournalEntry je, APRegister doc, Boolean isPrebooking, ref List<INRegister> inDocs, ReleaseDocProcDelegate baseMethod)
{
var retVal = baseMethod(je,doc,isPrebooking,ref inDocs);
//Your code goes here.
PXTrace.WriteInformation("My override worked!");
return retVal;
}
#endregion
}

Related

Collecting Graph data during Process invoice and memos process button

I am currently upgrading code from Build 19.213.0029 to Build 21.201.0086.
I have code running during the release of an invoice.
namespace JVDnamespace
{
public class JVDSOInvoiceEntry_Extension : PXGraphExtension<SOInvoiceEntry>
{
public static bool IsActive() => true;
#region Event Handlers
public delegate IEnumerable ReleaseDelegate(PXAdapter adapter);
[PXOverride]
public IEnumerable Release(PXAdapter adapter, ReleaseDelegate baseMethod)
{
if ( !(Base.Document.Current is null) && !(Base.Document.Current.CuryOrigDocAmt is null))
{
setCreditLimit(Base.Document.Current.CustomerID.Value, Base.Document.Current.CuryOrigDocAmt.Value);
}
return baseMethod(adapter); ;
}
I use the Process Invoice and Memos(SO505000) to process/Release all my documents and then the code above would do a calculation for me.
The problem is with the new version of Acumatica(Build 21.201.0086) Base.Document.current is null and I can find a way to see what document is currently being processed. This is not the case if you release the document from the Invoice(SO303000) then the current data is populated.
Question:
Is there a new way or another way to get the current CustomerID and CuryOrigDocAmt during processing(release) on Page 'Process Invoice and Memos(SO505000)'.
You can use adpater.Get<ARInvoice>() to get a list of the invoices that are being released and then execute whatever logic you need per invoice. This should work on both pages if you are releasing from the Entry page it will just be a list of that invoice only.
public class SOInvoiceEntryExt : PXGraphExtension<SOInvoiceEntry>
{
public static bool IsActive() => true;
public delegate IEnumerable ReleaseDelegate(PXAdapter adapter);
[PXOverride]
public IEnumerable Release(PXAdapter adapter, ReleaseDelegate baseMethod)
{
foreach(ARInvoice inv in adapter.Get<ARInvoice>())
{
// Exceute logic here per invoice
}
return baseMethod(adapter); ;
}
}

Acumatica: what it the correct way to over right release so that base happens first

Good day
What is the correct way to change the below Release function to: first do the base function and only do your code?
When you use the built-in Acumatice "Override method"(that can be found when editing code) you get the following:
namespace PX.Objects.AR
{
public class ARPaymentEntry_Extension : PXGraphExtension<ARPaymentEntry>
{
#region Event Handlers
public delegate IEnumerable ReleaseDelegate(PXAdapter adapter);
[PXOverride]
public IEnumerable Release(PXAdapter adapter, ReleaseDelegate baseMethod)
{
//Normally you will add your code here.
return baseMethod(adapter);
}
#endregion
}
}
If you wanted the base to run fist and then you wanted your code after if would somthing like this:
namespace PX.Objects.AR
{
// Acuminator disable once PX1016 ExtensionDoesNotDeclareIsActiveMethod extension should be constantly active
public class ARPaymentEntry_Extension : PXGraphExtension<ARPaymentEntry>
{
#region Event Handlers
public delegate IEnumerable ReleaseDelegate(PXAdapter adapter);
[PXOverride]
public IEnumerable Release(PXAdapter adapter, ReleaseDelegate baseMethod)
{
baseMethod(adapter);
// your code here.
return;
}
#endregion
}
}
Question: What should I put as the return?
If I use null it gives a return nextstep error
public IEnumerable Release(PXAdapter adapter, ReleaseDelegate baseMethod)
{
IEnumerable result = baseMethod(adapter);
// your code here
return result;
}

Acumatica override method - Scan and Receive screen

Good day
I am looking for a way to override the function ProcessItemBarcode(string Barcode) inside public class INScanReceive : WMSBase
The idea is to extend the INScanReceiveHost graph and manipulate the barcode before it is processed. This is to change how the Scan and Receive page scan'sa barcodes so that I can read and manipulate QR codes
namespace PX.Objects.IN
{
// Acuminator disable once PX1016 ExtensionDoesNotDeclareIsActiveMethod extension should be constantly active
public class INScanReceiveHost_Extension : PXGraphExtension<INScanReceive>
{
#region Event Handlers
[PXOverride]
public virtual void ProcessItemBarcode(string barcode)
{
//change barcode
Base.ProcessItemBarcode.Invoke(barcode);
}
#endregion
}
}
But It telling me i can't access the function?
Update 2021/06/15
Thanks Sean Prouty for your help so far. I am getting very close to a solution.
I have a follow-up question.
I have overridden the ProcessItemBarcode function and ProcessLotSerialBarcode
Question: Can I call ProcessLotSerialBarcode from ProcessItemBarcode
because I have the location from the QR code I can set it from the first scan:
#region Overrides ProcessItemBarcode
//ProcessItemBarcode
public delegate void ProcessItemBarcodeDelegate(string barcode);
[PXOverride]
public virtual void ProcessItemBarcode(string barcode, ProcessItemBarcodeDelegate baseMethod)
{
try
{
string inventoryBC = barcode;
//...//get InvetoryID using Barcode
baseMethod?.Invoke(inventoryBC);
//how do you call the ProcessLotSerialBarcode function?
ProcessLotSerialBarcode(barcode, ProcessLotSerialBarcodeDelegate);
}
catch (Exception ex)
{//TODO: check if not a QR code
PXTrace.WriteError("ProcessItemBarcode Override: " + ex.Message);
baseMethod?.Invoke(barcode);
}
}
#endregion
#region Overrides ProcessLotSerialBarcode
//ProcessLotSerialBarcode
public delegate void ProcessLotSerialBarcodeDelegate(string barcode);
[PXOverride]
public virtual void ProcessLotSerialBarcode(string barcode, ProcessLotSerialBarcodeDelegate baseMethod)
{
try
{
string inventoryBC = "LOgic";
baseMethod?.Invoke(inventoryBC);
}
catch (Exception)
{
//TODO: check if not a QR code
baseMethod?.Invoke(barcode);
}
}
#endregion
[PXProtectedAccess]
public abstract class INScanReceiveHostExtProtectedAccess : PXGraphExtension<INScanReceiveHostExtCustomPackage, INScanReceive, INScanReceiveHost>
{
[PXProtectedAccess(typeof(INScanReceive))]
protected abstract void ProcessItemBarcode(string barcode);
[PXProtectedAccess(typeof(INScanReceive))]
protected abstract void ApplyState(string state);
[PXProtectedAccess(typeof(INScanReceive))]
protected abstract void ProcessLotSerialBarcode(string barcode);
}
I was also thinking of setting the state from the first method but then I need to call
Base.ApplyState(INScanIssue.ScanStates.Confirm);
Then I can set the Header and just keep resetting the scanner to the Confirm state. What do you think?
Because the method you are trying to override is protected, and not public, you will need to override the logic in a different way using the PXProtectedAccess attribute and an abstract graph extension.
namespace MyCustomPackage.Graph.Extension
{
public class INScanReceiveHostExtCustomPackage : PXGraphExtension<INScanReceive, INScanReceiveHost>
{
public static bool IsActive() => true;
#region Overrides
public delegate void ProcessItemBarcodeDelegate(string barcode);
[PXOverride]
public virtual void ProcessItemBarcode(string barcode, ProcessItemBarcodeDelegate baseMethod)
{
PXTrace.WriteInformation("Running abstract override");
baseMethod?.Invoke(barcode);
}
#endregion
}
[PXProtectedAccess]
public abstract class INScanReceiveHostExtProtectedAccess : PXGraphExtension<INScanReceiveHostExtCustomPackage, INScanReceive, INScanReceiveHost>
{
[PXProtectedAccess(typeof(INScanReceive))]
protected abstract void ProcessItemBarcode(string barcode);
}
}
I didn't have a good way to test this unfortunately, so you may need to tweak the type that is being passed to the PXProtectedAccess attribute above the abstract method. If this doesn't work, try passing the INScanReceiveHost type to the attribute and see if that works for you.

How do I get a hook into the Acumatica AR Document release?

gone through a variety of the articles, and none seem to "Work". In particular, 2021r1, not getting ANY of the PXTrace statement in the output
Challenge:
Static method of the graph directly called from ARPaymentEntry, and 4-5 overloads (From .\App_Data\CodeRepository\PX.Objects\AR\ARDocumentRelease.cs)
Eventually ends up calling a single method within that graph, starting with "public static void ReleaseDoc("
No clear place to add a delegate, though that seems the "most correct" method (E.g. question 37262565, comment from cbetabeta) - Yet the initialize event doesn't appear to be firing (possibly JIT optimization? Direct call into static method doesn't really need the class to be instantiated, I'd guess)
Also need a complete solution - e.g. Must handle the call from Payment Entry as well as from AR Document Release process
Sample Code:
using PX.Data;
using PX.Objects.AR;
using PX.Objects.GL;
using System.Collections;
using System.Collections.Generic;
using static PX.Objects.AR.ARDocumentRelease;
namespace Test.GraphExtensions
{
public class ARDocumentReleaseTestABC : PXGraphExtension<ARDocumentRelease>
{
// Tries include:
// https://html.developreference.com/article/11055300/How+to+customize+the+Process+button+on+the+AP505200+screen.+Acumatica
// https://stackoverflow.com/questions/36784480/customize-release-ap-document-in-acumatica-system
// https://stackoverflow.com/questions/37262565/how-can-i-execute-code-from-the-release-release-all-buttons-in-the-release-ar
// https://living-sun.com/es/acumatica/2179-extend-arpaymententry-release-action-acumatica.html
#region IsActive - Turn off if no setup record
public static bool IsActive()
{
return true;
}
#endregion IsActive - Turn off if no setup record
public virtual void BalancedARDocument_RowSelected(PXCache sender, PXRowSelectedEventArgs e)
{
PXTrace.WriteVerbose(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}", "dc1703c7-f8b7-4ce1-b838-d51475f4d477"));
}
public override void Initialize()
{
PXTrace.WriteVerbose(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}", "8ecc4f83-9ac8-4bb6-bad7-ac2aabc5b58e"));
}
public static void ReleaseDocRBRR(ARRegister ardoc, bool isAborted)
{
PXTrace.WriteVerbose(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0} {1} {2}", "20ae0d5e-44eb-42f2-ad15-0b9e307d2a86", isAborted, (ardoc == null)));
}
[PXUIField(DisplayName = "Release", MapEnableRights = PXCacheRights.Update, MapViewRights = PXCacheRights.Update)]
[PXProcessButton]
// [PXOverride]
public virtual IEnumerable Release(PXAdapter adapter)
{
PXTrace.WriteVerbose(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}", "0ccff0b7-7702-4083-b717-17b031e27be5"));
List<ARRegister> list = new List<ARRegister>();
return list;
}
}
}
The proper place to override is either ARReleaseProcess.OnBeforeRelease if you need your code to fire before the release code or ARReleaseProcess.ReleaseDocProc.
Also, if you just need to run your code after the release, it is recommended that you add your code to onreleasecomplete Delegate in ARReleaseProcess.ReleaseDocProc.
Also, if you just need to run your code after the document release and you do not necessarily need to have it run exactly in the same transaction, please consider adding a separate process that picks up released documents and processes them further. You can either schedule that process ti run in the backgroud every minute or put a trigger with Business Events.
I think its the namespace that is the issue:
namespace PX.Objects.AR
{
public class ARDocumentRelease_Extension : PXGraphExtension<ARDocumentRelease>
{
#region Event Handlers
public override void Initialize()
{
PXTrace.WriteVerbose(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}", "8ecc4f83-9ac8-4bb6-bad7-ac2aabc5b58e"));
}
#endregion
}
}
Seems I had a variety of issues, in particular was an extension to the wrong graph. Hooking up with Dmitrii's answer, I indicate at least some of the events that are hit, so others can use in the future
Code modified per #dmitrii-naumov's answer:
using PX.Data;
using PX.Objects.AR;
using PX.Objects.GL;
using System.Collections.Generic;
namespace Test.ABCD
{
public class ARDocumentReleaseTestABCD : PXGraphExtension<ARReleaseProcess>
{
#region IsActive - Turn off if no setup record
public static bool IsActive()
{
return true;
}
#endregion IsActive - Turn off if no setup record
public override void Initialize()
{
// Hit
PXTrace.WriteVerbose(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}", "8ecc4f83-9ac8-4bb6-bad7-ac2aabc5b58e"));
}
public delegate List<ARRegister> ReleaseDocProcDelegate(JournalEntry je, ARRegister ardoc, List<Batch> pmBatchList, ARDocumentRelease.ARMassProcessReleaseTransactionScopeDelegate onreleasecomplete);
[PXOverride]
public List<ARRegister> ReleaseDocProc(JournalEntry je, ARRegister ardoc, List<Batch> pmBatchList, ARDocumentRelease.ARMassProcessReleaseTransactionScopeDelegate onreleasecomplete, ReleaseDocProcDelegate del)
{
// Hit
PXTrace.WriteVerbose(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}", "8f153b0b-dd57-4893-aa8c-d29ea69528e4"));
PXTrace.WriteVerbose(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}", "9b1caa30-5abf-4f21-8c45-a55c4047441a"));
return null;
}
[PXOverride]
public virtual ARRegister OnBeforeRelease(ARRegister ardoc)
{
// Hit
PXTrace.WriteVerbose(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}", "741a01ad-5a37-40a8-ad10-a1fcd6659f7e"));
PXTrace.WriteVerbose(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}", "9b1caa30-5abf-4f21-8c45-a55c4047441a"));
return ardoc;
}
}
}
This version implements OnReleaseComplete, from code Dmitrii provided to me (I'll take the blame for mistakes, but he got the event hooked up correctly, so do get the OnComplete event displayed in the log):
public class ARDocumentReleaseTESTABC : PXGraphExtension<ARReleaseProcess>
{
#region IsActive
public static bool IsActive()
{
return true;
}
#endregion IsActive
public void OnReleaseComplete(ARRegister doc)
{
///code
PXTrace.WriteVerbose(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}", "7d22cef8-c14d-4111-bcc5-405be006ea6b"));
}
#region ReleaseDocProc
public delegate List<ARRegister> ReleaseDocProcDelegate(JournalEntry je, ARRegister ardoc, List<Batch> pmBatchList, ARDocumentRelease.ARMassProcessReleaseTransactionScopeDelegate onreleasecomplete);
[PXOverride]
public List<ARRegister> ReleaseDocProc(JournalEntry je, ARRegister ardoc, List<Batch> pmBatchList, ARDocumentRelease.ARMassProcessReleaseTransactionScopeDelegate onreleasecomplete, ReleaseDocProcDelegate del)
{
PXTrace.WriteVerbose(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}", "d508b521-976c-452b-9765-57f532a0a513"));
onreleasecomplete += OnReleaseComplete;
PXTrace.WriteVerbose(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}", "309e2e6b-6fb8-4c75-ab8a-40e56c173562"));
return del(je, ardoc, pmBatchList, onreleasecomplete);
}
#endregion
}

How to customize the Release Cash Transactions mass release screen

I am trying to customize the Release Cash Transactions screen and I am using this way to be able to call the Persist method, however when I release a record it does not enter the method specified above.
Here I am showing my code that if it works correctly for AP and AR.
I am doing the same for CA.
Could you help me that I'm wrong. Thanks for your help beforehand.
public class CAReleaseProcess_Extension : PXGraphExtension<CAReleaseProcess>
{
#region Custom
private WeakReference<JournalEntry> je;
public override void Initialize()
{
base.Initialize();
PXGraph.InstanceCreated.AddHandler<JournalEntry>(delegate (JournalEntry graph)
{
je = new WeakReference<JournalEntry>(graph);
});
}
public delegate void PersistDelegate();
[PXOverride]
public void Persist(PersistDelegate baseMethod)
{
CASplit doc = Base.CASplits.Current;
ActualizarCATaxTran(doc);
baseMethod();
}
public virtual void ActualizarCATaxTran(CASplit doc)
{
foreach (CATaxTran iTaxTran in Base.CATaxTran_TranType_RefNbr.Select(doc.AdjTranType, doc.AdjRefNbr))
{
if (iTaxTran != null)
{
//do something
}
}
}
#endregion
}
CA502000

Resources