Create voyage in the dynamics 365 SCM using code x++
In this article, I will share how you can automate the process of voyage creation in the dynamics 365 F&O using code (x++). The process of voyage exists in the Dynamics 365 Supply chain management, under the Landed cost module as shown in below fig.
What is voyage?
A voyage typically represents a vessel. However, depending on your practices and procedures, it can represent a vendor, a purchase order, or some other item that makes sense for your organization.
How to create voyage using code?
public boolean createVoyage(PurchLine purchLine { ITMTable itmTable; ITMTmpCreatorTable itmTMPCreatorTBL,itmTMPCreatorTBLUpdate; ITMTmpCreatorLine itmTMPCreatorLine,itmTMPCreatorLineUpdate; ITMLine itmLines; ITMContainers itmContainer; ITMCostTrans itmCostTrans; ITMFolioTable itmFolioTbl; ITMCostEstimateTable itmCostEstimateTBL; PurchTable purchTable; ITMCostAutoLine iTMCostAutoLine; ITMCostAutoTable iTMCostAutoTable; PurchLine purchLineUpdateVoyage; boolean ret = false; ITMAddBucketContainerFormHandler addBucketContainerForm; purchTable = PurchTable::find(purchLine.PurchId); try { ttsbegin; itmTable.clear(); itmTable.initValue(); itmTable.initFromPurchTable(purchTable); itmTable.ShipId = this.getvoyageNumSeq(); itmTable.ShipDescription = purchTable.PurchId; itmTable.ShipVesselId = AAMYCustomTable.ShipVesselId; itmTable.ITMPurchStatus = PurchTable::find(purchLine.PurchId).PurchStatus; itmTable.ShipVendAccount = AAMYCustomTable.AccountRelation; itmTable.DlvModeId = AAMYCustomTable.DlvModeId; itmTable.insert(); // Adding the lines data of itmEditor form in table ITMTmpCreatorTable (TMP TABLE) itmTMPCreatorTBL.clear(); itmTMPCreatorTBL.initValue(); itmTMPCreatorTBL.DateStatus = DateTimeUtil::date(today()); itmTMPCreatorTBL.InventTransType = InventTransType::Purch; itmTMPCreatorTBL.InventTransRefId = purchTable.PurchId; itmTMPCreatorTBL.NoOfLines = 1; itmTMPCreatorTBL.InventQty = purchLine.PurchQty; itmTMPCreatorTBL.ShipDataArea = purchTable.DataAreaId; itmTMPCreatorTBL.insert(); // Adding the lines data of itmEditor form in table ITMTmpCreatorLine (TMP TABLE) itmTMPCreatorLine.clear(); itmTMPCreatorLine.initValue(); itmTMPCreatorLine.DateStatus = DateTimeUtil::date(today()); itmTMPCreatorLine.InventTransType = InventTransType::Purch; itmTMPCreatorLine.InventTransRefId = purchTable.PurchId; ITMTmpCreatorLine.DateStatus = DateTimeUtil::date(today()); ITMTmpCreatorLine.ItemId = purchLine.ItemId; ITMTmpCreatorLine.PurchQty = purchLine.PurchQty; ITMTmpCreatorLine.Selected = NoYes::Yes; ITMTmpCreatorLine.ShipDataArea = purchLine.DataAreaId; ITMTmpCreatorLine.PurchUnit = purchLine.PurchUnit; ITMTmpCreatorLine.InventQty = purchLine.RemainInventPhysical; ITMTmpCreatorLine.TransferQty = 1; ITMTmpCreatorLine.InventTransId = purchLine.InventTransId; ITMTmpCreatorLine.InventDimId = purchLine.InventDimId; ITMTmpCreatorLine.insert(); ITMEditorFormHandler itmEditor = new ITMEditorFormHandler(); // vIEW STAGING // itmEditor.showBucketContainer(itmTMPCreatorTBL, itmTMPCreatorLine, itmTable); itmEditor.parmITMTable(itmTable); itmEditor.parmTmpCreatorTable(itmTMPCreatorTBL); itmEditor.parmTmpCreatorLine(ITMTmpCreatorLine); // ADD TO STAGING itmEditor.addToBucket(itmTMPCreatorTBL,itmTMPCreatorLine); // ITMCreatorTableGeneration::addToBucketFromForm(itmTMPCreatorTBL, itmTMPCreatorLine); // Create shipping container itmContainer.clear(); itmContainer.initValue(); itmContainer.initFromShipTable(itmTable); itmContainer.ShipId = itmTable.ShipId; itmContainer.ShipPurchStatus = PurchTable::find(purchLine.PurchId).PurchStatus; itmContainer.OrigShipId =itmTable.ShipId; itmContainer.ShipContainerId = itmTable.ShipVesselId; itmContainer.ShipContainerTypeId = itmTable.ShipVesselId; itmContainer.insert(); // default method calling addBucketContainerForm = new ITMAddBucketContainerFormHandler(); addBucketContainerForm.parmITMTable(itmTable); addBucketContainerForm.parmTmpCreatorLine(ITMTmpCreatorLine); addBucketContainerForm.parmITMContainers(itmContainer); addBucketContainerForm.validateTmpCreatorLine(); ITMCreatorCreateShipment::createShipmentFromShipEditor(ITMTmpCreatorLine,itmTable,itmContainer,true); addBucketContainerForm.addQtyifSplitQty(); addBucketContainerForm.removeTmpCreatorLine(); addBucketContainerForm.updateInventTransIdInBucket(); // creating folio itmFolioTbl.clear(); itmTable.initValue(); itmFolioTbl.ShipFolioId = this.getFolioNumSeq(); itmFolioTbl.ShipId = itmTable.ShipId; itmFolioTbl.ShipDataArea = itmTable.DataAreaId; itmFolioTbl.initFromShipTable(itmTable); itmFolioTbl.VendAccount = AAMYCustomTable.AccountRelation; itmFolioTbl.insert(); ttscommit; Info(strFmt('Voyage created %1',itmTable.ShipId)); ret = true; return ret; } catch(Exception::Error) { throw Exception::Error; return ret; } } public str getvoyageNumSeq() { NumberSeq numberSeq = NumberSeq::newGetNum(NumberSeqReference::findReference(extendedTypeNum(ITMId))); numberSeq.used(); return numberSeq.num(); } public str getFolioNumSeq() { NumberSeq numberSeq = NumberSeq::newGetNum(NumberSeqReference::findReference(extendedTypeNum(ITMFolioId))); numberSeq.used(); return numberSeq.num(); })
Happy learning,
Syed Amir Ali.
D365FO Lead Technical Consultant at Argano
1yMentioned code perfectly running fine for creating voyages for purchase. But getting error as "Voyage creator Item number must be specified" if i run the code for transfer order with respective changes in code for inventreftype, inventrefid and other fields to take from inventtransferline instead of purchline. Can you please suggest as I'm badly stucked in the issue. Syed Amir Ali