Skip to main content

Notifications

Announcements

No record found.

Supply chain | Supply Chain Management, Commerce
Answered

BeforeCreatingRetailOrderLines delegate on RetailTransactionServiceOrders explanation on update needed urgently

(0) ShareShare
ReportReport
Posted on by 1,433

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.

  • Retha Profile Picture
    Retha 1,433 on at
    RE: BeforeCreatingRetailOrderLines delegate on RetailTransactionServiceOrders explanation on update needed urgently

    Hi Guanghui

    I moved the code to RetailCreateCustomerOrderExtensions::orderHeaderBeforeInsert and it worked.

    But because I also have to add an MCROrderHoldTrans record which MCROrderHoldTrans.insert() has business logic to update SalesTable, we have decided to leave this custom out of the POS orders for now.  The only way to bypass the business logic is to use doInsert() which is not a good idea most of the time.

  • Suggested answer
    Guanghui Profile Picture
    Guanghui on at
    RE: BeforeCreatingRetailOrderLines delegate on RetailTransactionServiceOrders explanation on update needed urgently

    Hi,

    I have not tested the code, but could you please try this code in   RetailCreateCustomerOrderExtensions::orderHeaderBeforeInsert(args)

     SalesTable salesTable = orderHeader;

     salesTable.TMC_CreditCheckDate = DateTimeUtil::getToday(DateTimeUtil::getUserPreferredTimeZone());

     salesTable.TMC_CreditCheckStatus = vStatus;

    Please don't call salesTable.update() because I think it will cause update conflict issue

  • André Arnaud de Calavon Profile Picture
    André Arnaud de Cal... 291,711 Super User 2024 Season 2 on at
    RE: BeforeCreatingRetailOrderLines delegate on RetailTransactionServiceOrders explanation on update needed urgently

    Moved to the Dynamics 365 Commerce forum.

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

Congratulations 2024 Spotlight Honorees

Kudos to all of our 2024 community stars! 🎉

Meet the Top 10 leaders for December

Congratulations to our December super stars! 🥳

Start Your Super User Journey

Join the ranks of our community heros! 🦹

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 291,711 Super User 2024 Season 2

#2
Martin Dráb Profile Picture

Martin Dráb 230,458 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156

Leaderboard

Featured topics

Product updates

Dynamics 365 release plans