You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SOLine DAC定价初始化问题:FieldDefaulting事件下金额仍为0

SOLine_CuryUnitPrice字段默认值始终为0的问题排查与优化方案

问题描述

在Acumatica中尝试通过SOLine_CuryUnitPrice_FieldDefaulting事件初始化销售订单行的单价,但无论逻辑如何执行,金额始终保持为0,原实现代码如下:

protected void SOLine_CuryUnitPrice_FieldDefaulting(PXCache cache, PXFieldDefaultingEventArgs e)
{
  
  var row = (SOLine)e.Row;
  SOOrder order = (SOOrder) Base.Document.Current;
  BAccount un_compte=PXSelect<BAccount , Where<BAccount.bAccountID, Equal<Required<BAccount.bAccountID>>>>.Select(this.Base,row.CustomerID);
  if (row.InventoryID!=null)      
  {
     InventoryItem un_article=PXSelect<InventoryItem, Where<InventoryItem.inventoryID, Equal<Required<InventoryItem.inventoryID>>>>.Select(this.Base,row.InventoryID);
    
      string taxe=Convert.ToString(order.TaxCalcMode);
      if ((un_compte!=null) && (un_article!=null))
      {
          if ((un_compte.GetExtension<BAccountExt>().Usrcattarifaireclient=="cat1") && (taxe=="N"))
          {
            decimal? tmp=un_article.GetExtension<InventoryItemExt>().Usrprxht1;
            e.NewValue=tmp;
          }
          if ((un_compte.GetExtension<BAccountExt>().Usrcattarifaireclient=="cat1") && (taxe=="G"))
          {
            decimal? tmp=un_article.GetExtension<InventoryItemExt>().Usrprxttc1;
            e.NewValue=tmp;
          }
      }
  }
}

问题根源分析

  1. row.CustomerID为空导致逻辑中断:FieldDefaulting事件触发时,SOLine行的CustomerID可能还未从订单头同步,导致查询不到BAccount记录,后续赋值逻辑完全不执行。
  2. order为空引发的潜在异常与取值错误:直接转换order.TaxCalcMode时,若Base.Document.Current为空(比如订单头未保存),会抛出空引用异常;同时将枚举类型转为字符串对比,易因枚举值字符串变化导致匹配失败。
  3. 未覆盖全场景逻辑:当客户分类不是cat1或计税模式不是N/G时,未设置e.NewValue,系统会沿用默认值0。
  4. 直接查询数据库的效率与缓存问题:使用PXSelect.Select()直接查询数据库,未利用Acumatica缓存机制,既影响性能也可能获取到非最新数据。

修复后的代码实现

protected void SOLine_CuryUnitPrice_FieldDefaulting(PXCache cache, PXFieldDefaultingEventArgs e)
{
    var row = (SOLine)e.Row;
    if (row == null) return;

    // 优先从订单头获取客户ID,避免行字段未同步
    SOOrder order = Base.Document.Current;
    int? customerID = row.CustomerID ?? order?.CustomerID;
    if (customerID == null) return;

    // 从缓存获取BAccount,避免直接查库
    BAccount un_compte = PXSelect<BAccount, Where<BAccount.bAccountID, Equal<Required<BAccount.bAccountID>>>>.Select(Base, customerID);
    if (un_compte == null) return;

    if (row.InventoryID == null) return;
    // 从缓存获取InventoryItem
    InventoryItem un_article = PXSelect<InventoryItem, Where<InventoryItem.inventoryID, Equal<Required<InventoryItem.inventoryID>>>>.Select(Base, row.InventoryID);
    if (un_article == null) return;

    BAccountExt bAccountExt = un_compte.GetExtension<BAccountExt>();
    InventoryItemExt invItemExt = un_article.GetExtension<InventoryItemExt>();
    if (bAccountExt.Usrcattarifaireclient != "cat1")
    {
        // 非cat1客户的默认价格逻辑,可根据需求调整
        e.NewValue = invItemExt.Usrprxht1; // 示例:默认取不含税价
        return;
    }

    // 使用枚举类型对比,避免字符串转换错误
    if (order?.TaxCalcMode == SOOrderTaxCalcMode.Exclusive) // "N"对应枚举值Exclusive
    {
        e.NewValue = invItemExt.Usrprxht1;
    }
    else if (order?.TaxCalcMode == SOOrderTaxCalcMode.Inclusive) // "G"对应枚举值Inclusive
    {
        e.NewValue = invItemExt.Usrprxttc1;
    }
    else
    {
        // 其他计税模式的默认值,可根据需求设置
        e.NewValue = invItemExt.Usrprxht1;
    }
}

关键优化点说明

  • 优先从订单头取客户ID:解决SOLine行字段未同步导致的客户ID为空问题。
  • 使用枚举类型对比计税模式:避免字符串转换的潜在错误,提升代码健壮性。
  • 覆盖全场景逻辑:对非目标客户分类、其他计税模式设置明确的默认值,避免系统返回0。
  • 利用缓存查询数据:通过PXSelect.Select(Base, ...)从Acumatica缓存获取数据,提升性能并确保数据一致性。

进阶优化建议

如果需要更灵活的价格规则,建议使用Acumatica原生的**价格类别(Price Class)**功能,通过配置价格层级(客户、客户分类、库存等)实现自动化价格默认,无需编写硬编码逻辑,更符合系统架构且易于维护。

内容的提问来源于stack exchange,提问作者Xavier LARTEM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 19:35:22