How to create Sales Order by SysOperation framework

 How to create Sales Order by SysOperation framework 

is you know that sales order is the most important and useful feature of Dynamic-365 F&O and many developers have requirement to create sales order through x++ code. in this blog i will share the complete step by step process with x++ code. But before starting you should need to know the complete cycle of creating sales order. 

1- Create Sales order 

2- Confirm Sales order 

3- Create Picking List 

4- Register picking list 

5- Create Picking Slip 

6- Invoiced Sales order 

So let’s get started, 

first, you need to create the following three classes for Sys Operation. 

SOSysOperationsController // SO Sales Order 

SOSysOperationsContract 

SOSysOperationsService 

 Then finally create Display Menu Item to open Parameter form. 

step-1 : create a class with the following name and extends from SysOperationServiceController or copy paste the following code. 

class SOSysOperationsController extends SysOperationServiceController 

 protected void new() 

 { 

     super(classStr(SOSysOperationsService), methodStr(SOSysOperationsService, process),

                                                                         SysOperationExecutionMode::Synchronous); 

 } 

 public static SOSysOperationsController construct(SysOperationExecutionMode _executionMode =

                                                                                              SysOperationExecutionMode::Synchronous) 

 {

 SOSysOperationsController controller = new SOSysOperationsController(); 

 controller.parmExecutionMode(_executionMode); 

 return controller; 

 } 

 public static void main(Args _args) 

 { 

     SOSysOperationsController controller;  

     controller = SOSysOperationsController::construct(); 

     controller.parmArgs(_args); 

 controller.startOperation(); 

 } 

step-2 : create another class for Contract to show pop-form and paste the following code 

class SOSysOperationsContract 

 CustAccount custAccount; 

 ItemId itemId; 

 InventLocationId inventLocationId; //warehouse; 

 InventSiteId inventSiteId; //Site 

 [DataMemberAttribute("custAccount"), AifCollectionTypeAttribute("_custAccount", Types::String)] public CustAccount parmCustAccount(CustAccount _custAccount = custAccount) 

 { 

 custAccount = _custAccount; return custAccount;

 } 

 [DataMemberAttribute("ItemId"), AifCollectionTypeAttribute("_ItemId", Types::String)] 

 public ItemId parmItemId(ItemId _itemId = itemId) 

 {

 itemId = _itemId; return itemId; 

 } 

 [DataMemberAttribute("inventLocationId"), AifCollectionTypeAttribute("_inventLocationId", Types::String)] 

 public InventLocationId parmInventLocationId(InventLocationId _inventLocationId = inventLocationId) 

 {

 inventLocationId = _inventLocationId; return inventLocationId; 

 } 

 [DataMemberAttribute("InventSiteId"), AifCollectionTypeAttribute("_InventSiteId", Types::String)]

 public InventSiteId parmInventSiteId(InventSiteId _InventSiteId = InventSiteId) 

 {

 InventSiteId = _InventSiteId; 

 return InventSiteId; 

 }

 } 

step-3 : create one more class for Services which is used for logic business copy and paste the following code. 

class SOSysOperationsService extends SysOperationServiceBase 

 SalesTable salesTable; 

 SalesLine salesLine; 

 SalesFormLetter salesFormLetter; 

 SalesFormLetter_PickingList pickingList; 

 InventDim inventDim; 

 WMSPickingRouteID pickingRouteId; 

 NumberSeq numberSeq; 

 CustPackingSlipJour custPackingSlipJour; 

 SalesId salesId; 

 List list = new List(Types::String); 

 CustInvoiceJour custInvoiceJour; 

 InventTable inventTable; 

 CustTable custTable; 

 CustAccount custAccount; 

 str warehouse; 

 str site;

 ItemId itemId; 

 public void process(SOSysOperationsContract _contract) 

 {

 custAccount =_contract.parmCustAccount(); 

 itemId = _contract.parmitemId(); 

 site = _contract.parmInventSiteId(); 

 warehouse = _contract.parmInventLocationId();

 ttsbegin; salesTable.clear();

 numberSeq = NumberSeq::newGetNum(SalesParameters::numRefSalesId()); 

 numberSeq.used();

 salesTable.SalesId = numberSeq.num(); 

 salesId = salesTable.SalesId; 

 salesTable.initValue(); ///custAccount = "US-001";

 if(CustTable::find(custAccount)) 

 { 

 salesTable.CustAccount = custAccount; 

 } 

 else 

 { 

 info(strFmt("Customer account %1 doesn't exist.", custAccount)); 

 }

 salesTable.initFromCustTable(); 

 if(InventLocation::find(warehouse).InventLocationId != "") 

 { 

 salesTable.InventSiteId = InventLocation::find(warehouse).InventSiteId; 

 salesTable.InventLocationId = inventlocation::find(warehouse).InventLocationId; 

 } 

 salesTable.insert();

 inventTable.clear(); 

 inventDim.clear(); 

 salesLine.clear();

 select * from inventTable where inventTable.itemId == itemId; //"1000";

 salesLine.clear(); 

 salesLine.SalesId = salesId; 

 salesLine.ItemId = inventTable.ItemId; 

 salesLine.itemIdChanged(); 

 salesLine.initFromInventTable(InventTable::find(salesLine.ItemId));

 if(Inventlocation::find(warehouse).InventLocationId != "") 

 {

 inventdim.InventSiteId = InventLocation::find(warehouse).InventSiteId; 

 inventdim.InventLocationId = Inventlocation::find(warehouse).InventLocationId; 

 } 

 salesLine.InventDimId = InventdIm::findOrCreate(inventDim).inventDimId;

 salesLine.createLine(NoYes::Yes, // Validate 

 NoYes::Yes, // initFromSalesTable 

 NoYes::No, // initFromInventTable 

 NoYes::Yes, // calcInventQty

 NoYes::Yes, // searchMarkup 

 NoYes::Yes); //

 salesLine.SalesPrice = 250; 

 salesLine.SalesQty = 3; 

 salesLine.LineDisc = 25;

 salesLine.RemainSalesPhysical = salesLine.SalesQty;

 salesLine.QtyOrdered = salesLine.calcQtyOrdered(); 

 salesLine.RemainInventPhysical = salesLine.QtyOrdered;

 salesLine.LineAmount= salesLine.calcLineAmount(); 

 salesLine.update(); 

 ttscommit; 

 info(strFmt("Sales order '%1' has been created", salesTable.SalesId));


 ////////CreateSOConfirmed //////// 

 ttsBegin; salesTable = SalesTable::find(salesId);

 salesFormLetter = SalesFormLetter::construct(DocumentStatus::Confirmation);

 salesFormLetter.update(salesTable, systemDateGet(), SalesUpdate::All, AccountOrder::None, false, false);

 ttsCommit; 

 info(strFmt("Sales order '%1' has been Confirmed", salesTable.SalesId));


 //////// CreateSOPickingList////////

 ttsBegin; salesTable = SalesTable::find(salesId); 

 if (salesTable && salesTable.SalesStatus == SalesStatus::Backorder) 

 {

 salesFormLetter = SalesFormLetter::construct(DocumentStatus::PackingSlip); salesFormLetter.update(salesTable,systemDateGet(),SalesUpdate::PackingSlip,AccountOrder::one, NoYes::No, NoYes::No, NoYes::No); 

 if (salesFormLetter.parmJournalRecord().TableId == tableNum(custPackingSlipJour)) 

 {

 custPackingSlipJour = salesFormLetter.parmJournalRecord(); 

 info(strFmt('Packing Slip :%1 successfully created for Sales Order :%2', custPackingSlipJour.PackingSlipId, custPackingSlipJour.SalesId)); 

 }

 } 

 else

 { 

 info(strFmt('%1 does not exsists in the system !', salesId)); 

 } 

 ttscommit; 

 ////////Picking List Register//////// 

 ttsBegin; 

 select pickingRouteID from WMSPickingRoute where WMSPickingRoute.customer ==custAccount; 

        pickingRouteId = WMSPickingRoute.pickingRouteID;

        if(pickingRouteId)

        {

            list.addEnd(WMSPickingRoute.pickingRouteID);

            WMSPickingRoute::finishMulti(list.pack());

            info(strFmt("Picking List Register with pickingRouteID: %1",pickingRouteId));

        }

        else

        {

            info(strFmt('%1 does not exsists in the system !', pickingRouteId));

        }

        ttsCommit;


 /////// CreateSOPickingSlip //////// 

 ttsBegin; salesTable = salesTable::find(salesId); ///replace '001011' your sales order number 

 salesFormLetter = SalesFormLetter_PickingList::newPickingList();

 salesFormLetter.transDate(systemDateGet());

 salesFormLetter.update(salesTable, systemdateget(), SalesUpdate::All, AccountOrder::None, NoYes::No, NoYes::No);

 ttsCommit; 

 info(strFmt("Sales order '%1' Picking List created", salesTable.SalesId)); 


 ////////Invoicing the sales order//////// 

 ttsBegin;

 try 

 { 

 salesTable = SalesTable::find(salesId); 

 if (salesTable && salesTable.SalesStatus == SalesStatus::Delivered) 

 { 

 salesFormLetter = SalesFormLetter::construct(DocumentStatus::Invoice); 

 salesFormLetter.update(salesTable, systemDateGet(), SalesUpdate::All, AccountOrder::None, NoYes::No, NoYes::No, NoYes::No, NoYes::Yes); 

 if (salesFormLetter.parmJournalRecord().TableId == tableNum(CustInvoiceJour)) 

 { 

 custInvoiceJour = salesFormLetter.parmJournalRecord(); 

 info(strFmt('Invoice for Sales Order: %1 has been posted, Invoice: %2', custInvoiceJour.SalesId, custInvoiceJour.InvoiceId)); 

 }

 } 

 else 

 {

 info(strFmt('%1 does not exsists or not in delivered state.', salesId)); 

 } 

 } 

 catch (Exception::Error) 

 {

 info(strFmt('Failed to post Sales order invoice for %1.', salesId)); 

 } 

 ttscommit; 

 } 

Step-4 : create Action Menu Item for opening parameter form. 



Step-5 : Set the following properties for Action Menu Item. 



Step-6 : Finally create Menu Extension and Drag your Action Menu Item on it. 



Now build your project and refresh your browser and find and click your Menu item the following Parameter Form will be open. 



That’s it and enjoy….

Comments

Popular posts from this blog

How to Extract and generate a CSV File and Retrieve a List of Project Addresses in AX 2012 Using SQL and X++

How to create C# Library and Use with in Dynamics 365 For Finance and Operation

Extracting Project Addresses to Excel in Dynamics AX 2012