≡ Menu

Customization in New Dynamics Ax (Aka AX 7)- Part 6 Custom Workflow


Hi, every one, Let’s explore the custom workflows in new Dynamics Ax commonly known as AX 7.

This blog post is part of series.

In this post, I build a custom workflow based on table and form build in pervious posts.

Below links leads you to older posts.













As per Microsoft Documentation Custom workflow development is very similar to Dynamics Ax 2012.


Let’s do this in in following steps.

Custom Enum type.


We need Custom enum type for defining the States or status of Workflow. In Current Example I am using Al as naming convention for development.


Right click on Solution explorer and then add a new from ax artifacts. Name it AlDocumentWorkflowState.


When new AlDocumentWorkflowState enum is added in Solution explorer then double click on it to open it in designer mode. And then Add following Elements in it.

Add following elements in Enum



Now drag this enum to required table and it will create a new field other wise you have to create a new field in table and set extended data type / base enum. For current example I used the AlEarningCodeGroup table which I created in my previous post.




Table methods:

We need two methods in Table, first method is CanSubmitToWorkFlow.  This table help us to enable workflow based on specific condition, For example if table row has workflow state draft or not submitted, then workflow will processing will enable.



A new class is added in and update with logic, The condition on which Workflow enabled in class

public boolean canSubmitToWorkflow(str _workflowType = '')


boolean ret;

ret = super(_workflowType);

if (this.AlDocumentWorkflowState  == AlDocumentWorkflowState::NotSubmitted)


ret = boolean::true;




ret = boolean::false;


return ret;



Now add one more method in class We pass recId of current row and update its workflow state.

Public static void UpdateWorkFlow(RefRecId _RecId,AlDocumentWorkflowState _Status)


AlEarningCodeGroup _Group;

select forupdate * _Group where _Group.RecId == _RecId;


_Group.AlDocumentWorkflowState = _Status;






Custom Query:

Workflow uses the query to define the tables and fields that will be used by the workflow to define the data set available.

Again right click on solution explorer and add new Item and then select Query.

Now create a Query so we can build Document on that Query.




Name it AlEarningCodeGroupQuery .

Double click on Query and open it into Design mode and drag table in Data source. Save


Now right click on Table and press Now F4 or open property window and set dynamics Field


You find fields details.



Workflow Category:

A workflow category is used to determine the module in which the workflow will be available

Right click on project in solution explorer and add new Item.  From dialog window select workflow category.




Double click on workflow category created in previous step and open in designer view, press F4   to property window. set Module Property to HumanResource and Label to “AlEarningcodeGroupWFCategory” and save it.





Workflow type.

Now to go to Solution explorer and add new item and from new Item dialog select



Name it AlEarningGrpWFType. A wizard will start and there you have to select Query , Workflow category and the link from which required form will be open. We build all these three things in previous steps.


When Wizard finish, number of classes, Workflow type and classes will be generated and added in Visual studio, you can find them in solution explorer.




Update label of workflow type open them in designer window and set its label.


Similarly update labels of menu items to something good.



Similarly update the label of submit button.


Now expand the Submit Manager Class “AlEarnGrpWFTypeSubmitManager”  and update event handlers as follow.

/// <summary>

/// The AlEarnGrpWFTypeSubmitManager menu item action event handler.

/// </summary>

public class AlEarnGrpWFTypeSubmitManager


public static void main(Args _args)


AlEarningCodeGroup                           EarningCodeGroup;

AlEarnGrpWFTypeSubmitManager     submitManger;

recId _recId =                      _args.record().RecId;

WorkflowCorrelationId               _workflowCorrelationId;



workflowTypeName                    _workflowTypeName = workFlowTypeStr(“AlEarnGrpWFType”);

WorkflowComment                     note = “”;

WorkflowSubmitDialog                workflowSubmitDialog;

submitManger =                      new AlEarnGrpWFTypeSubmitManager();






//Opens the submit to workflow dialog.

workflowSubmitDialog = WorkflowSubmitDialog::construct(_args.caller().getActiveWorkflowConfiguration());




if (workflowSubmitDialog.parmIsClosedOK())


EarningCodeGroup = _args.record();

// Get comments from the submit to workflow dialog.

note = workflowSubmitDialog.parmWorkflowComment();






// Activate the workflow.

_workflowCorrelationId = Workflow::activateFromWorkflowType(_workflowTypeName, EarningCodeGroup.RecId, note, NoYes::No);



EarningCodeGroup.AlDocumentWorkflowState = AlDocumentWorkflowState::Submitted;





// Send an Infolog message.

info(“Submitted to workflow.”);


catch (Exception::Error)


error(“Error on workflow activation.”);










Now double click on event class “AlEarnGrpWFTypeEventHandler”  in solution explorer edit its events with table method call, We create this static method in one of above step.

/// <summary>

/// The AlEarnGrpWFTypeEventHandler workflow event handler.

/// </summary>

public class  AlEarnGrpWFTypeEventHandler implements WorkflowCanceledEventHandler,




public void started(WorkflowEventArgs _workflowEventArgs)





public void canceled(WorkflowEventArgs _workflowEventArgs)





public void completed(WorkflowEventArgs _workflowEventArgs)







Workflow Approval:



Add new item and select Workflow Approval like in previous steps



In wizard select Workflow document this will be generated by Workflow element step. Also select the field group from table on which we are building workflow. Also select form menu item which will open when user click on notification.









In Solution explorer new menu items and classes are added.




Now double click and open the approval class and update it as AlEarningGroupWFApprEventHandler

And update workflow dates

/// <summary>

/// The AlEarningGroupWFApprEventHandler workflow outcome event handler.

/// </summary>

public final class AlEarningGroupWFApprEventHandler implements WorkflowElementCanceledEventHandler,








public void started(WorkflowElementEventArgs _workflowElementEventArgs)





public void canceled(WorkflowElementEventArgs _workflowElementEventArgs)


AlEarningCodeGroup::UpdateWorkFlow(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), AlDocumentWorkflowState::PendingConcellation);



public void completed(WorkflowElementEventArgs _workflowElementEventArgs)


AlEarningCodeGroup::UpdateWorkFlow(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), AlDocumentWorkflowState::Approved);



public void denied(WorkflowElementEventArgs _workflowElementEventArgs)


AlEarningCodeGroup::UpdateWorkFlow(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), AlDocumentWorkflowState::Reject);



public void changeRequested(WorkflowElementEventArgs _workflowElementEventArgs)


AlEarningCodeGroup::UpdateWorkFlow(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), AlDocumentWorkflowState::ChangeRequest);



public void returned(WorkflowElementEventArgs _workflowElementEventArgs)


AlEarningCodeGroup::UpdateWorkFlow(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), AlDocumentWorkflowState::Returned);



public void created(WorkflowWorkItemsEventArgs _workflowWorkItemsEventArgs)


// TODO:  Write code to execute once work items are created.





Now double click on workflow type and open in designer





Update it workflow approval with name


Form Properties to enable Workflow.


Now expand the form, double click on designer and set following properties.


Workflow data source, enable for workflow and workflow Type.


Now save Compile And Run with Ctrl F5 to run without debugging to open Dynamics Ax web client



Now we have to configure workflow.

We set workflow category is Human Resource Management, and you will find Human resource workflows



Create a new workflow and select the workflow type we created in above step.



Enter credentials.




From designer window select and configure workflow.



Save and activate.


Now when you open the client in browser. You will find workflow menu item you can run the workflow from here.





While building Dynamics Ax 7 simple list page, I got following error on compiling.


Severity                Code      Description         Project  File         Line

Error                     Path: [AxForm/AXEarningCodeGroup/Design/Controls/Filtergrp]:Control ‘AxForm/AXEarningCodeGroup/Design/Controls/Filtergrp’ is missing child ‘Quick Filter’ required by pattern ‘Custom and Quick Filters’.   CustomPayroll (USR) [CustomPayroll] C:\AOSService\PackagesLocalDirectory\ApplicationSuite\CustomPayroll1\AxForm\AXEarningCodeGroup.xml               0


In short

Design/Controls/Filtergrp’ is missing child ‘Quick Filter


Something different then Dynamics Ax 2012. Yes, just right click on add a group and the add Quick Filter.





No other property I found, After solution compiled without any error.


Just open then dynamics learning portal, two new menus or classification found on top menu.

Dynamics 365 enterprise and Dynamics 365 Business.


I found that Microsoft just upload 6 new courses for Dynamics Enterprise on Dynamics Learning Portal.


If you have time and passion and more importantly Dynamics Learning Portal access credentials, you must enjoy the 365 degree change in World of ERP.


List of courses are as below.

80731AE: Architecture of Microsoft Dynamics 365 for Operations

80777AE: Monitoring and Diagnostic Tools in Microsoft Dynamics 365 for Operations

80794AE: Deploying and Servicing Environments in Microsoft Dynamics 365 for Operations by using LCS

80773AE: System Administration in Microsoft Dynamics 365 for Operations

80774AE: Managing Users and Security in Microsoft Dynamics 365 for Operations

80795AE: Managing Users and Security in Microsoft Dynamics 365 for Operations





I created a video and posted on Channel 9 . It is my native language. There is sound quality problem, But I made it. This is my second video on Channel 9.




We conduct an information sharing session on New Dynamics Ax 7 at Microsoft Innovation Center Lahore on 7 October 2016.

In this session, two speakers invited by Meetup group. Hasan Bukhari from Maison Consultancy (It is leading Microsoft Dynamics AX Implementer in Pakistan and Middle east). Second speaker was Me.

As professionally I am technical consultant (Currently working as freelancer). I cover the technical side of Dynamics Ax.  While Mr. Hasan Bukhari covered the Functional expects of The Product. Usman Ur Rehman Ahmed helped us to organize this meetup. Here are some picture taken during the session.
























For Future reference, I used following Queries to check the General Ledger Entry in Dynamics ax 2012. Small tip,

You can used them to delete posted ledger entry


select * from LEDGERJOURNALTABLE where JOURNALNUM =’XYZ-015528′


select * from LEDGERJOURNALTRANS where JOURNALNUM =’XyZ-015528′


select * from LedgerEntryJournal   where JOURNALNUMBER =’XyZ-015528′

select recid,* from GeneralJournalEntry where  LedgerEntryJournal= LedgerEntryJournal.RecID


select * from GeneralJournalAccountEntry where GeneralJournalEntry = GeneralJournalEntry.RecID




This post is series. In Last post we create some custom tables for  in Dynamics Ax.

Customization in New Dynamics AX (AK 7) Part 4- Custom Tables

In basic level we create two tables EarningCodeGroup and Earning Code. In this post we build simplest and very basic level forms.


Open the project and add a new Item and select Form  from “Add New Item “ Dialog and set its Name “AlEarningCodeGroup”



New form will be created in solution explore. Double click on it and open it in design mode.




Now right click on right side and select form Pattern.

Apply Pattern

From pattern select Simple list pattern.

You can read more details about simple list in the following



Patterns are applied but it described the following controls are missing.

Missing Controll




Now again right click on designer on and add action pane, custom filter group and grid.

Add new control


In first step I add the Action tab, then Add Action tab Pane page and then Button group and then add three command button.



Now update the different properties of Action Pane, tab strip and command button.

Change default to strip

Strip stryle

Set Caption as Home

Now select first command button set its text as New and command button as New.

Command Button Properties

Similarly set other two command button as Edit, and delete.

Now again right click on design and also add  group and rename it to grpFilter

Also right click on custom filter group and apply pattern We will see this in next post.



Now add Grid so form pattern requirement will be complete. Rename It to grpEarningCodeGroup. After that form design look like

Validated FormPattern


Now we go back to add table as a data source. We created the AxEarningCodeGroup in previous post, we will use that table here.

Grid data source





Set Name it with your table name, select table and set insertIfEmpty property to no.


Now go back and expand action pane => Pane and then button group  and update datasouce property to table  property to  AlEarningCodeGroup

Button Group DataSource property




Now right click on grid and press F4 or open property window and set datasource to AxEarnigCodeGroup and datagroup to grid (I created the field group with Name “Grid” In previous post”.

Grid dDaou


If you see, you find two fields are added under grid node


Grid fields




Now go back to solution explorer and create a new menu Item of type display


Name It as “AlEarningCodeGroupMenu” . New menu Item will be added on solution explorer. Double click on it to open it in design mode and Set Object Type to form and Object to AlFormEarningCodeGroup. Also Update its label Property to “Earning code Group”.



Open the AlEarningCodeGroup table in designer window and set its form ref to AlFormEarningCodeGroupMenu This will help us to add earning code group in earning code entry form.

Table Propeperties



Now we add the menu Item in  Menu to run and display,  For this open the menu Item in designer mode and drag menu item created in above step. In this post I am using custom Menu, If you are working with out of box menu then you must create menu extension then drag the menu Item in it.

Menu Display


Now run the application with Ctrl F5, I found the earning Code group in menu.

Live menu


By Clicking on link, forms open and I did following entries.


Data Entry







Suppose we are writing a custom module for Payroll. According to requirement, we have to create a custom table for Earning code. As well as Earning group.


At minimum we required following fields

Earn  Code Group Table

Earning Group of length 20.

Earning Group description length 60


Earning Code Table

Earning Code possible length 20.

Earning Code Description length 60.

Variable of fixed, If Variable the base value will be used as base percentage of Basic Salary, If fixed then base value will used as fixed amount.

Amount, The base value described as previous step.

And reference of Earning Code Group.


Lest explore some Extended data Type and enum and we create them with.


Extended Data Type:

For Extended Data Type is some kind of reusable data type based in primitive data type with some extra properties.

For example In Dynamics AX there is out of box extended Data type with “AmountCur”. It is Real based data Type. This extended Data Type usually used in amount related fields. So one of the many benefit of Extended data type is that we can change one place and it reflect where ever it used. For example, some organization want two decimal point while some required 4 decimal point. So if update decimal point at extended data type it update all fields where In our case we need to extended data Type, one for Earning code and one for Earning Group code,  For description fields we used the Out of the box field.

Now we have to create two extended data type .




Currently I am creating objects with AL extension. So I added a extended Data type of EDT String type and name it ALEarngingCode.  Clicking on Add. A new Extended will be added in Visual studio project. Double click on it and It will open in Designer window. Right click on it and open property window and set its size properties and 20.


Similarly, you can create ALEarningGroupCode







Similar there is enum is basically name of literal for example if we have Week days and enum then Sunday , Monday…. Saturday are literals.  In our current example we need Earning type as Fixed or Variable.


Double click on it and describe its detail on designer window


Add new Element


Double click and update Name and label.

Add name and label

Similarly add one more element




Now we have to add new tables.



Now we explore some important properties of Tables in

Table types.  We can define regular table in database or required temporary table. Temporary table stay in memory until its related object stay in memory. There are two type of Temporary tables.

In memory or Temp db, In memory are usually used in report. Temp db type are used when larger data and larger processes are instantiated.

In current example we use the regular tables.








Now add new tables First we create ALEarningGroup and then AlEarningCodes.

Add new item in visual studio and select table from add new Item dialog.

New Table


Set table name as as AlEarningCodeGroup, right click on table object in designer window solution explorer and open set table type as regular.






Now add two fields  with EarningCode and Description of string type
















Now expand field group and add new group Named to Grid and drag both fields into it








Similarly create another table for EarningCode


Add two fields AlEarningCode and fields EarningCode and description.


Now add one more field with type Enum


Set its name EarningcodeType  and set its enum Type to AlEarningCodetype, We created this enum type in previous steps.




Now add one more field with real type and set its







similarly create a Field group name Grid and drag all fields there.



Add one more string type for EarningCodeGroup we will map this field with Earning Code table for primary and foreign key relationship.


Indexes – are a way to speed up retrieval of data from a table


There are three types of Index in New Dynamics Ax.

A primary Index. This will provide the unique key to each record.  And field used in primary index used as primary or alternative key for table.

Second one is Clustered and not Clustered which are not scope of this post, we will discuss them in later post.

A clustered index organizes the data in the table in the order of the index.

Non-Clustered index is some kind of reference stored somewhere else to pointed to data. Example of the book index, placed at the end of book, reference of sorted title with page number.

Now we create Index in AlEarningCodeGroup table and then AlEarningCode


Update the following properties to    Alternate Key Yes, Allow Duplicates to now and set its name as idxEarnGode p



Now drag EarningCodeGroup Under index.



Now open table properties and add following  update Primary Index  to IdxEarningGrpCode and also select


Similar create index in ALEarningCodes




Table Relationship

There are two types of relationship in new Dynamics ax.

The first relationship type is called a normal relationship.  A normal relation is used to specify a relation without any conditions.

Another type of relation is called a foreign key relation.  This is used to specify a correspondence between a foreign key field in the present table to the primary key field in another parent table.  Foreign key relations are usually set on a child table.

In our current Scenario, we want to we want EarningGroup code as reference in EarningCode table. For this we expand relationship node of AlEarningCode and add new Relation based on Primary key relation


Updates relation Name and also select related table



Save it again right click and Select Normal relation




Click on Related Field fixed.


Now from selected screen select both related fields.

Save It compile, so Tables will be synchronizing to database.


In next post we will build simple data entry forms on these two tables.




I used following code snippet to get financial dimension attached with hcmposition


static void GetFinancialDimensionValue1(Args _args)


HcmPosition  position;

HcmPositionDefaultDimension  positionDefaultDimention;

DimensionAttributeValueSetStorage dimStorage;

Counter i;

select * from position

join * from positionDefaultDimention


where position.PositionId=="000001"

&& position.RecId == positionDefaultDimention.Position;




dimStorage = DimensionAttributeValueSetStorage::find(positionDefaultDimention.DefaultDimension);


for (i=1 ; i<= dimStorage.elements() ; i++)



info(strFmt("%1 = %2", DimensionAttribute::find(dimStorage.getAttributeByIndex(i)).Name,







Reference:  https://jkmsdax2012.wordpress.com/2015/11/16/how-to-get-financial-dimensions-for-a-particular-customer-using-x-code-in-ax-2012/


today I got this error while running a custom report.

Cannot edit a record in  Table

An update conflict occurred due to another user process deleting the record or changing one or more fields in the record.



I found that this error occurs due to concurrent access to table is allowed. And we did not need concurrent access.

I change the ccEnabled to no




If this error occur on table that can be used on concurrent mode, then write tableBuffer.reread() before adding or modify data.



Reference: https://community.dynamics.com/ax/f/33/t/95177