Acumatica - 双向更新单位价格与毛利润百分比并返回

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (17)

无法设置单位价格更新毛利润百分比并返回。

我已成功为销售订单行创建了一个新字段以显示毛利百分比,但现在用户想要一种方法来调整百分比并更新单价。到目前为止,我的所有尝试都显然造成了无限循环。

添加到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,则表示已从UI或通过Web Service API启动DAC对象的更新

除此之外,另一种情况是当两个字段属性相互依赖并且需要彼此计算它们的值时。您不能让字段1具有依赖于字段2的公式以及还具有引用字段2的公式的字段1。

通过这种设置,当询问字段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);

扫码关注云+社区

领取腾讯云代金券