Catch the "Last" OrderInfo Update After Event?

Senior Software Engineer - Kentico Xperience MVP

Trevor Fayas asked on August 30, 2017 20:30

Hey all,

Kentico's Event hooks are awesome, except for the Ecommerce ones. When you have an order with say, 3 items, and you add an item, it triggers 8 total "OrderInfo" Update events.

The reason I believe is that the cart will remove each OrderItem from the cart one at a time, then add the new items, and each one triggers an OrderInfo Update.

So what you get is after adding a 4th item to the order...

  • Update Triggered = Order w/ 3 Items
  • Update Triggered = Order w/ 2 Items
  • Update Triggered = Order w/ 1 Item
  • Update Triggered = Order w/ 0 Items
  • Update Triggered = Order w/ 1 Item
  • Update Triggered = Order w/ 2 Items
  • Update Triggered = Order w/ 3 Items
  • Update Triggered = Order w/ 4 Items --> THIS is the one i want to execute update logic on.

I need the last event triggered as the Generation of the Shopping Cart from the Order object at each step only has the certain # of items in it, and i need to call the ShippingOptionInfoProvider.GetShippingTax(cart) and update some custom Shipping Tax fields on the order we need for an integration, along with freight discounts.

Anyone have any idea how to catch the LAST execution at the end of the chain? I've resorted to seeing if the calculated total shipping = the Order.OrderTotalShippingInMainCurrency, but that's calling the create cart (so i can calculate the shipping) and the get Shipping cost each time.

Correct Answer

Trevor Fayas answered on August 30, 2017 21:51

In my example in order to generate the shipping i needed the ShoppingCart object, which if i get from the Order on the 1st time, it wasn't accurate, so recursion didn't help.

But i did find out the correct way to go about this. Even if an order is already created, the ShoppingCartInfoProvider.SetOrderInternal(ShoppingCartInfo cartObj, bool generateInvoice) is called 1 time. This method will then cause the OrderItem.Update to trigger a bunch.

So i overwrote that method, used the cartObj (which is the TRUE order status) to find the ShippingTax and Discount, and set it in the cartObj.ShoppingCartCustomData.

Then i used the OrderItem.Update.Before with a recursion to catch the first execution and GET The OrderObject's CustomData values of my taxes and set the corresponding fields.

[assembly: RegisterCustomProvider(typeof(CustomShoppingCartInfoProvider))]
public class CustomShoppingCartInfoProvider : ShoppingCartInfoProvider
{
    protected override void SetOrderInternal(ShoppingCartInfo cartObj, bool generateInvoice)
    {
        try { 
            // Set some Custom Order Data so the OrderInfo.Events.Insert.Before and OrderInfo.Events.Update.Before can latch onto them.
            double ShippingCost = ShippingOptionInfoProvider.CalculateShipping(cartObj);
            cartObj.ShoppingCartCustomData.SetValue("ShippingTax", ShippingOptionInfoProvider.CalculateShippingTax(cartObj));
            cartObj.ShoppingCartCustomData.SetValue("ShippingDiscount", ShippingOptionInfoProvider.CalculateShippingDiscount(cartObj, ShippingCost));
        } catch(Exception ex)
        {
            EventLogProvider.LogException("CustomShoppingCartInfoProvider", "ERRORSETTINGSHIPPINGVALUES", ex, cartObj.ShoppingCartSiteID, additionalMessage: "Could not set the Shipping Tax and Shipping Discount for the order due to an error calculating shipping.");
        }
        base.SetOrderInternal(cartObj, generateInvoice);
    }

}

.

protected override void OnInit()
    {
 // Add Custom Fields from Order Custom Field webpart to Order from Shopping Cart and handle getting the Shipping Taxes and Discount from the Custom Data (Set in the Custom Shopping Cart Info Provider)
        OrderInfo.TYPEINFO.Events.Insert.Before += OrderInsert_Before;
        OrderInfo.TYPEINFO.Events.Update.Before += OrderUpdate_Before;
    }

    private void OrderUpdate_Before(object sender, ObjectEventArgs e)
    {
        try
        {
            OrderInfo OrderObject = (OrderInfo)e.Object;
            RecursionControl FirstTimeSetTaxAndDiscount = new RecursionControl("OrderUpdate_" + OrderObject.OrderID);
            if(FirstTimeSetTaxAndDiscount.Continue) { 
                // Set shipping tax and discount fields set from the CustomShoppingCartInfoProvider.SetOrderInternal
                if (OrderObject.OrderCustomData.ContainsColumn("ShippingTax"))
                {
                    OrderObject.SetValue("OrderTotalShippingTaxesInMainCurrency", Convert.ToDouble(OrderObject.OrderCustomData.GetValue("ShippingTax")));
                }
                if (OrderObject.OrderCustomData.ContainsColumn("ShippingDiscount"))
                {
                    OrderObject.SetValue("OrderTotalShippingDiscountInMainCurrency", Convert.ToDouble(OrderObject.OrderCustomData.GetValue("ShippingDiscount")));
                }
            }
        } catch(Exception ex)
        {
            EventLogProvider.LogException("CustomLoader", "OrderUpdate_Before", ex);
        }
    }
1 votesVote for this answer Unmark Correct answer

Recent Answers


Brenden Kehren answered on August 30, 2017 21:38

Can you not use the RecursionControl() method on that particular event and then process the rest of the items until before, after or never? Or are you looking for something else?

string rKey = "updateOrderForCheckPayment";
// only allow this to happen once per save event
using (var rc = new RecursionControl(rKey))
{
    if (rc.Continue)
    {

    }
}
2 votesVote for this answer Mark as a Correct answer

Trevor Fayas answered on August 30, 2017 21:52

I'll mark my answer as the correct answer so others can learn from it, but i voted for ya Brenden as always appreciate your input!

2 votesVote for this answer Mark as a Correct answer

   Please, sign in to be able to submit a new answer.