Jump to content

Need to add correct shipping AFTER discounts, promotions, vouchers


Recommended Posts

Hi,

 

I'm having problems with how the shipping rate is applied at the checkout and would like some imput from the experts.

 

I'm currently offering free shipping on orders over €35 and €1.95 for orders under €35. However, if there is a promotion (for example, 3 for 2) the shipping cost is still being calculated based on the original cart total, not the final figure. For example:

 

Now:

customer buys 3 products, €15 each, on 3 for 2 promotion. The product total before promotion is €45, so the free shipping is added to the order. Then the cart shows a deduction of €15 on 3 for 2, so the order total is now €30 (and this is what the customer pays) but the shipping is still free.

 

Should be:

As the final payment amount is below the free shipping threashold, the €1.95 charge must be added.

 

Basically, I need to configure the shipping cost so that it's added last, after applications of discounts, vouchers, promotions, etc.

 

Any help is greatly appreciated!

  • Like 1
Link to comment
Share on other sites

  • 1 month later...
  • 4 weeks later...
  • 2 months later...
  • 5 months later...

I think I figured it out in ps 1.6

this modification takes a total price of products with discounts for calculating range of shipping

 

it's not nice solution but works

 

classes/cart.php at about 2561 line after this

		// Order total in default currency without fees
		$order_total = $this->getOrderTotal(true, Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING, $product_list);

you need add

		$order_dis = $this->getOrderTotal(true, Cart::ONLY_DISCOUNTS, $product_list);
		$order_total = $order_total - $order_dis;

have fun :)

  • Like 1
Link to comment
Share on other sites

  • 4 months later...

I think I figured it out in ps 1.6

this modification takes a total price of products with discounts for calculating range of shipping

 

it's not nice solution but works

 

classes/cart.php at about 2561 line after this

		// Order total in default currency without fees
		$order_total = $this->getOrderTotal(true, Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING, $product_list);

you need add

		$order_dis = $this->getOrderTotal(true, Cart::ONLY_DISCOUNTS, $product_list);
		$order_total = $order_total - $order_dis;

have fun :)

 

I added it and now all my pages load blank... any ideas?  :unsure:

Link to comment
Share on other sites

  • 2 weeks later...

I think I figured it out in ps 1.6

this modification takes a total price of products with discounts for calculating range of shipping

 

it's not nice solution but works

 

classes/cart.php at about 2561 line after this

		// Order total in default currency without fees
		$order_total = $this->getOrderTotal(true, Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING, $product_list);

you need add

		$order_dis = $this->getOrderTotal(true, Cart::ONLY_DISCOUNTS, $product_list);
		$order_total = $order_total - $order_dis;

have fun :)

it's working for me 

Link to comment
Share on other sites

which error do you have?

 

if you create this voucher (cart rule), return a maximum execution time error. Because prestashop calls 8 times this function (getpackageshippingcost) and this function calls getOrderTotal 2 times, every time.

Link to comment
Share on other sites

Hi Aka_ys and mir-aus

 

Same problem here...

 

I can´t create any cart rule with free shipping. If I select this option then the shop crash when the customer selects this voucher and then the only option is to delete the cart (in backoffice) and then the customer can start from the beginning.

 

Please help.

(Sorry my english)

Link to comment
Share on other sites

Hi Aka_ys and mir-aus

 

Same problem here...

 

I can´t create any cart rule with free shipping. If I select this option then the shop crash when the customer selects this voucher and then the only option is to delete the cart (in backoffice) and then the customer can start from the beginning.

 

Please help.

(Sorry my english)

HI, but for me is working OK, I have price range( for example anything over than $95.00 with AUSpost shows free shipping) I never use free shipping option in cart rule.

If I use free shipping in cart rule then it doesn't work for me as well.

Edited by mir-aus (see edit history)
Link to comment
Share on other sites

I think If we can add some code which said that,

 

IF discount code use freeshipping option use same code as before. or in simple way:

 

after:

// Order total in default currency without fees
        $order_total = $this->getOrderTotal(true, Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING, $product_list)

 

we need code : if discount code use free shipping option do same as before if discount code doesn't use freeshipping option and use the price range for shipping then do this:

 

$order_dis = $this->getOrderTotal(true, Cart::ONLY_DISCOUNTS, $product_list);

        $order_total = $order_total - $order_dis;

 

 

I am not web-developer to type the new code if anyone knows that will help us.

Link to comment
Share on other sites

Hi Aka_ys and mir-aus

 

Same problem here...

 

I can´t create any cart rule with free shipping. If I select this option then the shop crash when the customer selects this voucher and then the only option is to delete the cart (in backoffice) and then the customer can start from the beginning.

 

Please help.

(Sorry my english)

 

no problem.

 

follow steps:

 

(the problem occurs when use function getOrderTotal with ONLY_DISCOUNTS when the discount is free shipping)

 

Overriding class Cart.php

You need create your own method.

 

1) Create function to get vouchers of this cart.

public function getVoucher_(){
		$cart_id = Context::getContext()->cart->id;
		$cart = New Cart($cart_id);
		$cr = $this->getRealDisc($cart_id);
		return $cr;
	}

2) Create second function calling from getVoucher_

public function getRealDisc($cart_id)
	{
		return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
		SELECT `id_cart_rule`
		FROM `'._DB_PREFIX_.'cart_cart_rule` cr
		WHERE cr.`id_cart` = '.(int)$cart_id);
	}

3) Create other function that return if this cart_rule is free_shipping

public function existFreeRule($id_cart_rule)
	{
		$result = Db::getInstance()->getValue('
		SELECT `free_shipping`
		FROM `'._DB_PREFIX_.'cart_rule` cr
		WHERE cr.id_cart_rule = '.(int)$id_cart_rule.' 
		AND cr.date_from < "'.date('Y-m-d H:i:s').'"
		AND cr.date_to > "'.date('Y-m-d H:i:s').'"');

		return $result;
	}

4) And finally modify prestashop function getPackageShippingCost like after.

Add this lines after // Order total in default currency without fees and before of // Start with shipping cost at 0 $shipping_cost = 0;

// Order total in default currency without fees
		$order_total = $this->getOrderTotal(true, Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING, $product_list);

		//recalculate shipping cost
		$free_s = false;

	
			$cr = $this->getVoucher_();
			if(count($cr) > 0){
				foreach ($cr as $crr) {
					$exist = $this->existFreeRule($crr['id_cart_rule']);
					if ($exist == 1){
						$free_s = true;
						break;
					}

				}
			}
	

		if(!$free_s){
				$order_dis = $this->getOrderTotal(true, Cart::ONLY_DISCOUNTS, $product_list);
				$order_total = $order_total - $order_dis;
			}

// Start with shipping cost at 0
		$shipping_cost = 0;

From this way, you only run this function getOrderTotal(true, Cart::ONLY_DISCOUNTS, $product_list); when there are no free shipping discounts in cart

Edited by aka_ys (see edit history)
Link to comment
Share on other sites

Hi aka_ys, It works!!

 

Thank you very much!

Genius!!

 

The only problem is that I´ve just detected that prestashop doesn´t apply automatically the "free shipping" option to a new cart rule generated after using it partially to pay an order. I mean with the "partial use" option applied. So I have to manually apply the option "free shipping" to each new cart rule generated after each use... :-(

 

(sorry my english)

Link to comment
Share on other sites

  • 1 month later...
  • 2 months later...

Hi,

 

here is another (dirty) workaround that is working in a prestashop 1.6.1.1 with a huge amount of products, without blank page or "out of memory" error.

 

just replace $order_total from $orderTotalwithDiscounts in lines 2965 and 2972 classes/Cart.php

// Get shipping cost using correct method
        if ($carrier->range_behavior) {
            if (!isset($id_zone)) {
                // Get id zone
                if (isset($this->id_address_delivery)
                    && $this->id_address_delivery
                    && Customer::customerHasAddress($this->id_customer, $this->id_address_delivery)) {
                    $id_zone = Address::getZoneById((int)$this->id_address_delivery);
                } else {
                    $id_zone = (int)$default_country->id_zone;
                }
            }

            if (($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT && !Carrier::checkDeliveryPriceByWeight($carrier->id, $this->getTotalWeight(), (int)$id_zone))
            || ($shipping_method == Carrier::SHIPPING_METHOD_PRICE && !Carrier::checkDeliveryPriceByPrice($carrier->id, $total_package_without_shipping_tax_inc, $id_zone, (int)$this->id_currency)
            )) {
                $shipping_cost += 0;
            } else {
                if ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT) {
                    $shipping_cost += $carrier->getDeliveryPriceByWeight($this->getTotalWeight($product_list), $id_zone);
                } else { // by price
                    //WORKAROUND
                    //$shipping_cost += $carrier->getDeliveryPriceByPrice($order_total, $id_zone, (int)$this->id_currency);
                    $shipping_cost += $carrier->getDeliveryPriceByPrice($orderTotalwithDiscounts, $id_zone, (int)$this->id_currency);
                }
            }
        } else {
            if ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT) {
                $shipping_cost += $carrier->getDeliveryPriceByWeight($this->getTotalWeight($product_list), $id_zone);
            } else {
                //WORKAROUND
                //$shipping_cost += $carrier->getDeliveryPriceByPrice($order_total, $id_zone, (int)$this->id_currency);
                $shipping_cost += $carrier->getDeliveryPriceByPrice($orderTotalwithDiscounts, $id_zone, (int)$this->id_currency);
            }
        }
Edited by annoyingusername (see edit history)
  • Like 2
Link to comment
Share on other sites

 

Hi,

 

here is another (dirty) workaround that is working in a prestashop 1.6.1.1 with a huge amount of products, without blank page or "out of memory" error.

 

just replace $order_total from $orderTotalwithDiscounts in lines 2965 and 2972 classes/Cart.php

// Get shipping cost using correct method
        if ($carrier->range_behavior) {
            if (!isset($id_zone)) {
                // Get id zone
                if (isset($this->id_address_delivery)
                    && $this->id_address_delivery
                    && Customer::customerHasAddress($this->id_customer, $this->id_address_delivery)) {
                    $id_zone = Address::getZoneById((int)$this->id_address_delivery);
                } else {
                    $id_zone = (int)$default_country->id_zone;
                }
            }

            if (($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT && !Carrier::checkDeliveryPriceByWeight($carrier->id, $this->getTotalWeight(), (int)$id_zone))
            || ($shipping_method == Carrier::SHIPPING_METHOD_PRICE && !Carrier::checkDeliveryPriceByPrice($carrier->id, $total_package_without_shipping_tax_inc, $id_zone, (int)$this->id_currency)
            )) {
                $shipping_cost += 0;
            } else {
                if ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT) {
                    $shipping_cost += $carrier->getDeliveryPriceByWeight($this->getTotalWeight($product_list), $id_zone);
                } else { // by price
                    //WORKAROUND
                    //$shipping_cost += $carrier->getDeliveryPriceByPrice($order_total, $id_zone, (int)$this->id_currency);
                    $shipping_cost += $carrier->getDeliveryPriceByPrice($orderTotalwithDiscounts, $id_zone, (int)$this->id_currency);
                }
            }
        } else {
            if ($shipping_method == Carrier::SHIPPING_METHOD_WEIGHT) {
                $shipping_cost += $carrier->getDeliveryPriceByWeight($this->getTotalWeight($product_list), $id_zone);
            } else {
                //WORKAROUND
                //$shipping_cost += $carrier->getDeliveryPriceByPrice($order_total, $id_zone, (int)$this->id_currency);
                $shipping_cost += $carrier->getDeliveryPriceByPrice($orderTotalwithDiscounts, $id_zone, (int)$this->id_currency);
            }
        }

 

 

This is working!!! Thank you very much!!!

Link to comment
Share on other sites

  • 2 weeks later...
  • 7 months later...

  I think this is the regarding github-issue:

 

[*] Calculate carrier price on the real order price #4402

 

the suggested solution is even simpler:

 

instead of "ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING":

$order_total = $this->getOrderTotal(true, Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING, $product_list);

use "BOTH_WITHOUT_SHIPPING" :

$order_total = $this->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING, $product_list);
Edited by brrt (see edit history)
  • Like 4
  • Thanks 2
Link to comment
Share on other sites

  • 2 months later...

 

  I think this is the regarding github-issue:

 

[*] Calculate carrier price on the real order price #4402

 

the suggested solution is even simpler:

 

instead of "ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING":

$order_total = $this->getOrderTotal(true, Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING, $product_list);

use "BOTH_WITHOUT_SHIPPING" :

$order_total = $this->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING, $product_list);

 

This didn't work for me in 1.6.2. Any ideas why? I cleared the cache after I made the changes. Emptied my cart, and re-added a product and voucher code. Still doesn't work.

Link to comment
Share on other sites

  • 2 months later...
  • 4 weeks later...

 

  I think this is the regarding github-issue:

 

[*] Calculate carrier price on the real order price #4402

 

the suggested solution is even simpler:

 

instead of "ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING":

$order_total = $this->getOrderTotal(true, Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING, $product_list);

use "BOTH_WITHOUT_SHIPPING" :

$order_total = $this->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING, $product_list);

 

 

Its working on my system (1.6.1.6).

Thanks a lot.

Link to comment
Share on other sites

  • 7 months later...

 

  I think this is the regarding github-issue:

 

[*] Calculate carrier price on the real order price #4402

 

the suggested solution is even simpler:

 

instead of "ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING":

$order_total = $this->getOrderTotal(true, Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING, $product_list);

use "BOTH_WITHOUT_SHIPPING" :

$order_total = $this->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING, $product_list);

This worked for me on 1.6.1.12, perfect solucion!!!!!!!!!!

Link to comment
Share on other sites

×
×
  • Create New...