Sales Price Updating Every Other Time

2020-05-07 06:17发布

问题:

I have extended the SOOrderEntry graph and added the following code in order to update another line on the same sales order that is related to the current line that is being updated:

protected virtual void SOLine_RowUpdating(PXCache cache, PXRowUpdatingEventArgs e)
{
    if (e.NewRow == null)
    {
        return;
    }

    SOLine soLine = (SOLine)e.NewRow;

    SOLine relatedLine = Base.Transactions.Search<SOLine.inventoryID> 
    (456);

    if (relatedLine != null)
    {
           relatedLine.Qty = soLine.Qty;
           relatedLine.CuryUnitPrice = 24.20;

           Base.Transactions.Update(relatedLine);
           Base.Transactions.View.RequestRefresh();
    }
}

When I try to test this by updating the Qty on the current line, the Unit Price on the related line only updates every other time that I update the Qty. The related item is a Non-stock item where the current item is a Stock Item.

I'm doing this in a Sales Demo environment on 18.102.0048

I tried this but, now the Extended Price is always 0.00:

protected virtual void SOLine_RowUpdating(PXCache cache, PXRowUpdatingEventArgs e)
{
    if (e.NewRow == null)
    {
        return;
    }

    SOLine soLine = (SOLine)e.NewRow;

    SOLine relatedLine = Base.Transactions.Search<SOLine.inventoryID> 
(456);

    if (relatedLine != null)
    {
       SOLine oldRelatedLine = PXCache<SOLine>.CreateCopy(relatedLine);
       relatedLine.Qty = soLine.Qty;
       relatedLine.CuryUnitPrice = 24.20;

       Base.Transactions.Cache.RaiseRowUpdated(relatedLine, oldRelatedLine);

       Base.Transactions.Update(relatedLine);
       Base.Transactions.View.RequestRefresh();
    }
}

回答1:

When a field calculated value depends on another field value it's sometimes required to trigger events for the value to be recalculated.

In some cases it only requires firing the event for the field that you modified. Assigning values using the C# assignment operator (=) or the SetValue method will not trigger the events handler, SetValueExt method will:

// Doesn't trigger events
relatedLine.Qty = soLine.Qty;
cache.SetValue<SOLine.qty>(relatedLine, soLine.Qty);

// This will trigger events
cache.SetValueExt<SOLine.qty>(relatedLine, soLine.Qty);

There are some cases where you need to fire events for the whole row too. You can use the RaiseXxxYyy methods to do that. I used Current in the example but you might have to adapt it if Current is not the row being modified:

SOLine oldRowCopy = PXCache<SOLine>.CreateCopy(Base.Transactions.Current);
Base.Transactions.Current.Qty = soLine.Qty;
Base.Transactions.Cache.RaiseRowUpdated(Base.Transactions.Current, oldRowCopy);

EDIT:

Looking at updated question, it might not make much of a difference but I suggest you switch the order of these 2 lines:

   Base.Transactions.Cache.RaiseRowUpdated(relatedLine, oldRelatedLine);
   Base.Transactions.Update(relatedLine);

Like this:

// You want the value in Cache to be updated
Base.Transactions.Update(relatedLine);

// After Cache value is set you want to raise the events
Base.Transactions.Cache.RaiseRowUpdated(relatedLine, oldRelatedLine);


回答2:

Thanks to HB_ACUMATICA, here's the code that resolved this:

protected virtual void SOLine_RowUpdating(PXCache cache, PXRowUpdatingEventArgs e)
{
    if (e.NewRow == null)
    {
        return;
    }

    SOLine soLine = (SOLine)e.NewRow;

    SOLine relatedLine = Base.Transactions.Search<SOLine.inventoryID>(456);

    if (relatedLine != null)
    {
       SOLine oldRelatedLine = PXCache<SOLine>.CreateCopy(relatedLine);
       relatedLine.Qty = soLine.Qty;
       relatedLine.CuryUnitPrice = 24.20;

       object outPrice = 0.01;
       outPrice = (relatedLine.CuryUnitPrice * relatedLine.Qty);
       cache.SetValueExt<SOLine.curyExtPrice>(relatedLine, outPrice);

       Base.Transactions.Cache.RaiseRowUpdated(relatedLine, oldRelatedLine);

       Base.Transactions.Update(relatedLine);

       Base.Transactions.View.RequestRefresh();
    }
}


标签: acumatica