Jump to content

Additional shipping cost, overides free shipping


Recommended Posts

Hello eveybody.

I am looking for a solution for overiding free shipping in specific products or categories , PS 1.5.2.

For example,

I have set a free shipping starting at 50 €.

I need, If a customer adds a product with additional shipping cost enabled , this cost is added to cart, even the cart sum is over 50€.

Any suggestions?

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

I searched the 1.5.2 code for the configuration name "PS_SHIPPING_FREE_PRICE". This is the name of the field in the back office related to your free shipping starting at 50 €

 

There are only 2 places in the code that use it, which are Cart.php and AdminShippingController.php

 

You can ignore AdminShippingController.php since that is the configuration page where you entered 50 €

In Cart.php there is a function called getPackageShippingCost which has the following code

 

// Free fees
$free_fees_price = 0;
if (isset($configuration['PS_SHIPPING_FREE_PRICE']))
   $free_fees_price = Tools::convertPrice((float)$configuration['PS_SHIPPING_FREE_PRICE'], Currency::getCurrencyInstance((int)$this->id_currency));
$orderTotalwithDiscounts = $this->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING, null, null, false);
if ($orderTotalwithDiscounts >= (float)($free_fees_price) && (float)($free_fees_price) > 0)
{
   Cache::store($cache_id, $shipping_cost);
   return $shipping_cost;
}

 

It would seem you could override this code to introduce your custom logic, so that instead of returning zero if the free shipping price is met, that you would instead return the correct rate.

 

Now I have to admit, I am having a hard time believing that this is the only area of the code that needs to change. I would suggest taking baby steps, start with this code change and test it and see how it works.

  • Like 1
Link to comment
Share on other sites

It seems that you guide me to the right way :)

I am not a programmer, but ....

For products with additional price enabled , adding to cart.php code, the "$product['additional_shipping_cost'] <= 0" seems to do the trick!


// Free fees
$free_fees_price = 0;
if (isset($configuration['PS_SHIPPING_FREE_PRICE']))
$free_fees_price = Tools::convertPrice((float)$configuration['PS_SHIPPING_FREE_PRICE'], Currency::getCurrencyInstance((int)$this->id_currency));
$orderTotalwithDiscounts = $this->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING, null, null, false);

if ($product['additional_shipping_cost'] <= 0 && $orderTotalwithDiscounts >= (float)($free_fees_price) && (float)($free_fees_price) > 0 )
{
Cache::store($cache_id, $shipping_cost);
return $shipping_cost;
}

 

( i am not marking it "solved" yet, before furter testing )

Link to comment
Share on other sites

  • 1 year later...

I think I found the solution. I'm not a programmer and haven't tested it properly yet, but so far it seems to be working... in classes/Cart.php there is the following code: 

		// Additional Shipping Cost per product
		foreach ($products as $product)
			if (!$product['is_virtual'])
				$shipping_cost += $product['additional_shipping_cost'] * $product['cart_quantity'];

I edited the code as follows (added  && $shipping_cost > 0)

		// Additional Shipping Cost per product
		foreach ($products as $product)
			if (!$product['is_virtual'] && $shipping_cost > 0)
				$shipping_cost += $product['additional_shipping_cost'] * $product['cart_quantity'];

Now if the price range for free shipping is reached in the cart, additional price per item will not be added. In other words, it will only be added if shipping cost is higher than zero. 

 

Another thing is - if you do not want the additional shipping per item to be added multiple times, delete  

* $product['cart_quantity']  

from the code.  

 

Let me know how this works for you. And don't forget to backup just in case. ;-) 

 

PS: I'm using Prestashop 1.5.4.0

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

  • 3 weeks later...
  • 2 years later...

To kadapawn: Have you solved the problem? If not, check your general free shipping rules in your shop. In my case, if I add any number of products with extra shipping in the cart, free shipping won't appear until the limit for free shipping is reached. 
 
However, I found another problem. The solution from my post #5 only applies on the quantities of the same product. If another product with extra shippping is added in the cart, extra shipping is multiplied.

Example: 
 

Cart 1:
Product A (with extra shipping) - Qty 2: extra shipping is charged only once
 

Cart 2: 
Product A (with extra shipping) - Qty 2 - extra shipping is charged once

Product B (with extra shipping) - Qty 1 - extra shipping is charged again, so twice in total

 

What I needed was to charge my customers only one additional shipping fee per cart, doesn't matter how many products with extra shipping are added. This is the code I used (classes - Cart.php): 

foreach ($products as $product)
			if (!$product['is_virtual'] && $shipping_cost > 0)
				$shipping_cost += $product['additional_shipping_cost'];

and just removed: 

foreach ($products as $product)

Now, only 1 extra shipping is charged per cart. 

 

Hope this helps someone else as well. Good luck with your shops. ;-) 

Link to comment
Share on other sites

  • 1 month later...

A very weird problem occured. I am using the above mentioned solution (post #7). When I add two products in the cart - 1 product with extra shipping and 1 product without extra shipping - the extra shipping is only calculated correctly if the second product was added in the shop BEFORE the product with extra shipping. Any product added in the shop AFTER the product with extra charge removes the extra charge from the cart. Any ideas what could be causing this? It is so weird. 

 

Example: 

 

shipping is 5 USD, extra shipping set individually in BO for a specific product is 1 USD

 

Cart 1:
Product A (with extra shipping)

Product B (product without extra shipping, added in the shop BEFORE product A)

Shipping TOTAL: 6 USD (extra shipping is applied)
 

 

Cart 2: 

Product A (with extra shipping)

Product B (product without extra shipping, added in the shop AFTER product A)

Shipping TOTAL: 5 USD (the total is wrong, it should be 6 USD = extra shipping is not applied)

Link to comment
Share on other sites

  • 1 year later...

I know this is an old thread but i managed to make this work. The fix works on 1.6.x.

We have specific products that have special shipping costs applied to them (due to their weight and the extra money the carrier charges us for them).

We needed a way to keep the shipping if under X $, and add the additional shipping fees, but if the order is greater than X $, only the additional shipping fees will count as shipping. Because the first situation is default in prestashop, i found a way to override the second situation (because PS always disregarded the additional shipping fees if shipping is free).

In cart.php, where the Free Fee is set, go ahead and replace the whole chunk of code to:

// Free fees
        $free_fees_price = 0;
        if (isset($configuration['PS_SHIPPING_FREE_PRICE'])) {
            $free_fees_price = Tools::convertPrice((float)$configuration['PS_SHIPPING_FREE_PRICE'], Currency::getCurrencyInstance((int)$this->id_currency))
                ;
        }
        $orderTotalwithDiscounts = $this->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING, null, null, false);
        if ($orderTotalwithDiscounts >= (float)($free_fees_price) && (float)($free_fees_price) > 0) {
            Cache::store($cache_id, $shipping_cost);
             foreach ($products as $product) { //added line
                $shipping_cost = $shipping_cost + ($product['additional_shipping_cost'] * $product['cart_quantity']); //added line
             } //added line
                return $shipping_cost;
                
        }

Scroll down, where you will find // Additional Shipping Cost per product, edit the whole chunk of code with: 

// Additional Shipping Cost per product
        foreach ($products as $product) {
            
            if (!$product['is_virtual'] && $product['additional_shipping_cost']) {
                
                if ($shipping_cost > 0){
                    $shipping_cost += $product['additional_shipping_cost'] * $product['cart_quantity'];
                } else $shipping_cost = $product['additional_shipping_cost'] * $product['cart_quantity'];
            }
        }

Then go up the the function getCarrierCost, edit the last part of it (i pasted the whole function here for convinience):

public function getCarrierCost($id_carrier, $useTax = true, Country $default_country = null, $delivery_option = null)
    {
        if (is_null($delivery_option)) {
            $delivery_option = $this->getDeliveryOption($default_country);
        }

        $total_shipping = 0;
        $delivery_option_list = $this->getDeliveryOptionList();


        foreach ($delivery_option as $id_address => $key) {
            if (!isset($delivery_option_list[$id_address]) || !isset($delivery_option_list[$id_address][$key])) {
                continue;
            }
            if (isset($delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier])) {
                if ($useTax) {
                    $total_shipping += $delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier]['price_with_tax'];
                } else {
                    $total_shipping += $delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier]['price_without_tax'];
                }
            }
        }
		// loop products in the cart to find the addition cost of each
        foreach ($products as $product) {
            // find the additional shopping price of products
            if (!$product['is_virtual'] && $product['additional_shipping_cost']) {
                // if shipping exists, then add additional fees to it (reduntant)
                if ($total_shipping > 0){
                    $shipping_cost += $product['additional_shipping_cost'] * $product['cart_quantity'];
				// if shipping is free, just add the additional shipping fees as shipping price
                } else $shipping_cost = $product['additional_shipping_cost'] * $product['cart_quantity'];
            }
        } 
		// increment the shipping total
        $total_shipping += $shipping_cost;
        return $total_shipping;
    }

 

I've tested the situation and it works regardless of the combinations of products you have in the cart. Free shipping, no free shipping, one or multiple products with additional shipping cost.

EDIT: Please note that the block of code below can also be inputed into the carrier.php to override the free shipping stuff PS does.

$shipping_cost + self::$price_by_price[$cache_key];

$price_by_price = Hook::exec('actionDeliveryPriceByPrice', array('id_carrier' => $id_carrier, 'order_total' => $order_total, 'id_zone' => $id_zone));
        if (is_numeric($price_by_price)) {
            self::$price_by_price[$cache_key] = $price_by_price;
        }
        //from here
        foreach ($products as $product) {
            
                $shipping_cost = $shipping_cost + ($product['additional_shipping_cost'] * $product['cart_quantity']);
            
        }
        $shipTax = $shipping_cost + self::$price_by_price[$cache_key];
        return $shipTax;

 

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

  • 10 months later...

I can confirm the method listed here by GrandMa90 still works for PS 1.7. I don't know why Prestashop hasn't made this the default behavior. One addendum I must add is that if you are using a carrier that is free shipping overall you must add some code in another spot. In the Cart.php file edit the small if statement labeled under // Free fees if free carrier. Find this code:

// Free fees if free carrier
        if ($carrier->is_free == 1) {
            Cache::store($cache_id, 0);
			return 0;
        }

Replace with this:

// Free fees if free carrier
        if ($carrier->is_free == 1) {
            Cache::store($cache_id, 0);
			$shipping_cost = 0;
			foreach ($products as $product) {
                $shipping_cost = $shipping_cost + ($product['additional_shipping_cost'] * $product['cart_quantity']); //added line
             } 
            return $shipping_cost;
        }

 

Link to comment
Share on other sites

  • 6 months later...
  • 1 year later...
On 11/14/2017 at 11:55 AM, GrandMa90 said:

I know this is an old thread but i managed to make this work. The fix works on 1.6.x.

We have specific products that have special shipping costs applied to them (due to their weight and the extra money the carrier charges us for them).

We needed a way to keep the shipping if under X $, and add the additional shipping fees, but if the order is greater than X $, only the additional shipping fees will count as shipping. Because the first situation is default in prestashop, i found a way to override the second situation (because PS always disregarded the additional shipping fees if shipping is free).

In cart.php, where the Free Fee is set, go ahead and replace the whole chunk of code to:


// Free fees
        $free_fees_price = 0;
        if (isset($configuration['PS_SHIPPING_FREE_PRICE'])) {
            $free_fees_price = Tools::convertPrice((float)$configuration['PS_SHIPPING_FREE_PRICE'], Currency::getCurrencyInstance((int)$this->id_currency))
                ;
        }
        $orderTotalwithDiscounts = $this->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING, null, null, false);
        if ($orderTotalwithDiscounts >= (float)($free_fees_price) && (float)($free_fees_price) > 0) {
            Cache::store($cache_id, $shipping_cost);
             foreach ($products as $product) { //added line
                $shipping_cost = $shipping_cost + ($product['additional_shipping_cost'] * $product['cart_quantity']); //added line
             } //added line
                return $shipping_cost;
                
        }

Scroll down, where you will find // Additional Shipping Cost per product, edit the whole chunk of code with: 


// Additional Shipping Cost per product
        foreach ($products as $product) {
            
            if (!$product['is_virtual'] && $product['additional_shipping_cost']) {
                
                if ($shipping_cost > 0){
                    $shipping_cost += $product['additional_shipping_cost'] * $product['cart_quantity'];
                } else $shipping_cost = $product['additional_shipping_cost'] * $product['cart_quantity'];
            }
        }

Then go up the the function getCarrierCost, edit the last part of it (i pasted the whole function here for convinience):


public function getCarrierCost($id_carrier, $useTax = true, Country $default_country = null, $delivery_option = null)
    {
        if (is_null($delivery_option)) {
            $delivery_option = $this->getDeliveryOption($default_country);
        }

        $total_shipping = 0;
        $delivery_option_list = $this->getDeliveryOptionList();


        foreach ($delivery_option as $id_address => $key) {
            if (!isset($delivery_option_list[$id_address]) || !isset($delivery_option_list[$id_address][$key])) {
                continue;
            }
            if (isset($delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier])) {
                if ($useTax) {
                    $total_shipping += $delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier]['price_with_tax'];
                } else {
                    $total_shipping += $delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier]['price_without_tax'];
                }
            }
        }
		// loop products in the cart to find the addition cost of each
        foreach ($products as $product) {
            // find the additional shopping price of products
            if (!$product['is_virtual'] && $product['additional_shipping_cost']) {
                // if shipping exists, then add additional fees to it (reduntant)
                if ($total_shipping > 0){
                    $shipping_cost += $product['additional_shipping_cost'] * $product['cart_quantity'];
				// if shipping is free, just add the additional shipping fees as shipping price
                } else $shipping_cost = $product['additional_shipping_cost'] * $product['cart_quantity'];
            }
        } 
		// increment the shipping total
        $total_shipping += $shipping_cost;
        return $total_shipping;
    }

 

I've tested the situation and it works regardless of the combinations of products you have in the cart. Free shipping, no free shipping, one or multiple products with additional shipping cost.

EDIT: Please note that the block of code below can also be inputed into the carrier.php to override the free shipping stuff PS does.

$shipping_cost + self::$price_by_price[$cache_key];


$price_by_price = Hook::exec('actionDeliveryPriceByPrice', array('id_carrier' => $id_carrier, 'order_total' => $order_total, 'id_zone' => $id_zone));
        if (is_numeric($price_by_price)) {
            self::$price_by_price[$cache_key] = $price_by_price;
        }
        //from here
        foreach ($products as $product) {
            
                $shipping_cost = $shipping_cost + ($product['additional_shipping_cost'] * $product['cart_quantity']);
            
        }
        $shipTax = $shipping_cost + self::$price_by_price[$cache_key];
        return $shipTax;

 

I tested this solution on PS 1.7.5 and it works for the cart but when completing order, in the success page where you see order summary, I don't see additional shipping fee for single product, instead I see free shipping if order subtotal is greater than threshold set for free shipping. Perhaps I have to add other changes in other classes, I don't know (I'm not a Prestashop programmer). Can you indicate if there are other sections in Prestashop classes where to check? 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...