Friday, November 21, 2014

AX2012: Troubleshooting "ERROR: Cannot find index PK_ModelSecurityPermissionCache_RECID"

Hi Friends,
Recently while importing model store in AX2012 CU4 environment, I got the below error:

To resolve this, run the axutil schema command.

After executing the axutil schema command, the model store import worked fine. If you are also facing such issue then worth trying this. It reinitializes the default model store.

More details regarding this can be found at the below MSDN link:

Friday, October 24, 2014

AX2012 : An hour of SSRS error [;]

Hi Friends,
Recently we faced this SSRS issue in one of the clients environment running AX2012 CU4. This issue has strange definition:
  • Comes whenever we restart AOS.
  • Automatically gets fixed after almost an hour after AOS restart.
  • Either of the below 2 errors used to come on running any SSRS report
  • SSRS error 1 - "Access denied. You do not have sufficient authorisation to modify data in database". 

  • SSRS error 2 - " Access denied to field Company (dataAreaId) in table". 

Initially it looked like a security issue but this error was coming with system administrator roles and all the security setup was verified to be correct.

The system was configured with 6 AOS'es. One AOS was a dedicated batch server and the remaining 5 AOS were part of AOS cluster.
The solution found was that the business connector configuration on the SSRS server was pointing to AOS which was a dedicated batch server. It needs to point to an AOS which is a part of AOS Cluster. 
We created a new business connector configuration on SSRS server and pointed it to an AOS which was part of AOS cluster and it solved the issue.

If you are facing similar scenario then make sure that the business connector is pointing to an AOS from cluster. In case you also make changes to an existing AOS cluster then take care of this point.

Thanks for reading the blog and keep sharing.

Monday, October 13, 2014

Generate code using editor scripts and be more productive

Hi Friends,
Time is one of the most important factor in today's world. We develop many customizations for customers to save there time by reducing the number of clicks and automating the business processes.

There are tools available to save some time for developers too, to enable us to focus on coding the main logic rather than writing the pre requisite code to implement the logic.

One of such powerful feature is provided by editor scripts in AX. The good thing is that these classes can be enhanced to create your own custom code scripts. It is much more powerful then a template because you can add the extra pinch of run time magic.

Partners leverage these classes worldwide and extend them for variety of purposes. One of the very common use is to insert code comments. This is not a new tool and there are many good online resources already available. My intention is to share how we can use it to avoid overhead of writing too much of code.

So let us take an example. If you have to write X++ code to use a query class object for salesTable and have to add range on a field, then at-least you need to write 13-14 lines of code as shown below

By enhancing the code script classes you can achieve this just by a click of button! To achieve this I created 2 new methods in the system. One in EditorScripts class and another in XppSource class. After modifications I can see a new "query" option in editor scripts as shown below:

On selecting this option, system prompts me to enter the table name and the field name on which I want to apply the range.

Once I click OK, the code is automatically created for me.

Once I get the base code, I can further modify this as I want to implement my logic.

Below are the functions I added:
1. New method in EditorScripts class.

2. New method in XppSource class

You can download the XPO of the above modification from here.

The main idea is to save time by creating your own custom editor scripts which can help you to quickly generate pre defined code blocks at run time, so that you only spend time in writing the main logic.
Benefits of using this is approach:
1. Saves time and be more productive.
2. Avoid any typo errors.
3. You no longer need to shift your focus from your core logic to find the code pattern.
4. It is more efficient than Copy/Paste as you don't have to change the variable names and update all occurrences of those variables.

Some of the other ideas where you can extend these classes are:
  • Create find(), exists(), findRecID() methods on your tables. Refer to this nice blog by Joris de Gruyter here.
  • Create lookup methods.
  • Inserting code comments - here
  • Writing SQL statements which are required on day to day basis. For example: you can build your template for select statements using different keywords like crossCompany, firstonly , exits joins. etc.
  • Declaring/initializing set,lists, maps and there enumerators.
  • Create data contracts methods.
  • Declare Macros, Current versions, Current lists in class declaration.
  • Creating display methods - Refer to this nice blog by Micheal Brown here
If you are using these classes for any other purposes, please do leave your comment and share your bright ideas. 

Friday, September 19, 2014

Active project contracts in Microsoft Dynamics AX 2012 R3

Hi Friends,
In Microsoft Dynamics AX, project contracts are created to setup the funding sources, define funding limits on the funding sources, maintain uniform invoicing procedures and also for invoicing one or multiple projects at a same time. These can be found at Project management and accounting > Common > Projects > Project contracts.

In AX2012 R3, on the project contracts list page, you will find filter to show the contracts which are "Active". This filter is not available in previous versions of AX and caught my attention when I opened this list page in R3 environment.

Eager to know what is an active project contract, I jumped into the technical artefacts of this list page and found that active project contracts are those which are defined on a project whose status is not completed. So after creating a project contract we do not need to set it as active. There is no field in project contracts table which stores this value. It is considered active as soon as it is defined on any 'not completed' project. 

Note: This filter is not available on EP. It is only shown on the AX client.

The way standard AX does this filtering is interesting and different from the traditional way of creating such filters. This prompted me to write the post :).

1. The display target property of the filter group is defined as client. As a result, this feature is only available on AX client. Also, we can override method on the controls inside this group. 

2. If the value on the 'show contract' control is selected as "Active", then the datasource "ProjTable" of the query object is enabled. 

3. Nothing special till now. Let's look at the query used on the list page. Note that the "ProjTable" is not defined as a datasource on this query.

4. So now things become interesting! When is the data source "ProjTable" added in the query? To find this, let's check out the interaction class used in the list page. Interaction class name can be checked from the property of the list page: 

Look at the initializeQuery() method of the interaction class, you will find the below piece of code which is doing the little magic and making the whole thing interesting to share: 

  1. "ProjTable" data-source is added in the query as a datasource.
  2. Using sysDictRelation classes, the relation is defined between data-sources of projTable &  ProjInvoiceTable.
  3. The join mode is set as "Exists Join". 
  4. The range is defined on ProjTable status field as "Not Completed".  Note the queryNotValue function used in defining the range.
  5. The data-source is enabled/disabled on the 'show contract' filter control value.
The above code is a good example to understand how we can add relations and use exists join in query data sources. This approach is also helpful if we need to do a similar customization.

To read more about project contracts refer to the technet link Project contracts

Thanks for reading the blog. 

Wednesday, August 27, 2014

AX2012 SSRS Error "You do not have sufficient authorisation to modify data in database"

Hi Friends,
Recently we got this error on running a SSRS report. For every report we were getting similar error. I was a system administrator so I was sure it should not be a permission issue but the error message was pointing towards permission and security settings. 

I also tried generating full CIL, restarting AOS, restarting SSRS , deleting *.auc files, cleared usage data but still got the same error.

I found technet article on similar error message here and verified that no such properties were changed in our system.

Then we gave a try by rebooting the machine hosting AOS and guess what the reports started working. 

So just rebooting the server helped us in this situation however the error message was pointing towards permission issue. In case you also face similar issue then please try this and also share any other resolutions to this error message which you find.


Tuesday, August 26, 2014

AX2012: SSRS error "Item with the same key has already been added"

Hi Friends,
Recently we faced the below error when running a SSRS report on AX2012 Feature pack CU4 environment:

This was LIVE environment with lots of users logged in, so we wanted to avoid any downtime, and the following helped us to fix this issue without any downtime:
1. Clear *.auc files
2. Restart SSRS server
3. Redeploy the report

There is a blog from MS support team on the same topic here which suggest that only redeployment of the report can fix this issue but in our case we were also required to restart SSRS services.


Friday, July 25, 2014

AX 2012: Merge ledger and financial dimensions using X++ code

Hi Friends,
In this post let us see how to use out of the box available X++ API which can be used to merge ledger and financial dimensions.  The below code works well with AX2012/ AX2012 R2/ AX2012 R3 versions of Microsoft Dynamics AX. This is useful in scenarios when we need to create journal from code and need to merge the dimensions in order to get the correct offset account values.

So to keep it simple, let consider the below scenario:
Customer "2014" in the system is having the below financial dimensions defined on it:

Now let's create a standard AX general journal and on it's journal line, let's select account type as customer, account as customer account "2014" , offset account as Ledger  and then from lookup select ledger account "110101", as shown below:

As soon as you select the ledger account, you will notice that system merges the ledger dimension and the financial dimension and create the complete offset account dimension value with the display value as shown below:

To do this from code, use API serviceCreateLedgerDimension() available DimensionDefaultingService class, it is advisable to merge the dimensions whenever you create journal from X++ code, to make sure the resulting voucher entries are against correct and complete accounts.

static void Job1(Args _args)
    RecId   customerDefaultDimension = CustTable::find("2014").DefaultDimension;
    RecId   ledgerDimension = AxdDimensionUtil::getMultiTypeAccountId(enumNum(LedgerJournalACType),LedgerJournalACType::Ledger,[110101,110101]);


Line 1 --> gets the RecID which relates to the financial dimension defined on the customer.

Line 2 --> Get the RecID which related to the ledger account 110101.

Line 3 --> Is actually combining the logic to convert the recID into the display value and also to merge the dimensions.

DimensionDefaultingService::serviceCreateLedgerDimension() --> is the function which merges the dimensions. It takes the ledger dimensions and then the financial dimension which needs to be merged and returns the recID of the merged dimension.

DimensionAttributeValueCombination::getDisplayValue() this function returns the display value of the recID which is passed to it. I have used it here to demonstration purpose only. 

There are many other useful API's existing in this class which can be very helpful in developing customizations which require to use financial and ledger dimensions.
The ledger dimension framework whitepaper can be downloaded from technet using this link.

Thanks for reading the blog and keep sharing. 

Thursday, May 29, 2014

AX2012 : SSRS error - Request failed with HTTP status 401

Hi Friends,
Want to share this scenario:
I started getting this error message when running SSRS report in one of the environment and I was bit surprised that why suddenly I face this error although I was able to run the reports properly 5 minutes back:
As I was attached to system administer role so I was pretty sure that it was not a security permission issue inside AX. Google search resulting in several links and one of them suggested to log off from the windows and log back in.
On doing that system prompted me that my domain password has expired and must be changed. So I changed the password and then when I ran the report in AX again it executed successfully.
 So in this case, the domain password was expired which resulted in SSSR report execution error.
This might not be a sure shot solution but it worked for me.In case you have also faces similar issue then please do comment on the resolution you found for this.
Have a good day.

Thursday, April 17, 2014

AX2012 R2 CU7 - Pallet transports -[Part V - Relocation]

Hi Friends,
In this last part of my pallet transport series in continuation to my previous posts here . I will show how we can create relocation pallet transport in Microsoft Dynamics AX 2012 R2 CU7. These are created to move pallets inside a warehouse from one bulk location to another bulk/picking location. This could be for any reason like any maintenance activity to be carried inside a warehouse or to make some space in warehouse and move goods to another location.

So for illustration let's see on hand on my test item in the system, notice goods are at bulk location for pallet 00000638_114.
Now in order to create a relocation transport, we can right click on the pallet ID and go to Pallet form

 Now go to Functions --> Move Pallet

This will open the move pallet dialog where user needs to select the toLocation where this pallet needs to be moved to.

The list of locations shown in To-Location are based on the logic which can be found in the method findFreeLocations() in table TmpWMSLocation table. It Is based on the location where the pallet is currently available:

Click OK system creates a relocation transport which can be viewed from the pallet transport handling button

 We can now go to pallet transport handling form and follow the normal process of starting the pallet transport and complete it.

Once we complete it, see the on hand of the item and we can see that goods have been moved to another bulk location.

The class used in the above process is WmsPalletMove and the code to create the relocation pallet transport can be found in method createRelocationTransportOnServer().

This was the last blog post in the pallet transports blog series. I hope this will be of help the readers to to understand the basics of pallet transports in Microsoft Dynamics AX 2012 R2 CU7 and it's previous versions.With the upcoming AX2012 R3 release the community is excited to see the new functionalities in the AX WMS portfolio and probably some features are getting changed in this area too.
Till my next blog,....take care and keep sharing :).

Sunday, April 6, 2014

AX2012 R2 CU7 - Pallet transports -[Part IV - Outbound]

Hi Friends,
In continuation to my blog post series on pallet transports, this is the fourth post ,the previous posts can be found at these links (Part IPart II and Part III ).
In this post I'll be talking about the setup required to create outbound pallet transport in Microsoft Dynamics AX2012 R2 CU7.
An outbound pallet transport is created during shipment reservation and is controlled by the shipment reservation combination for the method Output transport - all bulk locations.
As the name suggest, when goods are lying in bulk locations and shipment reservation combination is running the rule - "output transport - all bulk location", outbound pallet transports are created. The rule means that if goods are lying in bulk locations then create the outbound pallet transport to move them to outbound dock. If there are no goods lying in bulk locations then system will try to reserve based on the rule with next priority and if there is no rule then reservation will fail.

So let;s walk-through this in a standard AX2012 R2 CU7 environment, I have on hand of the item no  "000139_202" in the bulk locations as shown below:

My shipment template is using shipment reservation sequence which uses a shipment reservation combination having Output transport - all bulk locations at highest priority configured in it;s line as shown below:

So now I create a sales order and then an output order which in turn create the shipment of the sales line.Notice the inventory transaction at this point

Now let's run the shipment reservation, at this point system checks the availability of goods at bulk location and as they are available system creates a output transport from bulk location to the outbound dock. Also interesting to see the inventory transactions at this point

We can look at the pallet transport from shipment inquiry >> Pallet transport option.

Now we can activate the  transport and then we can view it on the pallet transports form

Let's complete the pallet transport and then see the inventory transactions of the shipment lines. You will notice that the status is updated to "Picked"

Also interesting to note that system did not created any picking list or picking route in this case as this task has been accomplished by the pallet transport itself.
Technically the magic happens in WMSReservationEngine class which initialize the object of WmsReservation class based on the Reservation method, see below in this case the class created is WMSRreserve_Output

There is lot more to explore and find the hidden jewels of AX in these classes.The method to trigger the creation of output pallet transport is called in reserve()  as shown below:

So we saw in this post how we can configure shipment reservation combination to create outbound pallet transports.

Thanks for reading the blog, keep sharing.

Thursday, March 13, 2014

AX2012 : Removal of suspension of recId allocation for table VendInvoiceInfoTable has failed.

Hi Friends,
Recently working on one environment on AX2012 FP CU4 I got the below error on posting purchase order invoice and the following steps helped to fix the error:
  1. Generate Full CIL
  2. Stop AOS
  3. Delete *.auc files
  4. Start AOS
Before running full CIL, I also tried with generating incremental IL, but that did not helped.

This might not be a sure shot solution but it worked for me.

Keep sharing!!!

Saturday, March 1, 2014

AX2012 R2 CU7 - Pallet transports -[Part III - Refill]

Hi Friends,
My previous two posts on pallet transports were about Setup and Inbound pallet transports, in this post let's have a look on refill pallet transports.
Refill's are required in warehouse to refill goods at picking locations. Normally the picking locations are refilled from buffer location.

Let's see setup required in system to generate automatic refill pallet transport:
1. Shipment reservation combination: Shipment reservation combination are defined on shipment template. This sequence is used to reserve goods for the shipment. Refill can be turned on only for item picking location sequence as shown below

2. Automatic creation and activation of refill transports can be defined in store areas.

Refills can also be created manually for a picking location from inventory locations form and then functions > Create refill as shown below, this option is only available for picking locations.

So let us walk through the first automatic scenario to create refill pallet transport using shipment reservation sequence.
First let's look at the setup and the current system situation. The current warehouse item setup for the item I will be using is as shown below

Note the item picking location is 01-01-01-1

The default issue location is 01-01-02-1 which is a bulk location

Now let us see the on hand of the item

Notice that all the goods are placed in the bulk location of my warehouse, see below all the locations where goods are currently stored are bulk locations

To keep it simple, I have defined the shipment reservation sequence to look only for item picking locations and have turned on the refill parameter as shown below:
So now we are all set to run the show, let's create a new sales order for this item

Notice the default location in SO line is coming from the warehouse items, let's take a look at inventory transaction at this point

Let's manually reserve the goods against the stock lying in bulk location, I am doing this to also show the reservation changes when we reserve the shipment

Let's move ahead and create an output order, this will create the shipment for the sales line, see below when the shipment is created it maintained the reservation done on sales line but the shipment status is still registered and it is not reserved

Now let's run the shipment reservation , the magic happens at this time, system will try to reserve the goods at the item picking location but as we know there is no on hand at item picking location and we have turned on the Refill parameter, so system will still reserve the goods at the item picking location and will also create a refill pallet transport from the bulk location to the item picking location, see below when we run the shipment reservation

Notice that the shipment status is registered but the reserved check box is turned on.
The reservation has changed to the item picking location and the status is Reserved ordered

At this point if you open the pallet transport screen you will see that system has created a refill pallet transport from the bulk location to picking location

Before proceeding further with the pallet transport,  let's activate the shipment and look at the picking list

Look at the picking route, it shows that goods needs to be picked from the item picking location

At this point if user tried to complete picking list he will get error because the refill is not yet  complete and the goods are still at the bulk location. So let's go to the refill pallet transport and complete it.

Look at the inventory transactions of the pallet transport

 Now let's look at the on hand of the item after completing the refill pallet transport, this shows that the goods have now been moved to the picking location:

Notice that on hand is now available at the picking location, so we are good now the picking location has been refilled form the buffer location and now we can complete the picking list created for the shipment

The shipment status changed to Picked

The inventory transaction is updated to picked from the item picking location

On the sales line the line quantity is shown as picked

The output order is shown as picked

So we walked through the scenario where system automatically created a refill pallet transport using shipment reservation sequence setup.

The other automatic scenario is the automatic creation of refill pallet transports from the store area setup.

When we pick item from a picking location (manually, from picking list or from any other pallet transport) then system automatically creates a refill pallet transport to the picking location if the remaining on hand qty falls below the setup defined in item warehouse location and if the store area of that location is having the automatic activation turned on and there is no other refill pallet transport already en-route to that picking location.

User can also create refills manually, directly from the location form, but this button is enabled only for the locations of type picking. The system uses same algorithm to check and create a refill pallet transport when it creates automatically or manually. Interested readers who want to read the code can check out the \Classes\WMSPickingLocationRefillCheck\checkAndRefill() function to understand more on the logic behind it.

So to summarize, refill pallet transports are created in the following situations:

  • Automatic -> Shipment reservations
  • Automatic -> Completing the picking route 
  • Automatic -> Completing pallet transport
  • Manually -> Refill function from locations form for picking locations.
Have a nice day and stay tuned...