3

I am working with Contacts via REST API and I am trying to add an input field in my application for specifying the Source of the Contact. The problem is that the Source field is a combo box, which means that its values can be modified by Automation Steps (SM205000). For example, below is the list of the default values for the Source:

enter image description here

which corresponds to the CRMSourcesAttribute of that field

// Token: 0x020003D3 RID: 979
public class CRMSourcesAttribute : PXStringListAttribute
{
    // Token: 0x06004052 RID: 16466 RVA: 0x000FD4A4 File Offset: 0x000FB6A4
    public CRMSourcesAttribute() : base(new string[]
    {
        "W",
        "H",
        "R",
        "L",
        "O"
    }, new string[]
    {
        "Web",
        "Phone Inquiry",
        "Referral",
        "Purchased List",
        "Other"
    })
    {
    }

    // Token: 0x04002158 RID: 8536
    public const string _WEB = "W";

    // Token: 0x04002159 RID: 8537
    public const string _PHONE_INQ = "H";

    // Token: 0x0400215A RID: 8538
    public const string _REFERRAL = "R";

    // Token: 0x0400215B RID: 8539
    public const string _PURCHASED_LIST = "L";

    // Token: 0x0400215C RID: 8540
    public const string _OTHER = "O";
}

Should I go through the Automation Steps tables to get the final values of the combo-box or there is a way to get it by REST API specifying, for example, the DAC.FIELD?

Samvel Petrosov
  • 7,580
  • 2
  • 22
  • 46
  • I think this can be good feature request on feedback.acumatica.com – Yuriy Zaletskyy Aug 16 '19 at 19:46
  • Are you looking at all possible values, or possible values of a specific status? – KRichardson Aug 16 '19 at 19:50
  • 1
    @KRichardson I am looking for all the possible values of the Source lookup. I know that the additional values are stored in the AUCombo table and the "Active" checkbox is stored in the AUComboStep table. But I am looking for an optimal way to get that values because it will create delays on the external application side to request these tables every time. – Samvel Petrosov Aug 16 '19 at 19:54
  • @KRichardson At this moment I need all the values for "JustCreated" Step – Samvel Petrosov Aug 16 '19 at 19:55
  • 3
    If you were to get it / cache it locally, I would write a GI to the AUStepCombo table, specifying ScreenID/FieldName/TableName/StepID and returning the values listed back the the application – KRichardson Aug 16 '19 at 20:05
  • 1
    @KRichardson that is exactly the way I am thinking of how to get these values, but I want to see whether anybody has faced this problem and has a solution. – Samvel Petrosov Aug 16 '19 at 20:10
  • @samvelPetrosov have you seen the answer below? – Yuriy Zaletskyy Mar 02 '20 at 16:06
  • @YuriyZaletskyy Hi, yeah I saw you answer, but I want to check if it is returning the values added by automation steps or not and I can't find time for doing it. – Samvel Petrosov Mar 03 '20 at 04:19

1 Answers1

2

For tasks like these, I'd suggest to use reflection. Below goes example of reading Attributes with sample of usage:

    protected IEnumerable records()
    {
        //var row = new ClassFilter { ClassName = "PX.Objects.CR.CRMSourcesAttribute" };
        var row = Filter.Current;
        if (row != null && !string.IsNullOrWhiteSpace(row.ClassName))
        {
            var type = Type.GetType(row.ClassName) ??
                        Type.GetType(row.ClassName + ", PX.Objects");

            if (type != null)
                switch (type.BaseType.Name)
                {
                    case "PXIntListAttribute":
                        {
                            int[] values;
                            string[] labels;
                            GetRecords(type, out values, out labels);

                            for (int i = 0; i < values.Length; i++)
                                yield return new KeyValueRecord { Key = values[i].ToString(), UiValue = labels[i] };
                            break;
                        }
                    case "PXStringListAttribute":
                        {
                            string[] values, labels;
                            GetRecords(type, out values, out labels);

                            for (int i = 0; i < values.Length; i++)
                                yield return new KeyValueRecord { Key = values[i], UiValue = labels[i] };
                            break;
                        }
                }
        }
    }

    private void GetRecords<T>(Type type, out T[] values, out string[] labels)
    {
        var obj = Activator.CreateInstance(type);
        var flags = BindingFlags.NonPublic | BindingFlags.Instance;

        values = type.GetField("_AllowedValues", flags).GetValue(obj) as T[];
        labels = type.GetField("_AllowedLabels", flags).GetValue(obj) as string[];
    }

and picture:

enter image description here

After that you can just add graph and DAC to endpoint and expose it.

Full source code with comments is available here.

Yuriy Zaletskyy
  • 4,983
  • 5
  • 34
  • 54
  • 1
    I have just run the code and the problem with this method is that it isn't returning values added from the Automation Steps. In 20 R1 Acumatica Added a button showing all the possible values of the dropdown and that button is showing me more values than this method. – Samvel Petrosov Jun 06 '20 at 06:39