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

如何在销售订单界面CustomerID选择器中显示客户代码-名称-类别

解决Acumatica销售订单CustomerID选择器显示「客户代码-客户名称-客户类别」无效果问题

问题背景

需求是在销售订单(Sales Order)界面的CustomerID选择器中,实现选择时显示「客户代码-客户名称-客户类别」,并将客户类别追加到选择器搜索描述末尾,使描述字段包含这三个元素。但自定义Field Selecting事件处理代码执行后界面无变化。

原始属性代码

[PXDefault]
[Customer(
typeof(Search<BAccountR.bAccountID, Where<True, Equal<True>>>), // TODO: remove fake Where after AC-101187
Visibility = PXUIVisibility.SelectorVisible,
DescriptionField = typeof(Customer.acctName),
Filterable = true)]
[CustomerOrOrganizationInNoUpdateDocRestrictor]
[PXRestrictor(typeof(Where<Optional<SOOrder.isTransferOrder>, Equal<True>,
Or<Customer.status, IsNull,
Or<Customer.status, Equal<CustomerStatus.active>,
Or<Customer.status, Equal<CustomerStatus.oneTime>,
Or<Customer.status, Equal<CustomerStatus.creditHold>>>>>>>>),
AR.Messages.CustomerIsInStatus,
typeof(Customer.status))]
[PXForeignReference(typeof(Field<SOOrder.customerID>.IsRelatedTo<BAccount.bAccountID>))]

自定义事件代码

// Custom field selecting to show concatenated description
protected virtual void _(Events.FieldSelecting<SOOrder, SOOrder.customerID> e)
{
    if (e.Row?.CustomerID == null) return;

    Customer customer = PXSelect<Customer,
        Where<Customer.bAccountID, Equal<Required<Customer.bAccountID>>>>
        .Select(Base, e.Row.CustomerID);

    BAccount account = PXSelect<BAccount,
        Where<BAccount.bAccountID, Equal<Required<BAccount.bAccountID>>>>
        .Select(Base, e.Row.CustomerID);

    if (customer != null && account != null)
    {
        string fullDescription = $"{account.AcctCD} - {account.AcctName}";
        if (!string.IsNullOrEmpty(customer.CustomerClassID))
            fullDescription += $" - {customer.CustomerClassID}";

        e.ReturnState = PXFieldState.CreateInstance(e.ReturnState, typeof(string), 
            false, false, null, null, null, null, null, null, 
            fullDescription, null, PXErrorLevel.Undefined, null, null, null, 
            PXUIVisibility.Undefined, null, null, null);
    }
}

问题原因分析

  • 原事件仅处理已选择后字段的显示,未修改选择器下拉列表的显示逻辑,下拉列表仍沿用Customer属性默认的描述字段(AcctName)
  • 单独查询Customer和BAccount会产生额外数据库请求,且未关联获取数据,存在性能损耗及数据不一致风险
  • ReturnState参数设置不完整,未正确覆盖选择器的显示文本与描述规则

解决方案

方案一:修改Customer属性+优化FieldSelecting事件

修改Customer属性的查询逻辑,关联Customer表获取类别字段,同时指定选择器显示字段;再优化事件代码统一处理已选值和选择器描述:

修改后的属性代码

[PXDefault]
[Customer(
    typeof(Search<BAccountR.bAccountID, 
        LeftJoin<Customer, On<Customer.bAccountID, Equal<BAccountR.bAccountID>>>,
        Where<True, Equal<True>>>), // 保留原Where条件
    Visibility = PXUIVisibility.SelectorVisible,
    // 指定选择器下拉显示的字段:客户代码、客户名称、客户类别
    DisplayFields = new[] { typeof(BAccountR.acctCD), typeof(BAccountR.acctName), typeof(Customer.customerClassID) },
    DescriptionField = typeof(BAccountR.acctCD),
    Filterable = true)]
// 保留原有限制属性
[CustomerOrOrganizationInNoUpdateDocRestrictor]
[PXRestrictor(typeof(Where<Optional<SOOrder.isTransferOrder>, Equal<True>,
Or<Customer.status, IsNull,
Or<Customer.status, Equal<CustomerStatus.active>,
Or<Customer.status, Equal<CustomerStatus.oneTime>,
Or<Customer.status, Equal<CustomerStatus.creditHold>>>>>>>>),
AR.Messages.CustomerIsInStatus,
typeof(Customer.status))]
[PXForeignReference(typeof(Field<SOOrder.customerID>.IsRelatedTo<BAccount.bAccountID>))]

优化后的FieldSelecting事件

protected virtual void _(Events.FieldSelecting<SOOrder, SOOrder.customerID> e)
{
    if (e.Row == null || e.Row.CustomerID == null)
        return;

    // 关联查询一次性获取所有需要的数据,避免多次数据库请求
    var result = PXSelectJoin<BAccountR,
        LeftJoin<Customer, On<Customer.bAccountID, Equal<BAccountR.bAccountID>>>,
        Where<BAccountR.bAccountID, Equal<Required<BAccountR.bAccountID>>>>
        .Select(Base, e.Row.CustomerID);

    if (result == null)
        return;

    BAccountR account = result.GetItem<BAccountR>();
    Customer customer = result.GetItem<Customer>();

    string fullDescription = $"{account.AcctCD} - {account.AcctName}";
    if (customer != null && !string.IsNullOrEmpty(customer.CustomerClassID))
    {
        fullDescription += $" - {customer.CustomerClassID}";
    }

    // 正确覆盖显示文本与描述
    var state = (PXStringState)e.ReturnState;
    if (state != null)
    {
        state.DisplayText = fullDescription;
        e.ReturnState = state;
    }
}

方案二:使用PXSelectorAttribute自定义选择器(更灵活)

如果Customer属性的默认限制较多,可直接用PXSelectorAttribute完全自定义选择器逻辑:

[PXDefault]
[PXSelector(
    typeof(Search<BAccountR.bAccountID, 
        LeftJoin<Customer, On<Customer.bAccountID, Equal<BAccountR.bAccountID>>>,
        Where<Optional<SOOrder.isTransferOrder>, Equal<True>,
            Or<Customer.status, IsNull,
            Or<Customer.status, Equal<CustomerStatus.active>,
            Or<Customer.status, Equal<CustomerStatus.oneTime>,
            Or<Customer.status, Equal<CustomerStatus.creditHold>>>>>>>>),
    // 下拉列表显示字段顺序
    new[] { typeof(BAccountR.acctCD), typeof(BAccountR.acctName), typeof(Customer.customerClassID) },
    // 拼接显示文本的字段
    typeof(BAccountR.acctCD), typeof(BAccountR.acctName), typeof(Customer.customerClassID),
    DescriptionField = typeof(BAccountR.acctCD),
    Filterable = true,
    Visibility = PXUIVisibility.SelectorVisible)]
[CustomerOrOrganizationInNoUpdateDocRestrictor]
[PXForeignReference(typeof(Field<SOOrder.customerID>.IsRelatedTo<BAccount.bAccountID>))]

同时保留方案一中优化后的FieldSelecting事件,确保已选值显示正确。

关键说明

  1. 选择器下拉显示:必须通过DisplayFields指定要显示的字段,或在PXSelector构造函数中传入多个字段实现自动拼接
  2. 已选值显示:通过FieldSelecting事件修改ReturnState的DisplayText,确保字段显示自定义拼接文本
  3. 性能优化:使用关联查询(PXSelectJoin)一次性获取所有所需数据,避免多次数据库请求

内容的提问来源于stack exchange,提问作者Tharidhi P

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 22:24:53