Requirement
After clicking "Prepare Invoice" on the Shipments screen, I need to recalculate the invoice line items to match the actual quantity for the credit card charge. For instance, if the Sales Order (SO) has a quantity of 10 but only 2 have been shipped, the credit card fee should be based on the 2 quantities instead of the original 10. This involves two steps:
- Recalculate the invoice line items and update the document total accordingly.
- Once the recalculation is complete and the document is ready, programmatically trigger the capture button on the Applications tab.
I’m currently using the ARInvoice_RowPersisting
event in the SOInvoiceEntry
graph. While the recalculation works well, I’m struggling to find the right place to invoke the capture button. Whenever I attempt this, I encounter an Acuminator warning, and in some cases, it leads to an infinite loop or stack overflow exception.
I would appreciate your assistance.
CODE
/// <summary>
/// AR Invoice row persisting event to recalculate the CCFee
///
/// TODO: Only SO types and Credit Card. No other payment.
/// </summary>
/// <param name="cache"></param>
/// <param name="e"></param>
protected void ARInvoice_RowPersisting(PXCache cache, PXRowPersistingEventArgs e)
{
if (e.Operation == PXDBOperation.Delete && e.Operation == PXDBOperation.Update) return;
// Get inserted Sales Order detail line
var row = e.Row as ARInvoice;
SOInvoice invoice = PXSelect<SOInvoice,
Where<SOInvoice.docType, Equal<Required<SOInvoice.docType>>,
And<SOInvoice.refNbr,Equal<Required<SOInvoice.refNbr>>>>>
.Select(Base, row.DocType, row.RefNbr);
if(invoice != null && invoice.SOOrderType == "SO" )
{
//Extract the payment number associated with the invoice
ARAdjust2 adjust = PXSelect<ARAdjust2,
Where<ARAdjust2.adjdDocType, Equal<Required<ARAdjust.adjdDocType>>,
And<ARAdjust.adjdRefNbr, Equal<Required<ARAdjust.adjdRefNbr>>>>>
.Select(Base, row.DocType, row.RefNbr);
ExternalTransaction extTran = null;
//If there's any payment associated then
if (adjust != null)
{
// extract the Processing Status of
extTran = PXSelect<ExternalTransaction,
Where<ExternalTransaction.docType, Equal<Required<ExternalTransaction.docType>>,
And<ExternalTransaction.refNbr, Equal<Required<ExternalTransaction.refNbr>>>>>
.Select(Base, adjust.AdjgDocType, adjust.AdjgRefNbr);
}
//Check if the status of payment is Pre-Authorized or not. If not dont do anything. Let acumatic run its default algorithm.
if (extTran != null && extTran.ProcStatus !=null)
{
if (extTran.ProcStatus == "AUS" )
{
InventoryItem inventoryItem = PXSelect<InventoryItem,
Where<InventoryItem.inventoryCD, Equal<Required<InventoryItem.inventoryCD>>>>
.Select(Base, "CREDITCARDFEE");
decimal? taxAmt = Base.Taxes.Current.TaxAmt;
if (taxAmt == null)
{
taxAmt = 0;
}
if (inventoryItem != null)
{
var markupPct = inventoryItem.MarkupPct;
if (markupPct != null && markupPct > 0)
{
List<ARTran> trans = Base.Transactions.Select().RowCast<ARTran>().ToList();
if (trans != null && trans.Any())
{
ARTran currentInv = PXSelect<ARTran,
Where<ARTran.refNbr, Equal<Required<ARTran.refNbr>>,
And<ARTran.inventoryID, Equal<Required<ARTran.inventoryID>>>>>
.Select(Base, row.RefNbr, inventoryItem.InventoryID);
decimal? sumofAllLineItemsExceptCCFee = trans.Where(c => c.InventoryID != inventoryItem.InventoryID).Sum(c => c.CuryExtPrice);
var newCuryUnitPrice = ((sumofAllLineItemsExceptCCFee + taxAmt) * markupPct) / 100;
currentInv.CuryUnitPrice = newCuryUnitPrice;
currentInv.CuryExtPrice = newCuryUnitPrice;
//cache.SetValueExt<ARTran.curyUnitPrice>(row, newCuryUnitPrice);
//cache.SetValueExt<ARTran.curyExtPrice>(row, newCuryUnitPrice);
Base.Transactions.Update(currentInv);
Base.Document.Update(row);
}
}
}
}
}
}
}
‘