Skip to main content

I have a custom table that stores the customer ID of customers that have been merged in my “Merge Customers” application.  After customers get merged, I want to automatically select them to be processed on the Recalculate Customer Balances screen.  After merging, it is just simpler to let Acumatica calculate the new customer balances than to do it myself.

I created an extension for that graph.  The idea is that I redirect to this screen at the end of the Merge Customers process and the user simply has to click PROCESS on the screen as all the affected customers would be selected already.

In the extension, I thought I could use the RowInserting method on the grid to check the box on the line if it was in my custom table.  That line doesn’t fire when the grid is being filled from the related View. I also tried FieldVerifying on the Customer field of the grid (and a few others) but they don’t fire unless you actually interact with the grid.

Just to try to get something to work, I committed a sin and put my code in the RowSelected event for the Filter.  I KNOW this is bad, but it was a last resort to test my idea.

The code checks the box on the lines that have a matching record in my table.  BUT, they are not seen as being checked because the cache is not seen as updated by my changing the selected value on the line item.

namespace PX.Objects.AR
{
    // Acuminator disable once PX1016 ExtensionDoesNotDeclareIsActiveMethod extension should be constantly active
    public sealed class ARIntegrityCheck_Extension : PXGraphExtension<PX.Objects.AR.ARIntegrityCheck>
    {
        #region Event Handlers
        protected void Customer_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
        {
            Customer row = (Customer)e.Row;

            if (row == null) return;

            ICSCustomersToRebuild cust = SelectFrom<ICSCustomersToRebuild>.Where<ICSCustomersToRebuild.customerID.IsEqual<@P.AsInt>>.View.Select(Base, row.BAccountID);

            if (cust != null)
            {
                row.Selected = true;
            }
        }
        #endregion
    }
}

What method would I use to “cycle” through the grid and update the selected checkbox after the View has been loaded?  

 

@joe21 

 

Use a aPXDefault] to address it.


@Leonardo Justiniano  I think I see where you are going.  So I would do an override to that field (attribute) and use a PXDefault to check if it should be true based on whether or not the current record is in my custom table?  


Yes @joe21 

 

If you need to pre-set a value there, you need to override the field via CacheAttached with a default query that determines if it’s selected or not.


Acumatica helped me generate this code from the screen editor.  :-)

Please don’t write any code for me.  I want to crawl my way through this.  I am just wanting you to poing me in the right direction (which you are doing).  THANK YOU.

        PXBool]
        rPXDefault(false, PersistingCheck = PXPersistingCheck.Nothing)]
        nPXUIField(DisplayName = "Selected")]
        protected virtual void Customer_Selected_CacheAttached(PXCache cache)
        {

          DO CODE HERE?
        }

 


@joe21  Add a FieldDefaulting event and manage your query there,


@Leonardo Justiniano 

Here is what I have.  I put in a RowSelected event handler just to make sure this extension is firing and that event does fire in debug.

However, the FieldVerifying does not get fired.  Am I missing something?

    public class ARIntegrityCheck_Extension : PXGraphExtension<PX.Objects.AR.ARIntegrityCheck>
    {
        #region Event Handlers
        protected void Customer_Selected_FieldVerifying(PXCache cache, PXFieldVerifyingEventArgs e)
        {
            var row = (Customer)e.Row;
            if (row == null) return;

            ICSCustomersToRebuild cust = SelectFrom<ICSCustomersToRebuild>.
                Where<ICSCustomersToRebuild.customerID.IsEqual<@P.AsInt>>
                .View.Select(Base, row.BAccountID);

            if (cust != null)
            {
                e.NewValue = true;
            }
        }

        //just testing to make sure the extension is firing
        protected void ARIntegrityCheckFilter_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
        {
            var row = (ARIntegrityCheckFilter)e.Row;
            string joe = "";
        }
        #endregion
    }
 


@joe21 

 

Hi, From what you describe it’s firing. Isn’t it? (FieldDefaulting) The code looks 0k to me,

 


RowSelected fires, but FieldVerifying (Field Defaulting, Field Updating etc.) do no fire.  That is why I tried doing it via rowselected because I can’t get those other events to fire.  Baffling me.

I’ve been trying to do it in CacheAttached like this:

        PXBool]
        rPXDefault(typeof(Switch<Case<Where<Search2<Customer.bAccountID, InnerJoin<ICSCustomersToRebuild, On<ICSCustomersToRebuild.customerID, Equal<Customer.bAccountID>>>>>, True>, False>), PersistingCheck = PXPersistingCheck.Nothing)]

        ]PXUIField(DisplayName = "Selected")]
        protected virtual void Customer_Selected_CacheAttached(PXCache cache)
        {
        }

but the Search2 does not return a Unary value.  I’m trying to get this to work without you saving me by writing the code for me.  HA!  I’ve spent about 2 days trying to work this out.

 

 


Quick update…

The event fires when I click the checkbox on the grid.  But it does not fire when the grid is initially being populated. 


RowSelected fires, but FieldVerifying (Field Defaulting, Field Updating etc.) do no fire.  That is why I tried doing it via rowselected because I can’t get those other events to fire.  Baffling me.

Oh ok @joe21 Now I got it. I think you might need to override the view delegate (ARCustomerList) instead:

protected virtual IEnumerable arcustomerlist()
{

if (Filter.Current != null && Filter.Current.CustomerClassID != null)
{
using (new PXFieldScope(Customer_ClassID.View,
typeof(Customer.bAccountID),
typeof(Customer.acctCD),
typeof(Customer.customerClassID)))

// Custom code
// return Customer_ClassID.SelectDelegateResult();

foreach(var line in Customer_ClassID.SelectDelegateResult())
{
// Your code here

yield return line;
}
}
else
{
using (new PXFieldScope(Customers.View,
typeof(Customer.bAccountID),
typeof(Customer.acctCD),
typeof(Customer.customerClassID)))
return Customers.SelectDelegateResult();
// Custom code
// return Customers.SelectDelegateResult();

foreach(var line in Customers.SelectDelegateResult())
{
// Your code here

yield return line;
}

}

}

 


@Leonardo Justiniano  You rule.

This worked perfectly! 

Here is my final code in case anyone ever wants to see the final product (not that anyone would ever need to do this...)

        protected virtual IEnumerable arcustomerlist()
        {

            if (Base.Filter.Current != null && Base.Filter.Current.CustomerClassID != null)
            {
                using (new PXFieldScope(Base.Customer_ClassID.View,
                    typeof(Customer.bAccountID),
                    typeof(Customer.acctCD),
                    typeof(Customer.customerClassID)))

                    foreach (Customer line in Base.Customer_ClassID.SelectDelegateResult())
                    {
                        ICSCustomersToRebuild cust = SelectFrom<ICSCustomersToRebuild>.
                            Where<ICSCustomersToRebuild.customerID.IsEqual<@P.AsInt>>
                            .View.Select(Base, line.BAccountID);

                        if (cust != null)
                        {
                            line.Selected = true;
                        }
                        yield return line;
                    }
            }
            else
            {
                using (new PXFieldScope(Base.Customers.View,
                    typeof(Customer.bAccountID),
                    typeof(Customer.acctCD),
                    typeof(Customer.customerClassID)))

                    foreach (Customer line in Base.Customers.SelectDelegateResult())
                    {
                        ICSCustomersToRebuild cust = SelectFrom<ICSCustomersToRebuild>.
                            Where<ICSCustomersToRebuild.customerID.IsEqual<@P.AsInt>>
                            .View.Select(Base, line.BAccountID);

                        if (cust != null)
                        {
                            line.Selected = true;
                        }
                        yield return line;
                    }
            }
        }
 


Quick addendum.  I’m only posting this because I’m kind of proud that I figured this out.

@Leonardo Justiniano had the solution to get the items marked as selected.  However, the record that was selected was not flagged as updated so the PROCESS button didn’t do anything.  I put this code in to mark the selected records as Updated so that the PROCESS button would pick them up.

        protected void ARIntegrityCheckFilter_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
        {
            var row = (ARIntegrityCheckFilter)e.Row;
            if (row == null) return;

            var custCache = Base.Caches>typeof(Customer)];

            foreach (Customer cust in Base.ARCustomerList.Select())
            {
                if (cust.Selected == true)
                {
                    custCache.MarkUpdated(cust);
                }
            }
        }
The RowSelected event for the filter fires 3 or so times so the code here fires a few times, but the overhead due to this is pretty minimal.

😁


Quick addendum.  I’m only posting this because I’m kind of proud that I figured this out.

@Leonardo Justiniano had the solution to get the items marked as selected.  However, the record that was selected was not flagged as updated so the PROCESS button didn’t do anything.  I put this code in to mark the selected records as Updated so that the PROCESS button would pick them up.

        protected void ARIntegrityCheckFilter_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
        {
            var row = (ARIntegrityCheckFilter)e.Row;
            if (row == null) return;

            var custCache = Base.Caches>typeof(Customer)];

            foreach (Customer cust in Base.ARCustomerList.Select())
            {
                if (cust.Selected == true)
                {
                    custCache.MarkUpdated(cust);
                }
            }
        }
The RowSelected event for the filter fires 3 or so times so the code here fires a few times, but the overhead due to this is pretty minimal.

😁

Yes! 


Reply