Infor CRM Getting Custom Entities Working with Activity Associations

A while ago I wrote briefly about the new activity and history association functionality that was new in Infor CRM 8.4.04. This ability allows you to allow any entity in the system to be associated with an Activity.

For instance, if you wanted to allow Competitors to be associated with the activities you can set the Can Associate Activity attribute of the entity to true.

Once this attribute is set and the client portal is deployed, you will be able to associate that entity to an activity:

When you pick that entity and click the Associate button it then opens the lookup to allow picking which record you want to associate. For custom entities it defaults to show the Description attribute of the entity.

This is where the problem comes in.

If you try to search on the one field that is exposed for the custom entity it breaks the lookup altogether. Notice how the data has now disappeared.

Looking at the browser console we can see there is an error from the sdata client side handler

IN the console we can see the slxdata handler is receiving a request to filter the custom entity feed, passing in a where condition such as this:

http://localhost:3333/SlxClient/slxdata.ashx/slx/dynamic/-/comptitors?_compact=true&select=Id,$descriptor&where=(upper($descriptor) like "D%")&startIndex=1&count=25&format=json&_t=1674054097831

You can see in the where condition it is attempting to search the $descriptor field. The problem is that is not a searchable field. On the server, an error is thrown to the event logs like this:

Could not resolve property: $descriptor of: Sage.SalesLogix.Entities.Competitor.

How we can fix this?

In order to do this, we need to extend the Activity Association widget and tell it how to construct the lookup for our “custom” entity. The lookup definitions for standard entities are defined within the same base widget. The base widget is found in the Sage/MainView/ActivityMgr/ActivityAssociationsWidget.js file. There is a function in there called _getLookupConfig which defines these (line 434). This is the function that needs to be extended.

Let’s look at how to extend this.

We will use our custom loader application to make loading our module extension easier. We just need to create a new main.js file and inside it we will utilize Dojo’s aspect function to add an after overload to the standard _getLookupConfig function. The shell of this call to add the overload would look like this:

require([
    'dojo/aspect',
    'Sage/MainView/ActivityMgr/ActivityAssociationsWidget'
], function (
    aspect,
    AssociationsWidget
) {
aspect.after(AssociationsWidget.prototype, '_getLookupConfig', function (method, args) { 
//our custom code is here returning the appropriate result
});
}); 

In this shell we are passing into our custom function the original method result “method”, as well as the original method’s arguments “args”. In the case of the original _getLookupConfig function it has a single argument passed in of “associationEntity”.

With “args” there could be multiple arguments so first we need to get the first (and only) one passed in. We can do this with:

args[0]

This will allow us to determine which entity is being passed in. This is the actual Entity name and is case sensitive. To set this up for future extensibility lets use a switch statement. We can then handle the case in our example that we are trying to associate a Competitor:

        switch (args[0]) {
            case 'Competitor':
                return createCompetitorLookupConfig();
            default:
                return method;
        }

With this code, if the passed in entity is “Competitor” we are going to return the result of a function called “createCompetitorLookupConfig”. We also are adding a default switch, so that if the entity passed in is not one of our “custom” ones then our override just returns the original method.

Now we need to create our custom function that generates our custom lookup definition. We have stated this function is going to be named “createCompetitorLookupConfig”. This function needs to create the lookup. Using the standard widget code as a sample we can create our new function like this:

    function createCompetitorLookupConfig () {
        return {
            id: 'lu_associationLookup',
            structure: [
                {
                    label: "Competitor",
                    field: "CompetitorName"
                }, {
                    label: "Rating",
                    field: "Rating"
                }, {
                    label: "Strategy",
                    field: "Strategy"
                }, {
                    label: "Contact",
                    field: "Contact"
                }
            ],
            gridOptions: {
                contextualCondition: '',
                contextualShow: '',
                selectionMode: 'Multi',
                columnResizing: true
            },
            storeOptions: {
                resourceKind: 'competitors',
                sort: [{
                    attribute: 'CompetitorName'
                }]
            },
            isModal: true,
            seedProperty: '',
            seedValue: '',
            overrideSeedValueOnSearch: false,
            initializeLookup: true,
            preFilters: [],
            returnPrimaryKey: true,
            dialogButtonText: "OK"
        };
    }

In our method, within the structure array, we need to define the fields to include in the lookup. Each field will then be available to filter n in the activity lookup. Each field needs a label (the column header) and the field attribute (the entity property name).

In the storeOptions object we need to define the sdata feed name, as well as defining the default sort property name.

Let’s take a look at the complete javascript code:

require([
    'dojo/aspect',
    'Sage/MainView/ActivityMgr/ActivityAssociationsWidget'
], function (
    aspect,
    AssociationsWidget
) {

    function createCompetitorLookupConfig() {
        return {
            id: 'lu_associationLookup',
            structure: [
                {
                    label: "Competitor",
                    field: "CompetitorName"
                }, {
                    label: "Rating",
                    field: "Rating"
                }, {
                    label: "Strategy",
                    field: "Strategy"
                }, {
                    label: "Contact",
                    field: "Contact"
                }
            ],
            gridOptions: {
                contextualCondition: '',
                contextualShow: '',
                selectionMode: 'Multi',
                columnResizing: true
            },
            storeOptions: {
                resourceKind: 'competitors',
                sort: [{
                    attribute: 'CompetitorName'
                }]
            },
            isModal: true,
            seedProperty: '',
            seedValue: '',
            overrideSeedValueOnSearch: false,
            initializeLookup: true,
            preFilters: [],
            returnPrimaryKey: true,
            dialogButtonText: "OK"
        };
    }


    aspect.after(AssociationsWidget.prototype, '_getLookupConfig', function (method, args) {
        switch (args[0]) {
            case 'Competitor':
                return createCompetitorLookupConfig();
            default:
                return method;
        }

    });

});

That is all there is to it. Now when we deploy our custom module script it will cause the activity’s associate lookup for Competitors to have our custom lookup definition.

Want content like this delivered to your inbox? Sign up for our newsletter!
ABOUT THE AUTHOR

Kris Halsrud

Kris Halsrud is a Senior Analyst / Developer for Customer FX Corporation.

Submit a Comment

Your email address will not be published. Required fields are marked *