Developer forum

Forum » Development » Force recalculate cart

Force recalculate cart

Nuno Aguiar
Reply

Hi,

 

We developed an add-on that removes ordelines just before moving to checkout. So far so good, but some testing revealed that simply saving the cart does not trigger the cart recalculating. How can we do that?

 

The problems we are facing are:

  1. We end up with 0 products in the cart, so the user get's sent to payment, paying only the shipping fees: We wanted to trigger the empty cart settings!
  2. We remove orderlines that were triggering discounts: We wanted the cart to recalculate the discounts. We may end up in situation 1

 

Can you help us achieve this?

 

Best Regards,

Nuno Aguiar


Replies

 
Vladimir
Reply

Hi Nuno,

try this:

1)

            order.ForcePriceRecalculation()

2)

            ' Find discounts
            eCommerce.Frontend.Cart.CartCatch.FindDiscount()

            ' Recalculate Taxes
            Products.Taxes.TaxSetting.GetActiveTaxSettings().AddTaxesToOrder(cart)

Kind regards,

Vladimir

 
Nuno Aguiar
Reply

Hi Vladimir,

 

Thanks a lot.

Nuno Aguiar

 
Nuno Aguiar
Reply

Hi Vladimir,

 

Neither solution worked :(

 

We tried saving the order before recalculation, after recalculating, all actions isolated, all bundled, always with the same results:

  1. When there are no products remaining in the cart, we go to the checkout just with the shipping fees
  2. When we remove the product that triggered the orderline, the discount is still there

 

Maybe we should be subscribing to a different event? Can you take a look at the attachment?

 

Best Regards,

Nuno Aguiar

 
Vladimir
Reply

Hi Nuno,

I think I has understood what to do: 
In OrderIsPassedToCheckoutHandler order is passed with property order.IsCart = false; - this prevents order from any changes;
So you can make:
...make something what you want with order;
order.IsCart = true;
..discount/taxes/recalc;
order.IsCart = false;

 

Best regards,

Vladimir

 
Gonçalo Assunção
Reply

Hello Vladimir,

First of all, thank you for the help!

The context is the following: The discount is a discount matrix, and it is added to the order, as an orderline, and not to a product orderline.

I'm testing with only one product in the cart.

Now, I tried your suggestion, and it didn't recalculate the cart. First, the property IsCart of the OrderIsPassedToCheckoutHandler order comes with the value of "true".

 

I've tried to set the AllowOverridePrices property to "true" on each the order and all the orderlines, but that didn't produce any result.

Basicly, what we want is to reproduce the same behaviour as in the edit cart section, where if you update the quantity of the product, it recalculates the discount orderline, or it removes it, if the product is removed from the cart.

I've also tried to subscribe to the Dynamicweb.Notifications.eCommerce.Cart.BeforeShippingMethodIsSet event.

With exactly the same code that I am sending, subscribing to this event, it produces (partly) the result that we want. It removes the orderline with the product, and the discount orderline that was triggered by the product. But, (and here comes the 'partly' part of the result) it still sends me to checkout, despite the absence of any orderline in the cart,  billing me only the shipping fee. Here, I need it to trigger the empty cart event.

 

please check the attachement with the code.

Thank you in advance.

 
Vladimir
Reply

Hi guys,

yes, BeforeShippingMethodIsSet event is better place for such actions.

And my suggestion to trigger empty cart event:
lets create a new validation group for an field(http://manual.dynamicweb-cms.com/Default.aspx?ID=7249).
If field value = 1  - throw validation error.
And in BeforeShippingMethodIsSet handler you could control value for that field

btw you could remove rows(after BeforeShippingMethodIsSet cart will be recalculated):

            //force the price recalculation, due to the payment and shipping fees             
            Dynamicweb.eCommerce.Frontend.Cart.CartCatch.FindDiscount();
            Dynamicweb.eCommerce.Products.Taxes.TaxSetting.GetActiveTaxSettings().AddTaxesToOrder(currentOrder);

            currentOrder.ForcePriceRecalculation();
            currentOrder.Save();

            /*
            if (currentOrder.IsCart)
                currentOrder.IsCart = false;
            */

            Dynamicweb.eCommerce.Common.Context.SetCart(currentOrder);

​Best regards,

Vladimir

 
Gonçalo Assunção
Reply

Hello Vladimir,

 

Thank you again for your help!

In this case, we really want, if possible, to have all the behavior in the final dll. Your aproach would require to have an extra configuration, and if possible, we would want to avoid that.

I have searched in the Download section, for the source code of the checkout / add to cart process, but I had no luck with that..
I have tried the following methods:

if (currentOrder.OrderLines.CountOnlyProducts <= 0)
{
                currentOrder.DeliveryAddress = null;
                currentOrder.DeliveryAddress2 = null;
                currentOrder.DeliveryCell = null;
                currentOrder.DeliveryCity = null;
                currentOrder.DeliveryCompany = null;
                currentOrder.DeliveryCountry = null;
                currentOrder.DeliveryCountryCode = null;
                currentOrder.DeliveryEmail = null;
                currentOrder.DeliveryFax = null;
                currentOrder.DeliveryFirstName = null;
                currentOrder.DeliveryHouseNumber = null;
                currentOrder.DeliveryInitials = null;
                currentOrder.DeliveryMiddleName = null;
                currentOrder.DeliveryName = null;
                currentOrder.DeliveryPhone = null;
                currentOrder.DeliveryPrefix = null;
                currentOrder.DeliveryRegion = null;
                currentOrder.DeliverySurname = null;
                currentOrder.DeliveryTitle = null;
                currentOrder.DeliveryZip = null;
                currentOrder.AllowOverridePrices = true;
                currentOrder.ShippingMethod = null;
                
                currentOrder.ShippingFee.IsInformative = false;
                currentOrder.ShippingFee.Multiply(0);
                Dynamicweb.eCommerce.Frontend.Cart.CartCatch.ClearCart();               
}

my thought were: "If it doesn't have any delivery detail, then it can't configure the shipping method to the order"... I was wrong :)

I have also tried to subscribe to the AfterShippingMethodIsSet event, and set the shipping method to 'null', but it still leads to checkout billing only the shipping fees.

In the first step of the checkout process, if I remove the product from the cart, it triggers the empty cart event, just like I would like to do in this case.

Any thoughts?

 

Thank you once again!

Gonçalo Assunção

 
Vladimir
Reply

Hi Gonçalo,

Lets try to use property order.ShippingProviderErrors

So if (currentOrder.OrderLines.CountOnlyProducts <= 0) order.ShippingProviderErrors.Add("I can't deliver empty cart!!!");

else order.ShippingProviderErrors.clear();

I think this wiil work:)

Best regards,

Vladimir

 
Gonçalo Assunção
Reply

Hello Vladimir,

That also didn't work :(

Now we found another issue:

Our checkout process ir composed by 4 steps: 1-> costumer address  2-> delivery adress 3 -> review and confirm order details 4 -> payment:
 

We are eliminating the orderlines in the process of the step 2 to 3. If we have only one product, and it is eliminated, we go to step 3 with the shipping fees.

Now,  if we have more thant 1 product, and if only 1 product is eliminated (we still have other products remaining in the cart), and we reach step 3, we can exit the cart and add those products that were previously eliminated. When we comeback to the checkout process, we begin now at step 3 (because in the back office we configure the car to remind the last step). I can eliminate that product, but we still have our first problem, which is that the discount associated with that product is not removed.

I have tried to subscribe to other events like EcomCartBeforeRenderingNewStepObserver and tried the following code:

     if (cartStepIndex >= 1 && currentOrder.ShippingMethod != null)
                {
                    OrderlineValidation validation = new OrderlineValidation();
                    validation.validateOrder(currentOrder);
                    Dynamicweb.eCommerce.Frontend.Cart.CartCatch.FindDiscount();
                    currentOrder.ForcePriceRecalculation();

                }

But as I said, it doesn't eliminate the discount. Only the product. I've noticed that only a few propertys are changed in the order object when we move from step 2 to step 3. The main change that I saw was the "IsCaptureSupported" property from false to true. Has this have anything to do with this?

I have also tried the EcomCartLoadedObserver. This seems to eliminate the discount too:

                Order currentOrder = loadedArgs.Cart;

                var pv = Dynamicweb.Frontend.PageView.Current();
                
                if (pv.ID == currentOrder.CheckoutPageID  && currentOrder.ShippingMethod != null)
                {
                    OrderlineValidation validation = new OrderlineValidation();
                    validation.validateOrder(currentOrder);
                }

But not always the pageviewID is equal to the checkout page ID. Sometimes it gets the ID of the 404 page of the site, but still redirects to the following checkout step.

Any thoughts?

Thank you again for your help!
Best Regards from Portugal

Gonçalo Assunção

 
Vladimir
Reply

Hi Gonçalo,

Thank you for the regards - our North edges became warmer :)
By the truth, I'm confused... All seemed fine...

"IsCaptureSupported" property means that payment provider was assigned to the order and it supports capturing...  The more interesting property is order.CartV2StepIndex imho:)

I suppose that problem with BeforeShippingMethodIsSet notification is that it is sent only when EcomCartShippingmethodID exists in postback.
(so it fires in your case only on steps 2 -> 3)

So you could send BeforeShippingMethodIsSet noification on step 3 with hidden input with id = EcomCartShippingmethodID
Or there is another appropriate notification, Notifications.eCommerce.Cart.BeforeRemovingNonExistingProducts:
1. be  sure cart setting "Unavailable products" = remove (it is default value))
2. just fil order lines to remove: args.OrderLinesToRemove
it will remove lines and it will render Loop MissingProducts in template (so you coud handle it in nice way)

Best regards,

Vladimir

 

 
Gonçalo Assunção
Reply

Hello Vladimir!

Tried that method, but got the same 'old' result: Checkout billing only the shipping fees.
The best method that I found so far, is was this, that I mencioned before, with the EcomCartLoadedObserver event.

     var pv = Dynamicweb.Frontend.PageView.Current();
                
                if (pv.ID == currentOrder.CheckoutPageID  && !string.IsNullOrEmpty(currentOrder.ShippingMethod))
                {
                    OrderlineValidation validation = new OrderlineValidation();
                    validation.validateOrder(currentOrder);                   
                }

But as I said, pv.ID is not always equal to the checkoutPageID. It get tons of different ID's, due to all the redirecting. But, with this method, the cartV2StepIndex is always equal to 0.

 

Kind Regards

Gonçalo Assunção

 

I have also tried the EcomCartLoadedObserver. This seems to eliminate the discount too:

                Order currentOrder = loadedArgs.Cart;

                var pv = Dynamicweb.Frontend.PageView.Current();
                
                if (pv.ID == currentOrder.CheckoutPageID  && currentOrder.ShippingMethod != null)
                {
                    OrderlineValidation validation = new OrderlineValidation();
                    validation.validateOrder(currentOrder);
                }

- See more at: http://developer.dynamicweb.com/forum/development/development/force-recalculate-cart.aspx#sthash.hHlXmv2y.dpuf

I have also tried the EcomCartLoadedObserver. This seems to eliminate the discount too:

                Order currentOrder = loadedArgs.Cart;

                var pv = Dynamicweb.Frontend.PageView.Current();
                
                if (pv.ID == currentOrder.CheckoutPageID  && currentOrder.ShippingMethod != null)
                {
                    OrderlineValidation validation = new OrderlineValidation();
                    validation.validateOrder(currentOrder);
                }

- See more at: http://developer.dynamicweb.com/forum/development/development/force-recalculate-cart.aspx#sthash.hHlXmv2y.dpuf

I have also tried the EcomCartLoadedObserver. This seems to eliminate the discount too:

                Order currentOrder = loadedArgs.Cart;

                var pv = Dynamicweb.Frontend.PageView.Current();
                
                if (pv.ID == currentOrder.CheckoutPageID  && currentOrder.ShippingMethod != null)
                {
                    OrderlineValidation validation = new OrderlineValidation();
                    validation.validateOrder(currentOrder);
                }

- See more at: http://developer.dynamicweb.com/forum/development/development/force-recalculate-cart.aspx#sthash.hHlXmv2y.dpuf
 
Vladimir
Reply

Hi Gonçalo,

It seems lacking of extensibility at the moment of validation of an order... I will disscus with the boss that issue...

So if it is not possible to make some settings... I found only place to insert validation message :

      [Dynamicweb.Extensibility.Subscribe(Dynamicweb.Notifications.eCommerce.Order.AfterSave)]
      public class EcomOrderAfterSaveObserver : Dynamicweb.Extensibility.NotificationSubscriber
      {
          public override void OnNotify(string notification, Dynamicweb.Extensibility.NotificationArgs args)
          {
              Dynamicweb.Notifications.eCommerce.Order.AfterSaveArgs afterSaveArgs = args as Dynamicweb.Notifications.eCommerce.Order.AfterSaveArgs;

              if (validOrder) afterSaveArgs.Order.ShippingProviderErrors.Add("something wrong");
              else afterSaveArgs.Order.ShippingProviderErrors.Clear();
          }
      }

 Best regards,

Vladimir

 

You must be logged in to post in the forum