Reputation: 23
I have a modification in the sales order needs to update the sales order line unit price with a derived value. This is working well and the new unit price shows up after the item has been selected and my code in the SOLine_RowUpdating event has executed. However after the quantity is selected the SOLine_RowUpdating executes again and after that the system calculates discounts like it normally would. Since I have my own price that should not be discounted I'd like to over-ride or cancel this standard discount calculation and just leave my price as is. Here is the SOLine_RowUpdating code and this is working well.
protected virtual void SOLine_RowUpdating(PXCache sender, PXRowUpdatingEventArgs e)
{
if (e.NewRow == null) {return; }
Customer customer = Base.customer.Current;
if (customer == null) return;
SOLine soLine = (SOLine)e.NewRow;
int BAAccountID = Convert.ToInt32(customer.BAccountID);
int lCompanyID = PX.Data.Update.PXInstanceHelper.CurrentCompany;
int lInventoryID = Convert.ToInt32(soLine.InventoryID);
LookupPriceAndDiscountDetails(BAAccountID, lCompanyID, lInventoryID); // My own code
sender.SetValueExt<SOLine.curyUnitPrice>(soLine, gdNewUnitPrice); //New price is in gdNewUnitPrice
Base.Transactions.Cache.RaiseRowUpdated(soLine, soLine);
Base.Transactions.View.RequestRefresh();
}
After lots of investigation I found this method suggested by various posts that is supposed to clear out / cancel discounts and in fact I can find it in the standard PX.Objects.SO.SOOrderEntry Row_Updated event but when I try it in my graph extension it does not update or clear out in that the soline (cache) values still show the discount numbers. I must be missing something simple.
Any ideas appreciated at this point...
protected void SOLine_RowUpdated(PXCache sender, PXRowUpdatedEventArgs e)
{
SOLine row = e.Row as SOLine;
DiscountEngine<SOLine>.ClearDiscount(sender,row);
// RecalculateDiscounts(sender, row); // ? (Maybe this)
}
Upvotes: 1
Views: 258
Reputation: 5613
To make it easier you could just turn off the call to RecalculateDiscounts using the following graph extension:
public class SOOrderEntryExtension : PXGraphExtension<SOOrderEntry>
{
[PXOverride]
public virtual void RecalculateDiscounts(PXCache sender, SOLine line, Action<PXCache, SOLine> del)
{
// if no discounts wanted, just return
// else call the base/standard Acumatica calc discounts on sales order...
if (del != null)
{
del(sender, line);
}
}
}
You can also write your own pricing logic by using a graph extension on ARSalesPriceMaint:
public class ARSalesPriceMaintExtension : PXGraphExtension<ARSalesPriceMaint>
{
[PXOverride]
public virtual decimal? CalculateSalesPriceInt(PXCache sender, string custPriceClass, int? customerID, int? inventoryID, int? siteID, CurrencyInfo currencyinfo, decimal? quantity, string UOM, DateTime date, bool alwaysFromBaseCurrency,
Func<PXCache, string, int?, int?, int?, CurrencyInfo, decimal?, string, DateTime, bool, decimal?> del)
{
//run your custom price logic here and return
// or return the base/standard Acumatica price logic...
return del?.Invoke(sender, custPriceClass, customerID, inventoryID, siteID, currencyinfo, quantity, UOM, date, alwaysFromBaseCurrency);
}
}
This way you do not need to fight the events, but override the calls the events are using to set Discounts and Price on the sales order. I also believe ARSalesPRiceMaint extension will override other screens using the pricing logic which helps to reduce duplicate code on different order entry screens.
Upvotes: 1
Reputation: 5151
You are on right track. Just few more comments. 1. Acumatica will always execute basic SOLine_RowUpdated event and then will execute your's SOLine_RowUpdated 2. If you want to control execution flow of SOLine_RowUpdated events, you can do something like this:
protected void SOLine_RowUpdated(PXCache cache, PXRowUpdatedEventArgs e, PXRowUpdated del)
{
//some code
//del or pointer to basic method can be called like this:
del(cache, e);
}
You'll have following options:
a. Don't call del at all ( I don't recommend you this approach because basic method has plenty of staff in it, not just discount calculation)
b. call del and then remove discount information
c. In case if your method ClearDiscount will not clear discount information, then it can be because it's tries to achieve it via simple assign, maybe you can try instead SetValueExt method.
One more point to keep in mind. By default Acumatica will call basic RowUpdated method and then it will call your method, so you don't need to use delegate. I'd recommend you to start from SetValueExt in your RowUpdated graph extension instead of simple assignment.
Upvotes: 1