Skip to main content

I have a custom processing screen that sets some custom fields (for stale dated checks, they get  a lot of these due to small amount refunds that never get cashed).  My client wants these to be voided automatically at the same time which means in code it needs to call the void action on the APPaymentEntry graph, remove the hold flag and call the release action.  Not having much luck pulling all of this together.  We had an import scenario to do the void after setting the stale dated info but they want it to be all in one step.

Here is the main processing loop.  Most of these will be Quick Checks (but not all) 

Correction, these will only be quick checks 
       

public static void Process(List<APPayment> payments)
        {
         

            var globalError = false;

            var graph = CreateInstance<APPaymentEntry>();


            var checkNumber = string.Empty;

            DateTime? currBusinessDate = graph.Accessinfo.BusinessDate;
            Guid currUser = graph.Accessinfo.UserID;

            foreach (var payment in payments) {
               
                var lineError = false;

                try
                {
                    graph.Clear();

                    checkNumber = payment.ExtRefNbr;

                    graph.Document.Current = payment;
                    
                    var origCheckNo = graph.Document.GetValueExt<APRegisterExt.usrOrigCheckNo>(payment);

                    if (origCheckNo == null || (string)origCheckNo == string.Empty)
                    {
                        PXDatabase.Update<APRegister>(new PXDataFieldAssign<APRegisterExt.usrStaleDated>(true),
                           new PXDataFieldAssign<APRegisterExt.usrStaleDatedBy>(currUser),
                           new PXDataFieldAssign<APRegisterExt.usrStaleDatedOn>(currBusinessDate),
                           new PXDataFieldAssign<APRegisterExt.usrOrigCheckNo>(payment.ExtRefNbr),
                           new PXDataFieldRestrict<APRegister.refNbr>(payment.RefNbr),
                           new PXDataFieldRestrict<APRegister.docType>(payment.DocType));
                    }
                    else
                    {
                        PXDatabase.Update<APRegister>(new PXDataFieldAssign<APRegisterExt.usrStaleDated>(true),
                            new PXDataFieldAssign<APRegisterExt.usrStaleDatedBy>(currUser),
                            new PXDataFieldAssign<APRegisterExt.usrStaleDatedOn>(currBusinessDate),
                            new PXDataFieldRestrict<APRegister.refNbr>(payment.RefNbr),
                            new PXDataFieldRestrict<APRegister.docType>(payment.DocType));
                    }

                    // Go ahead and void it here?
                    // this doesn't seem to do anything (not voided, put on hold, etc.)
                    var result =  graph.VoidCheck(new PXAdapter(graph.Document));
                    graph.Persist();
                    // Once the above works, we need to take off hold
                    // Then release
                }
                catch (Exception e)
                {

                    //set line error to true so will skip the process correct below

                    lineError = true;

                    //set globaError flag to true to get the global message

                    globalError = true;

                    //create a custom error message to post on the grid

                    var message = "Error Processing Check: " + checkNumber + ": " + e.Message;
                    PXTrace.WriteError(message);
                    PXTrace.WriteError(e);

                    //add the custom error message to the grid line 
                    PXProcessing.SetError(payments.IndexOf(payment), message);
                }

                var messageTwo = "Check: " + checkNumber + " Was Processed.";

                if (!lineError) PXProcessing.SetInfo(payments.IndexOf(payment), messageTwo);

            }

 

 

 

Update: got a little further (sort of answered my own question when I realized we are just doing quickchecks)  So after changing the processing view to APQuickCheck and the graph to APQuickCheckEntry I’m getting void.  However, the release fails with error: Document Status is invalid for processing.  If I look in debugger, the Document.Current is the VQC doctype and I’ve removed hold so not sure why it’s complaining.

 

                   // Go ahead and void it here?

                    var result =  graph.VoidCheck(new PXAdapter(graph.Document));

                    graph.Persist();

                    graph.Document.Current.Hold = false;

                    graph.Document.Current.Status = APDocStatus.Balanced;

                    graph.Persist();

// fails on following line:

                    graph.Release(new PXAdapter(graph.Document)); 

                    graph.Persist();


Hi @rjean09 Probably the document status is NOT Balance Status. Can comment other code and verify if the document is going to Balanced Status (and not in HOLD status).


Hi @ChandrasekharM  You are correct.  If I comment the release line I do not get an error any more, but voided quick check (VQC) is still on hold.  Maybe I need to create another instance of my quick check entry graph to remove the hold and release?


Hi @rjean09 OK. So the next step is to bring the Voided Check in “Balanced” Status. Try using cache update.

Thanks 


Hi @rjean09 Please find the below settings change that may work for you without changes to the Code. If the “Hold Documents on Entry” is unselected, all the payables document will go to “Balanced” status by default. Hence, you also need to verify with the functional consultant or admin to turn off this setting.

Thanks


Thanks for cache update. I totally forgot about that. Hold and status change now persisting.  Yay!  However, release still gives same error.

Here is what I have now:

  using (var ts = new PXTransactionScope())

                    {

                        // Go ahead and void it here?

                        var result = graph.VoidCheck(new PXAdapter(graph.Document));

                        // do I need to get something from result and populate current with that?

                        graph.Persist();

                        graph.Document.Current.Hold = false;

                        graph.Document.Current.Status = APDocStatus.Balanced;

                        graph.Document.Cache.Update(graph.Document.Current);

                        graph.Actions.PressSave();

                        // graph.Persist();

                        // the next line fails with incorrect status

                        // graph.Release(new PXAdapter(graph.Document));

                        // graph.Persist();

                        ts.Complete();

                    }


Hi @rjean09 Please comment the below code and try. Acumatica will automatically change the status to Balanced.

graph.Document.Current.Status = APDocStatus.Balanced;

 

Thanks


Just getting back to this (was at Summit 2021).

I now have the void working all the way through but I can’t seem to get the final release step to work.  I’m getting a concurrency error.  I’m not sure how to reload my current view from the database to get around this.

 

 

foreach (var payment in payments) {

               

                var lineError = false;

                try

                {

                    graph.Clear();

                    checkNumber = payment.ExtRefNbr;

                    graph.Document.Current = payment;

                    // update stale date custom fields

                    var origCheckNo = graph.Document.GetValueExt<APRegisterExt.usrOrigCheckNo>(payment);

                    using (var ts = new PXTransactionScope())

                    {

                        if (origCheckNo == null || (string)origCheckNo == string.Empty)

                        {

                            PXDatabase.Update<APRegister>(new PXDataFieldAssign<APRegisterExt.usrStaleDated>(true),

                               new PXDataFieldAssign<APRegisterExt.usrStaleDatedBy>(currUser),

                               new PXDataFieldAssign<APRegisterExt.usrStaleDatedOn>(currBusinessDate),

                               new PXDataFieldAssign<APRegisterExt.usrOrigCheckNo>(payment.ExtRefNbr),

                               new PXDataFieldRestrict<APRegister.refNbr>(payment.RefNbr),

                               new PXDataFieldRestrict<APRegister.docType>(payment.DocType));

                        }

                        else

                        {

                            PXDatabase.Update<APRegister>(new PXDataFieldAssign<APRegisterExt.usrStaleDated>(true),

                                new PXDataFieldAssign<APRegisterExt.usrStaleDatedBy>(currUser),

                                new PXDataFieldAssign<APRegisterExt.usrStaleDatedOn>(currBusinessDate),

                                new PXDataFieldRestrict<APRegister.refNbr>(payment.RefNbr),

                                new PXDataFieldRestrict<APRegister.docType>(payment.DocType));

                        }

                        ts.Complete();

                    }

                    using (var ts = new PXTransactionScope())

                    {

                        // Go ahead and void it here

                        var result = graph.VoidCheck(new PXAdapter(graph.Document));

                        graph.Persist();

                        // remove hold

                        graph.Document.Current.Hold = false;

                        // set stale dated account number on void

                        foreach (APTran item in graph.Transactions.Select())

                        {

                            item.AccountID = thisGraph.GetGLAccountID("460400");

                            graph.Transactions.Cache.Update(item);

                        }

                        graph.Document.Cache.Update(graph.Document.Current);

                        graph.Actions.PressSave();

                        ts.Complete();

                    }

                    // refresh the timestamp from the database?

                    graph.SelectTimeStamp();

                    // Release

                    List<APRegister> reg = new List<APRegister>();

                    reg.Add(graph.Document.Current);

                    APDocumentRelease.ReleaseDoc(reg, false);  // FAILS HERE with "another process has updated the APRegister record


                }…


This link on StackOverflow describes my problem exactly.  

 

StackOverflow

 

However, I tried modifying my code to match and still getting “another process has updated the APRegister record”

 

Here is the snippet where I am trying to do this now:

 

                    graph.Caches"APRegister"].ClearQueryCache();

                    APRegister apRegister = new PXSelect<APRegister, Where<APRegister.docType, Equal<Required<APRegister.docType>>, And<APRegister.refNbr, Equal<Required<APRegister.refNbr>>>>>(graph).SelectSingle(APDocType.VoidQuickCheck, payment.RefNbr);

                    using (var ts = new PXTransactionScope())

                    {

                        graph.SelectTimeStamp();

                        APDocumentRelease.ReleaseDoc(new List<APRegister>() { apRegister }, false);  // FAILS HERE with "another process has updated the APRegister record"

                        ts.Complete();

                    }


Dug into the ReleaseDoc static method and noticed this code:

if (aPRegister.Passed == true)
{
aPReleaseProcess.TimeStamp = aPRegister.tstamp;
}

I added this before my call:
apRegister.Passed = true;

Works now!


Hi @rjean09 , Thanks for the update


Reply