web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Finance | Project Operations, Human Resources, ...
Suggested Answer

How to create sales order by SysOperation framework using x++ code in D365 F&O

(0) ShareShare
ReportReport
Posted on by 5
As 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; 

 } 

} 

I have the same question (0)
  • huijij Profile Picture
    19,811 on at

    Thanks for your sharing.

  • Suggested answer
    Deepak Agarwal Profile Picture
    8,602 on at

    Thanks for sharing this, it will be more helpful if you put them in proper formatting. Use rich formatting for the same.  

  • Rafiullah Afridi Profile Picture
    5 on at

  • Martin Dráb Profile Picture
    237,908 Most Valuable Professional on at

    Please don't confuse discussion forums with a blogging platform. Blog posts don't belong here.

    Also, if you want to ask questions here, learn how to do it. For example, use Insert > Code (in the rich formatting view) to paste source code. It'll make code much easier to read than your post above.

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Neeraj Kumar – Community Spotlight

We are honored to recognize Neeraj Kumar as our Community Spotlight honoree for…

Leaderboard > Finance | Project Operations, Human Resources, AX, GP, SL

#1
Martin Dráb Profile Picture

Martin Dráb 544 Most Valuable Professional

#2
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 450 Super User 2025 Season 2

#3
Sohaib Cheema Profile Picture

Sohaib Cheema 250 User Group Leader

Last 30 days Overall leaderboard

Product updates

Dynamics 365 release plans