I'm logging this question under the Finance forum because it is X++ code and I will get faster an answer here than on the Retail forum.
I just want to know how the class works because it is not updating when I expected it to update.
The POS orders are created in Finance using the class RetailTransactionServiceOrders.createCustomerOrderNew().
It works weird for me in that it populates a map and it jumps between the map RetailOrderHeaderMap and the actual table: SalesTable.
We have custom in D365 where we assign a payment term to the delivery mode record in some cases. The customer has a delivery mode and it is defaulted to the salesTable on creation. It's the same for the POS order. I have to apply this custom to the POS order too when it is created in D365 via the backend process. I have changed successfully the payment term on the mapping to the payment term on the delivery mode if there was one assigned to the delivery mode record. So this part of my custom works.
In RetailTransactionServiceOrders::createOrUpdateRetailOrderHeader you will see it has a call to RetailCreateCustomerOrderExtensions::orderHeaderBeforeInsert(args); It is in here where I added my custom to replace the payment term to what is on the delivery mode instead of it taking it from the customer. This part works.
/*
public static void orderHeaderBeforeInsert(RetailCustomerOrderHeaderParameters args)
{
// CoC
next orderHeaderBeforeInsert(args);
boolean vCreateNew = args.createNew;
RetailOrderHeaderMap orderHeader = args.orderHeader as RetailOrderHeaderMap;
if(vCreateNew)
{
TMC_OrderTOP top = DlvMode::TMC_GetOrderPaymentTerm(orderHeader.DlvMode);
if(top)
{
orderHeader.getTableInInstanceHierarchy(tableNum(SalesTable)).setFieldValue("Payment", top);
}
}
}
*/
The part that I can't get to work is that I now need to add a validation that if the payment term differs from the customer payment term, then I need to set a custom flag flag that indicates that the order is on hold and I have to create an entry in the MCRHoldCodeTrans table. The link is the InventRefId = salesTable.SalesId. My custom fields are only on Salestable, not the RetailOrderHeaderMap. Because the custom was added to D365 a while ago.
Inside the method createCustomerOrderNew, directly after the call to RetailTransactionServiceOrders::createOrUpdateRetailOrderHeader, is a call to a delegate: RetailTransactionServiceOrders::beforeCreatingRetailOrderLines(salesTable, custOrderInfo);.
If one right-click on that delegate and choose: Copy event handler method, it creates the signature as follow:
"
[SubscribesTo(classStr(RetailTransactionServiceOrders), staticDelegateStr(RetailTransactionServiceOrders, beforeCreatingRetailOrderLines))]
public static void RetailTransactionServiceOrders_beforeCreatingRetailOrderLines(SalesTable _salesTable, Microsoft.Dynamics.Commerce.Runtime.Services.CustomerOrder.CustomerOrderInfo _customerOrderInfo)
"
I'm assuming I can just use the _salesTable, run my validation and then update the custom fields on it and also create the MCRHoldCodeTrans record when applicable.
However after the order is created, I can go to All Sales Orders and find my order and the status is not set when it is supposed to be set and there is no MCRHoldCodeTrans record created. It is as if it is not running the code in the delegate. However the payment term on the order has the correct one from the delivery mode.
If you look in createCustomerOrderNew, you will see it has a ttsbegin.
Then it runs RetailTransactionServiceOrders::createOrUpdateRetailOrderHeader and RetailTransactionServiceOrders::beforeCreatingRetailOrderLines and a bunch of other code and at the end it has either a ttsabort or a ttscommit, depending on what happens in between.
So for my custom in the delegate, do I just update the custom fields on _salesTable or do I include a _salestable.update()?
I did it without the update and with the update, with the same results. It's not updating _salestable.
Maybe _salestable is not in a SelectForUpdate state maybe ?
Or do I need to switch back to RetailOrderheaderMap and update that instead? Which means I have to add my custom fields to the map too. Then how to I update the MCRHoldcodeTrans record then if the delegate doesn't work.
My code:
/* ******
[SubscribesTo(classStr(RetailTransactionServiceOrders), staticDelegateStr(RetailTransactionServiceOrders, beforeCreatingRetailOrderLines))]
public static void RetailTransactionServiceOrders_beforeCreatingRetailOrderLines(SalesTable _salesTable, Microsoft.Dynamics.Commerce.Runtime.Services.CustomerOrder.CustomerOrderInfo _customerOrderInfo)
{
TMC_ManageInvoiceInCCProcess manageInvoiceInCCProcess = new TMC_ManageInvoiceInCCProcess();
// if the mode of delivery changes the term payment, then put the order on hold
boolean vOK = manageInvoiceInCCProcess.runCCPaymentTermCheck(_salestable);
TMC_CreditCheckEnums vStatus;
if(!vOK)
{
vStatus = TMC_CreditCheckEnums::Fail;
TMC_ManageInvoiceInCCProcess::mcrPutOrderOnHold(_salesTable.SalesId, "Term", strFmt("@TMC:TMC149"));
}
else
{
vStatus = TMC_CreditCheckEnums::Pass;
}
_salesTable.TMC_CreditCheckDate = DateTimeUtil::getToday(DateTimeUtil::getUserPreferredTimeZone());
_salesTable.TMC_CreditCheckStatus = vStatus;
_salesTable.update();
}
}
***** */
Ay help will be much appreciated in understanding this class and the jumping between OrderHeaderMap and SalesTable and which one am I supposed to update to update my custom fields.
I need to get this to work ASAP.