Unable to setup unit price updating gross profit percent and back.
I have successfully created a new field for the sales order line to display gross profit percent, but now the user wants a way to adjust the percentage and update the unit price as well. All my attempts so far have apparently caused an infinite loop.
Attribute added to [UnitPrice] field in the DAC:
[PXFormula(typeof(Switch<Case<Where<SOLineExt.usrGPPercent, Equal<decimal0>>, decimal0>, Mult<SOLineExt.usrGPPercent, SOLine.curyUnitCost>>))]
[UsrGPPercent] field attributes:
[PXDBDecimal]
[PXUIField(DisplayName="GPPercent", Visible = false)]
[PXFormula(typeof(Switch<Case<Where<SOLine.curyLineAmt, Equal<decimal0>>, decimal0>, Div<SOLineExt.usrTotalProfit, SOLine.curyLineAmt>>))]
[PXDefault(TypeCode.Decimal, "0.0")]
[UsrGPPct] Field attributes:
[PXUIField(DisplayName = "GP %", Enabled = true)]
[PXFormula(typeof(Mult<SOLineExt.usrGPPercent, decimal100>))]
[PXDefault(TypeCode.Decimal, "0.0")]
The above all works perfectly and update the GP% as expected.
Attempt #1, added the following attribute to [UsrGCP] (I realize the math is incomplete, just trying to proof-of-concept at this point).
[PXFormula(typeof(Switch<Case<Where<SOLine.curyLineAmt, Equal<decimal0>>, decimal0>, Div<SOLineExt.usrTotalProfit, SOLine.curyLineAmt>>))]
Attempt #2: FieldUpdated handler:
protected void SOLine_UsrGPPct_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e, PXFieldUpdated InvokeBaseHandler)
{
if(InvokeBaseHandler != null)
InvokeBaseHandler(cache, e);
var row = (SOLine)e.Row;
PX.Objects.SO.SOLineExt soLineExt = PXCache<SOLine>.GetExtension<PX.Objects.SO.SOLineExt>(row);
if (row.OrderType == "SO")
{
if (soLineExt.UsrGPPct > 0)
{
row.CuryUnitPrice = row.CuryUnitCost + (soLineExt.UsrGPPct * row.CuryUnitCost);
}
}
}
Both methods apparently resulted in an infinite loop (guessing since the debugger was triggered and IIS had to be reset). The goal is to only update once when either field is updated by the user and ignore updates made by the system. Any ideas?
Based on HB_Acumatica's response I updated the code above to:
protected void SOLine_UsrGPPct_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e, PXFieldUpdated InvokeBaseHandler)
{
if(InvokeBaseHandler != null)
InvokeBaseHandler(cache, e);
var row = (SOLine)e.Row;
PX.Objects.SO.SOLineExt soLineExt = PXCache<SOLine>.GetExtension<PX.Objects.SO.SOLineExt>(row);
if (e.ExternalCall)
{
if (soLineExt.UsrGPPct > 0)
{
if (row.OrderType == "SO")
{
decimal NewUnitPrice;
decimal GPPercent = soLineExt.UsrGPPct ?? 0;
decimal UnitCost = row.CuryUnitCost ?? 0;
NewUnitPrice = UnitCost + ((GPPercent / (decimal)100) * UnitCost);
row.CuryUnitPrice = NewUnitPrice;
row.UnitPrice = NewUnitPrice;
}
}
}
}
This almost works. Nothing happens on the screen, but when saved the unit price does indeed update and save properly. Almost there, is there some sort of update step I'm missing?