Acumatica-通过两种方式将单价更新为毛利润百分比并返回

时间:2019-04-08 17:47:42

标签: 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;
        }
      }
  }
}

几乎有效。屏幕上没有任何显示,但是保存后,单价确实会更新并正确保存。几乎在那里,我缺少某种更新步骤吗?

2 个答案:

答案 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")]