Wednesday 24 December 2014

Adding the Update operation to the Inventory Counting Journal Document Service




Hi guys, it has been for a while since last post. The year 2014 is comming to an  end and looking back it could be said that it was a really interesting year. I achieved to improve my German but also took on a new position and now I am working for one of the leading german clothing brands company with Microsoft Dynamics Ax 2012 R3 on the Retail Module.

Let's start with the purporse of this post. How to add the Update operation to the Inventory Counting Journal Document Service.

By default Microsoft has only provided the Create operation and it would be really interesting to have also the Read operation in order to create a Inventory Counting Journal on the system and send it through AIF but also the Update operation so we can receive back this Inventory through AIF in order to update the journal and post it.

The Inventory Counting Journal

We can find the Inventory Counting Journal on Inventory Management, Journals, Invent Counting, Counting. I think I have not to speak too much about it. The purporse of this post is to create manually a Inventory Counting Journal, send it out with AIF (We will add also the find and read operations) and receive the counted Inventory Counting Journal with AIF.




We have to setup the default Inventory Counting Journal for AIF on the Inventory and Warehouse Parametes, AIF Parameters section.




In order to update the standard Document Service Invent Counting Journal with the read, update and additional operations we use the Update document service  Wizard that we can find on Tools, Application Integration Framework, Update document service. 

Here provide we the name of the Service class InventCountingJournalService and we activate the service operations read, update, find, findKeys, getKeys and getChangedKeys. We activate also "Regenerate date object classes" and "Update AxBC classes". We click on OK and the Wizard will update the Document Service classes with the new operations.


We need also to update the Document Service Query AxdCountingJournal and set the "Update" value to "Yes" on the Query Data Sources InventJournalTable and InventJournalTrans because we want to be able to update data.

Also on the JoinMode of the InventDim datasource we change it to "OuterJoin" cause we want to be able to work with XML Messages which contain not info about the InventDim record. If we don't change the property, the Query will return nothing because the InnerJoin with the InventDim table.

Next, we need to add the new operations on the InventCountingJournalService Service. On the InventCountingJournalService, we make right click and in the node Operations we add the new operations.


Then, we have to refresh the service in order to update the new operation definitions. We make right click on the InventCountingJournalService, select Add-Ins and then on Register Service. Select the InventCountingJournalService and then click on Refresh in order to update the new operations on the service so they could be used on the outbound and inbound ports.


Next we need to check on the class Axd<Document> (AxdCountingJournal) and on the service class (InventCountingJournalService) if the corresponding operations methods are implemented.

On the AxdCountingJournal class we check the methods:
  1. findEntityKeyList
  2. findList
  3. getActionList
  4. read
  5. readList
  6. update
  7. updateList

On the InventCountingJournalService class we check the methods:


  1. find
  2. findKeys
  3. read
  4. update
In all these methods we sure make sure that there is not an error line code with the "Operation not implemented" message and in that case we should modify the code in order to implement a call to the base clase like this:


Next we make some code customizing on the Document Service classes in order to make possible the update operation with the Inventory Counting Journal.

In class AxdCountingJournal class we realice the following updates:

We add a new "createRecord" global variable to be used to control if we are creating a new record or only updating an existing one.




We modify the prepareInventJournalTrans method in order to have a code like the following:



On this code update, we check if the InventJournalTrans record already exists on system. If not, we set tup the createRecord global variable to true. Otherwise, we are updating the record and we take the actual value of the Qty field from the InventJournalTrans record because maybe this line was already counted (the Qty field have the difference between on hand and counted and is the posted qty on the InventTrans) and we also set up the proper InventDimId value on the InventJournalTrans record.

In the class AxdCountingJournal we modify the method prepareForSave with the following code in order to avoid the increase of the total number of lines in the journal. 




Configuration of the Outbound AIF Port

As we have also implemented the methods "Read" and "Find" we could create an outbound port in order to send out a XML message with the content of an inventory counting journal. We could use this message to send the Inventory Counting Journal to an external application which the proper Hash code that we need later when we build the incoming XML message.

Below the configuration of the outbound port





And the generated outbound XML Message:


Configuration of the Inbound AIF Port:

Below the configuration of an Inbound Port in order to be able to process incoming XML messages with the Update operation.




And the corresponding XML message with the Update operation:


Details about the update operation and implications with the Hash Code concept

Within the outbound and inbound messages finds itself the element “_DocumentHash”. When data is updated using AIF, the document hash is required. When data is read, AIF returns the document hash field “_DocumentHash”. This field contains a hash of all the RecId and RecVersion values for each record that is returned. In this example the records that are returned are a Invent Counting Table, the Invent Counting lines but also maybe the Invent Dimensions if we provide them.If the data change before the AIF response, the hash will be different and the response won´t be able to be processed correctly. Below a Microsoft link with an explanation of this concept:


Using the Microsoft Dynamics Ax Trace Parser to understand and be able to modify correctly the AIF artifacts

Understanding the AIF classes and where to add or modify code is not an easy task. There is not a lot of documentation about. A good source is the document "AIF Stuff" that we cand find here:


Another great resource to understand AIF classes is to use the Microsoft Dynamics Ax Trace Parser. We have only to generate a trace when we realice and update operation and study the code to understand what we have to do to properly implement the operation.

The trace could be generated on a Job that calls the AifInboundProcessingService in order to process manually the incoming message with the Update operation.


This generates us a trace file that we can open with the Microsoft Dynamics Trace Parser so we can start researching the executed code.



Possible AIF Exceptions that could appeard while testing the new Update operation on the Inventory Counting Journal

Lastly I want to provide a list of possible AIF Exceptions that could arrise while implementing the Update operation on the Document Service.


Counting journal outbound is not supported.

This message will appear if the corresponding operation (Method findEntityKeyList, findList, getActionList, read, readList, update or updateList in class AxdCountingJournal) is still not implemented on the class AxdCountingJournal (Methods findEntityKeyList, findList, getActionList, read, readList, update or updateList),  or in the class InventCountingJournalService (Methods find, findKeys, read or update)

There is no service with namespace = 'http://schemas.microsoft.com/dynamics/2008/01/services' and external name = 'InventCountingJournalService'.
This message will appear if we have not correctly written the service name on the incoming XML Message. A look on the AIFService table will provide us the correct service name.

Cannot process duplicate message. Message {A8EF6A9C-E84A-4FCB-8813-0DBCB34BE2FA} has already been processed and is different from the new message.
This message will appear if we provide an incoming message with a MessageId with a GUID already provided. We should provide always a new GUID or establishing the EnableIdempotence property of the InventCountingJournalService update operation to “No” if we want to provide repeated values for MessageId.

No default inventory counting journal name is specified in AIF parameters
We should provide a default journal name for inventory counting journal on the AIF parameters on the Inventory Management parameters. Not confuse with the inventory management parameters default inventory counting journal.

Inventory dimension Site is mandatory and must consequently be specified.
This exception happens because the service was only implemented for the “create” operation. On the AIF Document Service classes we should assure that on the update operation the InventJournalTrans get the right InventDim as described on this post.

The request failed with the following error:  The document hash does not match the hash in the XML. The document may have been changed since last read
With the “update” operation we should provide a document Hash on the incoming XML message. This Hash is calculated using the values RecId and RecVersion from all the records that are sent or received through AIF. We must be sure about which records are we sending back (InventJournalTable, InventJournalTrans and maybe also InventDim).

Cannot create a record in Inventory transactions originator (InventTransOrigin). Reference: Counting, 00031. The record already exists.

This error should happen because the service was first implemented only for the “create” operation and when an second incoming XML Message which reference to the same InventJournalTrans record arrives. Then the system tries to create again an InventTrans for the counted quantity. The problem it is solved with a little of code on the AIF Document Classes as stated on this post.



Ok that is it! It remains only to wish you all a Merry Christmas with your family and a happy new year! 2015 seems to be pretty amazing. In Germany lot of companies are moving to Microsoft Dynamics, specially the Retail companies and the next version of Microsoft Dynamics Ax with the exciting new HTML interface will make presence.

Ich wünsche euch Frohe Weihnachten!!!!