Environment based Dynamics AX Color coding

Before I start: As a disclaimer, I’m posting this to show a potential way to solve this issue or similar issues, and to spark thought not necessarily as a production recommended solution.

I have had the requirement in the past to ensure that our environments (DEV, UAT and PROD) are reliably color coded to reflect the true environment that is currently open. This should not be application dependent (code only existing in individual environements) or database dependent (settings residing in the database) as these may change, be restored or be overwritten.

The best solution out there on how to physically color forms is Palle Agermarks’ solution. I would recommend you look at his code to get started as this is not the primary purpose of this post.

This solution however relies on a database table with the required color settings. This means that if a database is restored the color settings in UAT may reflect the color settings in Prod. For some purposes this may be ok or indeed what is needed, but we want to be able to clearly and confidently differentiate between our environments without having to remember restore scripts etc.

To do this I took Palle Agermarks‘ color coding code and modified it to look (in code) at what the current database is and color code my environment accordingly. Unfortunately this does require a bit of hard-coding a set of database names, but the colors will change correctly regardless of database or application loaded.

The key to this is to use SysSQLSystemInfo::construct().getLoginServer(); to determine the current database server you are connecting to.

 

Some variations on this, depending on your setup, would include looking for keywords in your server names instead of the whole name to determine what environement is being used. E.G. Does servername contain “DEV”. This may make it a bit more flexible and re-usable.

Creating a Custom Workflow Due Date Provider

Although not often needed within workflow, one sometimes has the requirement to set due dates, escalation dates etc based on some sort of custom criteria E.G Complete by My Birthday or Complete at least one day before the documents requested date. Recently on the Dynamics AX forum this question was raised (https://community.dynamics.com/ax/f/33/t/156937.aspx) so I thought I’d write up a “short” post on how to create a custom WorkflowDueDate provider.

1. Create a new class in the AOT that implements “WorkflowDueDateProvider” e.g. MyCustomDueDateProvider
public class MyCustomDueDateProvider implements WorkflowDueDateProvider
{
}

2. Create method getCalendarTokens

The getCalendarTokens method will return a list of items that will display in the Time Limit’s Calendar option in your workflow configuration.
D2
You can return any list of items here that you would like to allow the user to select for resolution. For example in the standard Calendar Due Date provider a list of all the configured calendars in the system. However you could customise this to return an entirely personal list of options such as “My Birthday” and “My Anniversary” that will set the workitem’s due date to my next birthday (26th of June 2015) or next anniversary (24 of March 2016). You could also provide an option that is document specific such as “1 Day Before Requested Date”. For this example I am going to use these options to illustrate the true arbitrary nature of the tokens.

public WorkflowCalendarTokenList getCalendarTokens()
{
    WorkflowCalendarTokenList tokens = WorkflowCalendarTokenList::construct();
    ;
    tokens.add(“MYBIRTHDAY”, “My Birthday”);
    tokens.add(“MYANNIVERSARY”, “My Anniversary”);
    tokens.add(“1DAYBEFOREREQ”, “1 Day Before Requested Date”);
    return tokens;
}

3. Create the resolve and resolveNonUser methods

After creating the tokens list we need to create a way to resolve the specific option that the user has selected in his configuration. I’ve kept my code very simple (and hardcoded) to illustrate how this works.

public WorkflowDateTime resolve(WorkflowContext _context, WorkflowCalendarToken calendarToken, WorkflowTimeSpanMinutes _timeSpanMinutes, WorkflowUser _userId)
{
    Date tmpDate;
    WorkflowDateTime ret;
    PurchReqTable req;
    ;
    if (!_calendarToken)
        throw error(“@SYS105450″);

    if (_calendarToken == “MYBIRTHDAY”)
    {
        tmpDate = str2DateDMY(“26062010″); //specific date
        ret = DateTimeUtil::newDateTime(tmpDate, 0);
        ret = MyCustomDueDateProvider::nextDate(ret);
    }
    else if (_calendarToken == “MYANNIVERSARY”)
    {
        tmpDate = str2DateDMY(“24032010″); //specific date
        ret = DateTimeUtil::newDateTime(tmpDate, 0);
        //next date is a custom method that simply finds the next occurance of my birthday by adding years to the provided date until it is greater than today.
        ret = MyCustomDueDateProvider::nextDate(ret);
    }
    else if (_calendarToken == “1DAYBEFOREREQ”)
    {
        if (_context.parmTableId() == tableNum(PurchReqTable))
        {
            //retrieve original document form WorkflowContext
            req = PurchReqTable::find(_context.parmRecId());
            ret = DateTimeUtil::newDateTime(req.RequiredDate,0);
            ret = DateTimeUtil::addDays(ret, -1);
        }
       else
        {
            throw error(“Cannot use 1DAYBEFOREREQ with any document except PurchReqTable”);
        }
    }

return ret;
}

For this example we are not going to use user specific resolution, so the resolveNonUser and resolve methods will return the same values

public WorkflowDateTime resolveNonUser(WorkflowContext _context,
WorkflowCalendarToken _calendarToken,
WorkflowTimeSpanMinutes _timeSpanMinutes)
{
return this.resolve(_context, _calendarToken, _timeSpanMinutes, ”);
}

4. Create new and construct methods

protected void new()
{
}

public static MyCustomDueDateProvider construct()
{
return new MyCustomDueDateProvider();
}

5. Create a due Date provider in the AOT.

1. Navigate to Workflow -> Providers -> Due Date Calculation
2. Right click, click “new Due Date Calculation Provider”
3. Right click on your new provider and click properties.
4. Provide an appropriate name e.g. “MyCustomDueDateProvider”
5. Provide a relevant label. This will appear in your workflow configuration under “Calendar Name”
D1
6. Depending on how you have coded your provider you may need to select an Association Type of company and AvailableForAllWorkflowTypes as “no” if you rely on company specific information or on record specific information.
7. Most importantly: Select the the class that you have created under “ProviderClass”

6. Perform CIL Compile and restart your client
7. Configure your workflow:
 Open your workflow configuration and navigate to the place where you would like to make use of your new functionality. E.G. Any Assignment’s “Time Limit” tabYou should now be able to select your provider under the “Calendar Name” option and select the resolution type under the “Calendar” option. Note our code didnt make use of the “_timespanInMinutes” parameter so the Duration option can be set to anything. We could have used this parameter to increase the flexibility on the “Before Requested Date” option if necessary.

I hope this assists someone sometime! Happy Daxing

Workflow Notifications to Custom list of Users

Problem statement: It is quite frequent in workflow in Dynamics AX that one would like to notify users when certain approvals have occurred, tasks have been completed or when errors occur. This is pretty easy to accomplish out of the box with Dynamics AX by using the notifications on approvals, tasks or on the workflow as a whole. However the options are pretty limited and not very dynamic (especially in AX 2009) and up until AX2012 you have only really been allowed to assign to specific users (i.e. by user id). This means that it is very difficult to accomplish complex notifications such as notify the following people when a document has been approved: Document Creator, Project Manager for the document’s project and all users assigned to the “Accountants” security role in AX.

AX 2012 however has now allowed you the ability to make use of “Participant Providers” as an assignment option in notifications.
participant

This means that you can create a Custom “notification” participant provider for your system that can resolve any number of personalised lists of users as above.

For example we created a particpant provider with a couple these lists. In our custom participant provider we returned a unique token per list e.g. “Originator, Project Manager, Requester and CEO” and “Originator, Project Manager, Financial Manager and CEO”.

In the resolve method of the participant provider we then retrieved the workflow document out of the workflow context object and returned the “Created by” user,  looked up the project on the document and returned the associated Project manager and finally looked up the Financial Manager and CEO from a custom parameters table in AX and returned them as well.

The actual creation of a custom participant provider is beyond the scope of this article but you can find some more resources over here:

https://workflowax.wordpress.com/2009/10/30/participant-provider-example/

I hope this sparks some thought and is useful to some:

Inspired by: https://community.dynamics.com/ax/f/33/t/155436.aspx