Skip to main content

As you may have come across, in most of Aumatica screens when we change InventoryID, many other fields for the row get reset forcing user to re-enter the values that results in wasting time and frustration. We are experiencing this on our heavily used AP Bills and Purchase Order. As pilot I tried to fix POLine to restore the values entered by user when InventoryID is changed through RowUpdated event handler. 

The code works and restores the value of intended fields (see partial code below) but the problem is the total fields of the header are not refreshed. For example if I have only one POLine, upon chaning the InventoryID, header is reset to zero but when the custom handler restores the POLine values, the header remains zero.

Can someone advise how I can refresh POOrder related totals when POLine value is updated in event handler of POLine?

 

        protected void POLine_RowUpdated(PXCache cache, PXRowUpdatedEventArgs e, PXRowUpdated InvokeBaseHandler)
{
//InvokeBaseHandler?.Invoke(cache, e);

var newRow = e.Row as POLine;
var oldRow = e.OldRow as POLine;

if (newRow != null && oldRow != null)
{
if (newRow.InventoryID != oldRow.InventoryID)
{
if (oldRow.CuryLineAmt != decimal.Zero && newRow.CuryLineAmt == decimal.Zero)
{
newRow.CuryLineAmt = oldRow.CuryLineAmt;
newRow.CuryDiscAmt = oldRow.CuryDiscAmt;
newRow.CuryRetainageAmt = oldRow.CuryRetainageAmt;
}
}
}
}

 

Hi @aaghaei 

Please try with below line code,

Base.Document.View.RequestRefresh();

Normally the CuryLineAmt, CuryLineAmt fields have the property commit changes=true, If any values are updated, they should recalculate and reflect in total without refreshing the header.


Thanks @jinin 

The RequestRefresh command will help if the record set is updated but UI is not. In my case my POOrder cache is not updated so will not make any difference but anyways I tested and as I expeced the outcome didn’t change.

 

As you indicated these two fields CommitChanges by default are set to True by Acumatica itself. That is why when user enters value for them in the Grid, it updates the header summary fields and I had mentioned it in my original post.

 

Any other thought? 


@aaghaei It seems that the POTaxAttribute attached to POLine.TaxcategoryID is the one responsible for updating Line Total (curyLineTotal) at the header using SumCalc<>, so, you can emulate this by doing the following in your event:

PXFormulaAttribute.SetAggregate<POLine.curyExtCost>(Base.Cachesetypeof(POLine)], typeof(SumCalc<POOrder.curyLineTotal>));
PXFormulaAttribute.CalcAggregate<POLine.curyExtCost>(Base.Cachesetypeof(POLine)], poOrderRow);

 


Thank you @Dioris Aguilar 

You are right the TaxCategoryID is responsible to update POTax, PORetainedTax and POUnbilled Tax but 1) there are more fields on the header that need to be reclaculated and the POTax tab also will need to be updated. I slightly changed your suggested code as follow to work but it only updates CuryLineTotal.

PXFormulaAttribute.SetAggregate<POLine.curyExtCost>(Base.Cachesetypeof(POLine)], typeof(SumCalc<POOrder.curyLineTotal>));
PXFormulaAttribute.CalcAggregate<POLine.curyExtCost>(Base.Cachesetypeof(POLine)], Base.Document.Current);
 

Considering the complication around tax per line I’m unsure how the rest of the fields can be updated when not a single field in line make up most of the fields on header. Any thought?


@aaghaei You can see the remaining fields in the header are calculated inside the POUnbilledTaxAttribute and PORetainedTaxAttribute also attached to TaxCategoryID, and they inherit from TaxAttribute, so, maybe what’s needed is only recalculate the taxes for the whole document. Try the following in your RowUpdated event and probably by doing this the SetAggregate and CalcAggregate won’t be needed since the POTaxAttribute also inherits from TaxAttribute:
 

TaxAttribute.InvokeRecalcTaxes(sender);

 


@Dioris Aguilar thank you for all your help. Your suggested approach didn’t work but I figured out how to make it work. All I had to do was to Invoke the base handler after my custom code. Here is my completed code that works as intended.

        protected void POLine_RowUpdated(PXCache cache, PXRowUpdatedEventArgs e, PXRowUpdated InvokeBaseHandler)
{
var newRow = e.Row as POLine;
var oldRow = e.OldRow as POLine;

if (newRow != null && oldRow != null)
{
if (newRow.InventoryID != oldRow.InventoryID || newRow.UOM != oldRow.UOM)
{
if (oldRow.CuryLineAmt != decimal.Zero && newRow.CuryLineAmt == decimal.Zero)
{
newRow.TranDesc = oldRow.TranDesc;
newRow.TaxCategoryID = oldRow.TaxCategoryID;

newRow.OrderQty = oldRow.OrderQty;
newRow.UnitCost = oldRow.UnitCost;
newRow.CuryUnitCost = oldRow.CuryUnitCost;
newRow.LineAmt = oldRow.LineAmt;
newRow.CuryLineAmt = oldRow.CuryLineAmt;

newRow.ExtCost = oldRow.ExtCost;
newRow.CuryExtCost = oldRow.CuryExtCost;

newRow.DiscPct = oldRow.DiscPct;
newRow.DiscAmt = oldRow.DiscAmt;
newRow.CuryDiscAmt = oldRow.CuryDiscAmt;

newRow.DiscCost = oldRow.DiscCost;
newRow.CuryDiscCost = oldRow.CuryDiscCost;

newRow.RetainagePct = oldRow.RetainagePct;
newRow.RetainageAmt = oldRow.RetainageAmt;
newRow.CuryRetainageAmt = oldRow.CuryRetainageAmt;
}
}
}

InvokeBaseHandler?.Invoke(cache, e);
}

 


Reply