acumatica - Acumatica - 两种方式将单价更新为毛利润百分比并返回
问题描述
无法设置单价更新毛利百分比并返回。
我已经成功地为销售订单行创建了一个新字段来显示毛利润百分比,但现在用户想要一种方法来调整百分比并更新单价。到目前为止,我所有的尝试显然都导致了无限循环。
添加到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;
}
}
}
}
这几乎可以工作。屏幕上没有任何反应,但保存时单价确实会更新并正确保存。快到了,我是否缺少某种更新步骤?
解决方案
这通常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 属性 (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 值:object dummy;
sender.RaiseFieldDefaulting<SOLine.unitPrice>(e.Row, out dummy);
推荐阅读
- android - Android中RecyclerView的Textview AutoSizing
- tableau-api - Tableau 动态地图标签
- c++ - 如何正确设置高电压触发抓取?
- javascript - 使用 AJAX 调用通过 PHP 显示 base64 图像数据
- html - 如何在 snipcart 的付款部分添加文本?
- javascript - Lodash 的 .map 不保证迭代顺序?
- html - 面临html中文本对齐的困难
- python - 如何为熊猫数据框绘制箱线图,日期为日/周/月?
- python - 为什么发生过拟合时随机森林最大深度参数的验证分数不会缩小
- wpf - 如何在后面的组合框代码中更改背景