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
Post a Comment