Skip to main content
Answer

Override Pay/Apply Document to Process Multiple Invoices in Customer Details Inquiry Screen

  • March 8, 2025
  • 4 replies
  • 71 views

DipakNilkanth
Pro III
Forum|alt.badge.img+13

Hi Community,

I’m working on the Customer Details Inquiry screen in Acumatica, specifically on the Pay/Apply Document action. I’ve overridden this action to handle multiple document selection so I can apply payments to multiple invoices at once. Here’s the code I’m using:

public delegate IEnumerable PayDocumentDelegate(PXAdapter adapter);
[PXOverride]
public virtual IEnumerable PayDocument(PXAdapter adapter, PayDocumentDelegate baseMethod)
{



List<ARDocumentEnq.ARDocumentResult> selectedDocuments = Base.Documents.Cache.Updated
.RowCast<ARDocumentEnq.ARDocumentResult>()
.Where(shipment => PXCache<ARDocumentEnq.ARDocumentResult>
.GetExtension<ARDocumentResultExt>(shipment)?.UsrSelect == true)
.ToList();



if (!selectedDocuments.Any())
{
// Fall back to base behavior if no rows are selected
return baseMethod(adapter);
}

// Iterate through each selected document
foreach (var doc in selectedDocuments)
{


if (ARDocType.Payable(doc.DocType) == true)
{
// Create an instance of ARInvoiceEntry for each document
ARInvoiceEntry invoiceGraph = PXGraph.CreateInstance<ARInvoiceEntry>();

// Retrieve the ARInvoice for the selected document
ARInvoice invoice = PXSelect<ARInvoice,
Where<ARInvoice.docType, Equal<Required<ARInvoice.docType>>,
And<ARInvoice.refNbr, Equal<Required<ARInvoice.refNbr>>>>>
.Select(Base, doc.DocType, doc.RefNbr)
.FirstOrDefault();

if (invoice != null)
{
// Assign the retrieved invoice to the graph
invoiceGraph.Document.Current = invoice;

// Process payment
invoiceGraph.PayInvoice(adapter);
}
}
}

// Return default filter view
return Base.Filter.Select();
}

The issue I’m facing is that it’s not working as expected — the payment is still only applied to a single document, not multiple. I’d really appreciate any guidance on how I can properly apply payments to multiple invoices from the Customer Details Inquiry screen to the Payments and Applications screen.
I have added custom checkbox field UsrSelect to select multiple documents.

Thanks in advance for your help!

Best answer by DipakNilkanth

Hi Community,

I’ve implemented the following code logic to pass multiple records at a time to the Payments and Applications screen from the Customer Details screen when clicking the Pay/Apply Document action, and it’s working as expected.

Previously, I was just transferring the records directly. However, I’ve now created a list and written code to insert those records into the ARAdjust DAC.

 

public delegate IEnumerable PayDocumentDelegate(PXAdapter adapter);
[PXOverride]
public virtual IEnumerable PayDocument(PXAdapter adapter, PayDocumentDelegate baseMethod)
{
// Get selected documents
List<ARDocumentEnq.ARDocumentResult> selectedDocuments = Base.Documents.Cache.Updated
.RowCast<ARDocumentEnq.ARDocumentResult>()
.Where(doc => PXCache<ARDocumentEnq.ARDocumentResult>
.GetExtension<ARDocumentResultExtensionsTSExt>(doc)?.UsrSelected == true)
.ToList();

if (!selectedDocuments.Any())
{
// Fall back to base behavior if no rows are selected
return baseMethod(adapter);
}

// Create a list to store invoices that need to be processed
List<ARInvoice> invoicesToProcess = new List<ARInvoice>();
// Process each selected document
foreach (var doc in selectedDocuments)
{
if (doc.GetExtension<ARDocumentResultExtensionsTSExt>().UsrSelected == true)
{
// Retrieve the ARInvoice for the selected document
ARInvoice invoice = PXSelect<ARInvoice,
Where<ARInvoice.docType, Equal<Required<ARInvoice.docType>>,
And<ARInvoice.refNbr, Equal<Required<ARInvoice.refNbr>>>>>
.Select(Base, doc.DocType, doc.RefNbr);

if (invoice != null)
{
invoicesToProcess.Add(invoice);
}
}
}

if (invoicesToProcess.Count > 0)
{
// Create a payment entry graph
ARPaymentEntry paymentGraph = PXGraph.CreateInstance<ARPaymentEntry>();

// Set up the payment with the first invoice
ARInvoice firstInvoice = invoicesToProcess[0];

// Create the payment document
paymentGraph.Document.Insert();
paymentGraph.Document.Current.CustomerID = firstInvoice.CustomerID;
paymentGraph.Document.Current.DocType = ARPaymentType.Payment;
paymentGraph.Document.Current.AdjDate = firstInvoice.DocDate;
paymentGraph.Document.Current.CuryOrigDocAmt = 0m; // Will be calculated from added adjustments
paymentGraph.Document.Update(paymentGraph.Document.Current);

// Add each invoice as an adjustment
foreach (ARInvoice invoice in invoicesToProcess)
{
// Check if the adjustment already exists
ARAdjust existingAdjustment = PXSelect<ARAdjust,
Where<ARAdjust.adjdDocType, Equal<Required<ARAdjust.adjdDocType>>,
And<ARAdjust.adjdRefNbr, Equal<Required<ARAdjust.adjdRefNbr>>,
And<ARAdjust.adjgDocType, Equal<Required<ARAdjust.adjgDocType>>,
And<ARAdjust.adjgRefNbr, Equal<Required<ARAdjust.adjgRefNbr>>>>>>>
.Select(paymentGraph, invoice.DocType, invoice.RefNbr,
paymentGraph.Document.Current.DocType,
paymentGraph.Document.Current.RefNbr);

if (existingAdjustment == null)
{
// Create a new adjustment
ARAdjust adj = new ARAdjust();
adj.AdjdDocType = invoice.DocType;
adj.AdjdRefNbr = invoice.RefNbr;
adj.AdjdCustomerID = invoice.CustomerID;
adj.CuryAdjgAmt = invoice.CuryDocBal;

// Insert the adjustment
paymentGraph.Adjustments.Insert(adj);
}
}

// Redirect to the payment screen
throw new PXRedirectRequiredException(paymentGraph, "Payment & Application");
}

// Return default filter view
return Base.Filter.Select();
}

Thank you for taking the time to review this!

4 replies

darylbowman
Captain II
Forum|alt.badge.img+15

Have you in some way determined if your code is being executed / making it to the foreach?


DipakNilkanth
Pro III
Forum|alt.badge.img+13
  • Author
  • Pro III
  • March 10, 2025

Hi ​@darylbowman,

Thanks for your response! Yes, my code is being executed, and it is copying/inserting one record. While debugging, I noticed that it was only processing one record when calling the PayInvoice action.

After some research and digging, I was able to pass multiple records at a time. It’s working now, and I’m testing it further. I’ll post my code once it’s fully resolved.


DipakNilkanth
Pro III
Forum|alt.badge.img+13
  • Author
  • Pro III
  • Answer
  • March 10, 2025

Hi Community,

I’ve implemented the following code logic to pass multiple records at a time to the Payments and Applications screen from the Customer Details screen when clicking the Pay/Apply Document action, and it’s working as expected.

Previously, I was just transferring the records directly. However, I’ve now created a list and written code to insert those records into the ARAdjust DAC.

 

public delegate IEnumerable PayDocumentDelegate(PXAdapter adapter);
[PXOverride]
public virtual IEnumerable PayDocument(PXAdapter adapter, PayDocumentDelegate baseMethod)
{
// Get selected documents
List<ARDocumentEnq.ARDocumentResult> selectedDocuments = Base.Documents.Cache.Updated
.RowCast<ARDocumentEnq.ARDocumentResult>()
.Where(doc => PXCache<ARDocumentEnq.ARDocumentResult>
.GetExtension<ARDocumentResultExtensionsTSExt>(doc)?.UsrSelected == true)
.ToList();

if (!selectedDocuments.Any())
{
// Fall back to base behavior if no rows are selected
return baseMethod(adapter);
}

// Create a list to store invoices that need to be processed
List<ARInvoice> invoicesToProcess = new List<ARInvoice>();
// Process each selected document
foreach (var doc in selectedDocuments)
{
if (doc.GetExtension<ARDocumentResultExtensionsTSExt>().UsrSelected == true)
{
// Retrieve the ARInvoice for the selected document
ARInvoice invoice = PXSelect<ARInvoice,
Where<ARInvoice.docType, Equal<Required<ARInvoice.docType>>,
And<ARInvoice.refNbr, Equal<Required<ARInvoice.refNbr>>>>>
.Select(Base, doc.DocType, doc.RefNbr);

if (invoice != null)
{
invoicesToProcess.Add(invoice);
}
}
}

if (invoicesToProcess.Count > 0)
{
// Create a payment entry graph
ARPaymentEntry paymentGraph = PXGraph.CreateInstance<ARPaymentEntry>();

// Set up the payment with the first invoice
ARInvoice firstInvoice = invoicesToProcess[0];

// Create the payment document
paymentGraph.Document.Insert();
paymentGraph.Document.Current.CustomerID = firstInvoice.CustomerID;
paymentGraph.Document.Current.DocType = ARPaymentType.Payment;
paymentGraph.Document.Current.AdjDate = firstInvoice.DocDate;
paymentGraph.Document.Current.CuryOrigDocAmt = 0m; // Will be calculated from added adjustments
paymentGraph.Document.Update(paymentGraph.Document.Current);

// Add each invoice as an adjustment
foreach (ARInvoice invoice in invoicesToProcess)
{
// Check if the adjustment already exists
ARAdjust existingAdjustment = PXSelect<ARAdjust,
Where<ARAdjust.adjdDocType, Equal<Required<ARAdjust.adjdDocType>>,
And<ARAdjust.adjdRefNbr, Equal<Required<ARAdjust.adjdRefNbr>>,
And<ARAdjust.adjgDocType, Equal<Required<ARAdjust.adjgDocType>>,
And<ARAdjust.adjgRefNbr, Equal<Required<ARAdjust.adjgRefNbr>>>>>>>
.Select(paymentGraph, invoice.DocType, invoice.RefNbr,
paymentGraph.Document.Current.DocType,
paymentGraph.Document.Current.RefNbr);

if (existingAdjustment == null)
{
// Create a new adjustment
ARAdjust adj = new ARAdjust();
adj.AdjdDocType = invoice.DocType;
adj.AdjdRefNbr = invoice.RefNbr;
adj.AdjdCustomerID = invoice.CustomerID;
adj.CuryAdjgAmt = invoice.CuryDocBal;

// Insert the adjustment
paymentGraph.Adjustments.Insert(adj);
}
}

// Redirect to the payment screen
throw new PXRedirectRequiredException(paymentGraph, "Payment & Application");
}

// Return default filter view
return Base.Filter.Select();
}

Thank you for taking the time to review this!


Chris Hackett
Community Manager
Forum|alt.badge.img
  • Acumatica Community Manager
  • March 11, 2025

Thank you for sharing your solution with the community ​@Nilkanth Dipak!