Registering/Receiving Inventory with X++ - AX 2012

Question Status

Andy Adamak asked a question on 17 Jan 2013 4:04 PM

We are trying to register some product (Site, Warehouse, Location, Serial Number) for a receiving service in AX 2012.  What is the proper way to do this? 

I have it working if the product doesn't require serial number, I just update the line's Receive Now quantity and PurchFormLetter.update using PurchUpdate::ReceiveNow quantity.

But for things that require a serial number, I have to register that product first, then use the PurchUpdate::Recorded quantity to receive in. 

Basically, I need to perform the function of the InventTransRegister Form in X++ code.  How is this accomplished?



khalede responded on 22 Mar 2013 4:08 PM

Sorry , I copied the wrong error, the correct error message is :

"Inventory transactions are not supported for this posting."

All what I want is to create an inventory registration to assign a vendor batch id, so I used your code as is, I only passed the transaction id, and the batch id which already exist. below is my full method , And I get the error in the last statement, on the call to updateInvent method

public void InventoryRegisterLine(PurchId _purchId, str _packSlipId, int _reveivedQty,ItemId _item, str _site, str _warehouse, str _location, str _batch )


   InventTrans       inventTrans;

   PurchLine         purchLine;

   InventDim         inventDim;

   InventDimId       inventDimId;

   InventTransWMS_Register inventTransWMS_register;

   TmpInventTransWMS tmpInventTransWMS;

   inventDim.InventSiteId = _site;

   inventDim.InventLocationId = _warehouse;

   inventDim.WMSLocationId = _location;

   inventDim.InventBatchId = _batch;

   inventDimId              = InventDim::findOrCreate(inventDim).InventDimId;

   select  * from purchLine where purchLine.PurchId == _purchId && purchLine.itemid == _item && purchLine.inventdimid  == inventDimId;  

   inventTrans = InventTrans::findTransId(purchLine.InventTransId);

   inventDim = inventTrans.inventDim();

   inventTransWMS_register = inventTransWMS_register::newStandard(tmpInventTransWMS);



   tmpInventTransWMS.InventQty = _reveivedQty;

   inventDim.inventBatchId = _batch;

   tmpInventTransWMS.InventDimId = inventDim::findOrCreate(inventDim).inventDimId;







khalede responded on 22 Mar 2013 5:31 PM

Thank you Andy for trying to help. it gave me a clue anyway. I found the error, which is very weird.  I found that this statement


Does not initiate the itemid in the tmpInventTransWMS, and all what I needed  to make it work is adding a line:

tmpInventTransWMS.itemid = _item. I wonder how come your code doesn't need this statement?

Ax is fun, Isn't it? :)

khalede responded on 24 Mar 2013 12:06 AM

I need to run this code from a custom service, but it gives me an error because the services class must run on server, but the method  inventTransWMS_register = inventTransWMS_register::newStandard(tmpInventTransWMS);

Is specified to run on client. How can I circumvent that?

Dominic Lee responded on 25 Mar 2013 2:20 AM

Hi Khaldede,

I put the line you quoted to a public static server method and it worked. Maybe it's something else?

khalede responded on 25 Mar 2013 6:10 AM

Nothing else Dolee, the 2 problems is as I described:

1. To use the tmpInventTransWMS for subscription, you need to add a line to initialize the item

2. You can't call any of the inventTransWMS_register methods from a service because it's a client class: I circumvented that by copied this class and it's base class and used the copied classes after changing them to server classes

Everything work now, thank you

Andy Adamak responded on 25 Mar 2013 6:36 AM


The client/server issue is something I have in my service as well that I haven't tackled yet.  I have it in 2 or 3 places in the entire code, but haven't tried to fix it yet.  The inventTransWMS_register was one of them, so thanks for that!  Hopefully the other ones are just as easy :)

And yes, setting the itemid on the tmpInventTransWMS was something I had added as well.



Andy Adamak responded on 27 Mar 2013 12:30 PM


Copying the classes and changing to a server class instead of a client one works as KHALEDE describes.  Would it be a terrible idea to just change the original class (InventTransWMS) from 'RunOn: Client' to 'Server' instead of duplicating everything?  For this or any class... just wondering.



Dominic Lee responded on 27 Mar 2013 11:59 PM

Hi Andy,

I am guessing InventTransWMS is set to be a client class to reduce chattiness between the AOS and client. (I am thinking about tmpInventtransWMS in particular.)

Depends on the usage pattern it could be negligible or not acceptable. And I think similar logic can apply to other classes as well.

If time permits, maybe it's better to dig deeper and see if it's possible to call InventTransWMS_Register::updateInventOnServer() method directly. Then there's no need to copy the classes and set them as server class.


saman0suke responded on 18 Jan 2014 10:55 PM

I'm having the same problem that you mentioned at the beginning Andy, Dolee's code works for me because I changed the FinTransId() for FindRecId() so it will always select the appropiate record in InventTrans, however, it does not change the status from Ordered to Registered, is there something missing in that code? thanks I appreciate the help!

nagaraj responded on 20 Aug 2014 8:06 AM

can you give brief discussion on above issue

Arun Garg responded on 20 Jan 2016 3:38 AM

Hi Andy,

Can you please provide the code you have modified.



Verified Answer
Andy Adamak responded on 15 Feb 2013 7:36 AM

To answer this question, it was a mix of a lot of things, starting with dolee's code:

"Hi Andy,
For some reason I can't post code here. Please check this post ( for an example that you can try in your development or testing environment."

Which caused the following error, but got me on the right track:

"Posting  Purchase order: PO-000001  Item: TestItem  Transaction has already been posted physically.  Posting An error occurred during update"

This error was caused by:

"InventTrans             inventTrans = InventTrans::findTransId();
This bit of code simply grabs the first InventTransOrigin record where the InventTransID's match, then grabs the FIRST record of the InventTrans table where it matches up with the origin... regardless of status. The issue I was running into was even if it was received/registered, whatever status, it would grab the first InventTrans and override the record and it's InventDim record as well.
So... It works, but not really because it totally messes up all your transactions if you receive more than once against the same PO line."

Which I resolved in this post:

"So I think I got it.  InventTrans::findTransId() wasn't cutting it for the above explained reason.  So, I used a similar query from that method, but made an addition to the where clause to grab inventTrans.StatusReceipt == StatusReceipt::Ordered.
Also, instead of setting the inventDim = inventTrans.inventDim(), I created a brand new InventDim to set all my registration variables (SerialNumber, Location, Warehouse, etc etc)  This seems to help prevent the occasional overriding of serial numbers (Invent Dims). 
The entire code is quite lengthy, but these two things fixed the major issues I was having."

As I stated, my entire service is much more complex, but the above should help get you on your way!