Search code examples
customizationselectoracumatica

How to add a custom field into the ARInvoice Customer selector?


There is a custom field, that I declared for the Customer DAC:

public class CustomerExt : PXCacheExtension<Customer>
{
    #region UsrDemoField
    [PXDBString(255)]
    [PXUIField(DisplayName = "Demo Field")]

    public virtual string UsrDemoField { get; set; }
    public abstract class usrDemoField : IBqlField { }
    #endregion
}

Attempts to modify the ARInvoice Customer selector with the Customize Selector Columns popup didn't seem to work. How can I add my custom field into the ARInvoice customer selector?

enter image description here


Solution

  • Be aware, since Acumatica ERP build #17.201.0043, it's possible to customize the list of columns defined for AR Invoices' Customer lookup via the Customize Selector Columns dialog (available in the Data Class section of the Customization Manager). For step-by-step instructions please check the screenshot below: enter image description here

    To modify AR Invoices' Customer lookup on Acumatica ERP ver. 6.1 and earlier, please follow the steps below: The definition of PXCustomizeSelectorColumns generated by the Customize Selector Columns popup brilliantly works with the majority of selectors inside Acumatica ERP. Basically, PXCustomizeSelectorColumns simply replaces originally defined columns for a selector with the custom set of columns during an initialization of PXCache:

    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method, AllowMultiple = false)]
    public class PXCustomizeSelectorColumns: PXEventSubscriberAttribute
    {
        private readonly Type[] _columns;
    
        public PXCustomizeSelectorColumns(params Type[] columns)
        {
            _columns = columns;
        }
    
        public override void CacheAttached(PXCache cache)
        {
            cache.SetAltered(this.FieldName, true);
            foreach (PXEventSubscriberAttribute attr in cache.GetAttributes(null, this.FieldName))
            {
                PXSelectorAttribute sel = attr as PXSelectorAttribute;
                if (sel == null) 
                    continue;
                sel.SetFieldList(_columns);
                sel.Headers = null;
            }
        }
    }
    

    So what can cause the PXCustomizeSelectorColumns attribute to fail and not replace selector's originally defined columns? Any time the SetColumns method is executed on an instance of PXDimensionSelectorAttribute or PXSelectorAttribute after PXCache was initialized, there is no chance for PXCustomizeSelectorColumns to do its job.

    [PXDBInt()]
    [PXUIField(DisplayName = "Customer", Visibility = PXUIVisibility.Visible)]
    [Serializable]
    public class CustomerAttribute : AcctSubAttribute
    {
        ...
        public virtual void FieldSelecting(PXCache sender, PXFieldSelectingEventArgs e)
        {
            if (this.AttributeLevel == PXAttributeLevel.Item || e.IsAltered)
            {
                PopulateFields(sender);
            }
    
            PXFieldSelecting handler = GetAttribute<PXDimensionSelectorAttribute>().FieldSelecting;
            handler(sender, e);
        }
    
        protected virtual void PopulateFields(PXCache sender)
        {
            if (_FieldList == null)
            {
                _FieldList = new string[this._fields.Length];
                _HeaderList = new string[this._fields.Length];
    
                for (int i = 0; i < this._fields.Length; i++)
                {
                    Type cacheType = BqlCommand.GetItemType(_fields[i]);
                    PXCache cache = sender.Graph.Caches[cacheType];
                    if (cacheType.IsAssignableFrom(typeof(BAccountR)) ||
                        _fields[i].Name == typeof(BAccountR.acctCD).Name ||
                        _fields[i].Name == typeof(BAccountR.acctName).Name)
                    {
                        _FieldList[i] = _fields[i].Name;
                    }
                    else
                    {
                        _FieldList[i] = cacheType.Name + "__" + _fields[i].Name;
                    }
                    _HeaderList[i] = PXUIFieldAttribute.GetDisplayName(cache, _fields[i].Name);
                }
            }
    
            var attr = GetAttribute<PXDimensionSelectorAttribute>().GetAttribute<PXSelectorAttribute>();
            attr.SetColumns(_FieldList, _HeaderList);
        }
        ...
    }
    

    With that said, to add a custom field into the ARInvoice Customer selector, one should replace all attributes declared for the ARInvoice.CustomerID field and redefine columns for the Customer selector within the CustomerActive attribute: enter image description here

    [PXDefault()]
    [CustomerActive(typeof(Search<BAccountR.bAccountID>),
        new Type[]
        {
            typeof(BAccountR.acctCD),
            typeof(BAccountR.acctName),
            typeof(CustomerExt.usrDemoField),
            typeof(Address.addressLine1),
            typeof(Address.addressLine2),
            typeof(Address.postalCode),
            typeof(CustomerAttribute.Contact.phone1),
            typeof(Address.city),
            typeof(Address.countryID),
            typeof(CustomerAttribute.Location.taxRegistrationID),
            typeof(Customer.curyID),
            typeof(CustomerAttribute.Contact.salutation),
            typeof(Customer.customerClassID),
            typeof(Customer.status)
        },
        Visibility = PXUIVisibility.SelectorVisible, DescriptionField = typeof(Customer.acctName), Filterable = true, TabOrder = 2)]
    

    After publishing the customization, custom Demo Field should finally appear in the ARInvoice Customer selector: enter image description here

    To enable searching against a custom field inside the ARInvoice Customer selector, open Invoices and Memos screen in the Layout Editor and type UsrDemoField as the GridProperties.FastFilterFields property of the Customer selector:

    enter image description here

    enter image description here