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?
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 (domhk.blogspot.hk/.../ax2012-update-invent-registration-from.html) 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!
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 )
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;
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? :)
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?
I put the line you quoted to a public static server method and it worked. Maybe it's something else?
My blog | PBC
This forum post is my own opinion and does not necessarily reflect the opinion or view of Microsoft, its employees, or other MVPs.
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
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.
KHALEDE / DOLEE,
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.
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.
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!