无法设置单价来更新毛利百分比并返回。
我已经成功地为销售订单行创建了一个新字段,以显示毛利润百分比,但是现在用户想要一种调整百分比并更新单价的方法。到目前为止,我的所有尝试显然都导致了无限循环。
属性已添加到DAC的 [UnitPrice] 字段中:
[PXFormula(typeof(Switch<Case<Where<SOLineExt.usrGPPercent, Equal<decimal0>>, decimal0>, Mult<SOLineExt.usrGPPercent, SOLine.curyUnitCost>>))]
[UsrGPPercent] 字段属性:
[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] 字段属性:
[PXUIField(DisplayName = "GP %", Enabled = true)]
[PXFormula(typeof(Mult<SOLineExt.usrGPPercent, decimal100>))]
[PXDefault(TypeCode.Decimal, "0.0")]
以上所有方法均能完美运行,并按预期更新了GP%。
尝试#1 ,在[UsrGCP]中添加了以下属性(我意识到数学是不完整的,只是在此时尝试进行概念验证)。
[PXFormula(typeof(Switch<Case<Where<SOLine.curyLineAmt, Equal<decimal0>>, decimal0>, Div<SOLineExt.usrTotalProfit, SOLine.curyLineAmt>>))]
尝试#2 :FieldUpdated处理程序:
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);
}
}
}
这两种方法显然都导致了无限循环(猜测是由于触发了调试器并且必须重置IIS)。目标是在用户更新任一字段时仅更新一次,而忽略系统所做的更新。有什么想法吗?
根据HB_Acumatica的回复,我将上面的代码更新为:
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;
}
}
}
}
这几乎有效。屏幕上没有任何显示,但是保存后,单价确实会更新并正确保存。几乎在那里,我缺少某种更新步骤吗?
答案 0 :(得分:1)
通常在字段更新的事件处理程序中使用e.ExternalCall
进行了修复,以防止递归:
protected void SOLine_UsrGPPct_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e, PXFieldUpdated InvokeBaseHandler)
{
if (e.ExternalCall)
{
// Make sure it gets in here only once when value change in UI
}
}
ExternalCall Property (PXRowUpdatingEventArgs)
获取一个值,如果它等于true,则指示 DAC对象已从UI或通过Web服务启动 API
此外,另一种情况是两个字段属性相互依赖并且彼此需要计算它们的值。您不能让字段1的公式依赖于字段2,而字段1也具有引用字段2的公式。
通过这种设置,在询问字段1时,它将首先尝试评估字段1公式中的从属字段2,并且由于字段2也依赖于字段1,它将启动无限递归循环。
据我所知,这是没有办法的,您必须重新设计DAC字段,以使彼此之间不相互依赖。或者只是忽略DAC属性并在RowSelected事件中执行计算(这有一些缺点,因为它需要图形才能起作用)。
编辑:
关于UI中未更改的字段值。当某些字段的值更改时需要触发某些事件(通常是FieldUpdated事件)时,可能会发生这种情况。
与其分配不会引发任何事件的值,
row.Field = value;
您可以改用SetValueExt来引发诸如FieldUpdated之类的事件:
sender.SetValueExt<DAC.field>(row, value);
发件人必须是DAC类型的缓存,在您的情况下,应为否则:
Base.Caches[typeof(DAC)].SetValueExt<DAC.field>(row, value);
请注意,具有PXFormula属性的字段会在某个时候重新计算其值,因此您不应该手动设置此类字段的值。
如果在UnitPrice字段上仍具有此类属性,则不应手动更新字段值:
[PXFormula(typeof(Switch<Case<Where<SOLineExt.usrGPPercent, Equal<decimal0>>, decimal0>, Mult<SOLineExt.usrGPPercent, SOLine.curyUnitCost>>))]
也许您需要做的就是在UsrGPPercent更改时强制刷新公式。在这种情况下,请尝试使用RaiseFieldDefaulting
方法重新计算公式,而不是设置UnitPrice值:
对象虚拟对象;
sender.RaiseFieldDefaulting<SOLine.unitPrice>(e.Row, out dummy);
答案 1 :(得分:1)
非常感谢HB_ACUMATICA!
下面的最终代码将发布给尝试做类似事情的任何人。还清理了。
两个字段已添加到DAC(和SalesOrder屏幕):
UsrGPPercent
属性:
[PXDBDecimal()]
[PXUIField(DisplayName = "GP %", Enabled = true, Visible = true)]
[PXFormula(typeof(Mult<Switch<Case<Where<SOLine.curyExtCost, Equal<decimal0>>, decimal0>, Div<SOLineExt.usrTotalProfit, SOLine.curyExtCost>>, decimal100>))]
[PXDefault(TypeCode.Decimal, "0.0")]
代码扩展名:
#region Event Handlers
protected void SOLine_UsrGPPercent_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.UsrGPPercent > 0)
{
if (row.OrderType == "SO")
{
decimal NewUnitPrice;
decimal GPPercent = soLineExt.UsrGPPercent ?? 0;
decimal UnitCost = row.CuryUnitCost ?? 0;
decimal QtyOrdered = row.OrderQty ?? 0;
NewUnitPrice = (UnitCost + ((GPPercent / (decimal)100) * UnitCost));
soLineExt.UsrTotalProfit = (NewUnitPrice * QtyOrdered) - (UnitCost * QtyOrdered);
row.CuryUnitPrice = NewUnitPrice;
row.UnitPrice = NewUnitPrice;
}
}
}
}
#endregion
UsrTotalProfit
属性:
[PXDBCurrency(typeof(SOLine.curyInfoID), typeof(SOLineExt.usrTotalProfit))]
[PXUIField(DisplayName = "Total Profit", Enabled = false)]
[PXFormula(typeof(Sub<SOLine.curyLineAmt, SOLine.curyExtCost>))]
[PXDefault(TypeCode.Decimal, "0.0")]