Display cheapest shipping method from same carrier

  • Posts: 128
  • Thank you received: 3
8 years 8 months ago #234191

-- HikaShop version -- : 2.5.0
-- Joomla version -- : 3.4.1
-- PHP version -- : 5.3.24

I have created 3 UPS shipping methods with varying restrictions because of some of my products' dimensions, products' weights, and shipping box dimensions. When adding different products sometimes I have shipping methods overlap, which means I have 2 UPS shipping methods display for the order.



I'm going to have Fedex methods with the same restrictions, so I'll have the same problem with them. I was wanting to know if there is a way to only return the cheapest method from each carrier?

Attachments:
Last edit: 8 years 8 months ago by deuce4884.

Please Log in or Create an account to join the conversation.

  • Posts: 12953
  • Thank you received: 1778
8 years 7 months ago #234208

Hello,

The solution will just be to use restrictions like Maximum/Minimum :
- Price
- Weight
- Dimensions
- ..

So that you can filter which shipping method you want to be available and in which situation. So the solution will globally depends on how and when you want your shipping method to be displayed.

Last edit: 8 years 8 months ago by Mohamed Thelji.

Please Log in or Create an account to join the conversation.

  • Posts: 128
  • Thank you received: 3
8 years 7 months ago #234328

I understand the purpose of the restrictions and I'm using all of them on all 3 shipping methods. However, the because of the different dimensions, different weights, my shipping box dimensions, and the fact that due to weight limits on carrier services I have some overlap on the restrictions of the shipping methods. I added some javascript to the checkout->shipping view as a way to try to just hide the more expensive prices of the same methods.

$js = "
//function to only show cheapest carrier rates if overlap
function findMinRates(){
	var minRates = [];	
	jQuery('.hikashop_shipping_group').each(function(){
		var jQuerythis = jQuery(this);
		jQuerythis.find('.controls .hika-radio.hikashop_shipping_methods_table tr td input.hikashop_checkout_shipping_radio').each(function(){
			var shipType = this.next('label').html();
			var shipPrice = this.next('span.hikashop_checkout_shipping_price_full').children('span.hikashop_checkout_shipping_price').html();
			shipPrice = parseFloat(shipPrice);
			if(shipType in minRates){
				if(shipPrice > minRates[shipType]){
					jQuery('input.hikashop_checkout_shipping_radio[value=\"this.val()\"]').parents('tr[class^=\"row\"]').hide();
				}
                        }else{
			         minRates[shipType]=shipPrice;
			}
		});
	});
}
//function for window ready
window.hikashop.ready(function(){findMinRates();});
";

	if(!HIKASHOP_PHP5)
		$doc =& JFactory::getDocument();
	else
		$doc = JFactory::getDocument();

	$doc->addScriptDeclaration("\n<!--\n".$js."\n//-->\n");

I'm not getting any results with this though. Am I on the right track with this or is there a way to do what I need to do directly in the php code of the view?

Last edit: 8 years 7 months ago by deuce4884.

Please Log in or Create an account to join the conversation.

  • Posts: 82863
  • Thank you received: 13372
  • MODERATOR
8 years 7 months ago #234365

Hi,

You can edit the file "shipping" of the view "checkout" via the menu Display>Views. It's that view file which displays the shipping methods. So there, you can filter the shipping methods the way you want.

Please Log in or Create an account to join the conversation.

  • Posts: 128
  • Thank you received: 3
8 years 7 months ago #234379

I think I got this figured out. I found the code:

foreach($this->rates as $rate) {

and replaced with:
$min_rates = array();
foreach($this->rates as $rate) {
	if(array_key_exists($rate->shipping_name,$min_rates)){
		if($rate->shipping_price < $min_rates[$rate->shipping_name]){
			$min_rates[$rate->shipping_name]= $rate->shipping_price;
		}else{
			continue;
		}
	}else{
		$min_rates[$rate->shipping_name]= $rate->shipping_price;
	}

This seems to only show the cheapest shipping method for each carrier if there is any overlap on the restrictions. Do you see any problems that this code could cause? As far as I can tell it's working.

Please Log in or Create an account to join the conversation.

  • Posts: 82863
  • Thank you received: 13372
  • MODERATOR
8 years 7 months ago #234385

Hi,

It's not ideal but it's ok. Ideally, you should do a first foreach on $this->rates to construct your own filters list of rates and then replace $this->rates with your list and then leave the second foreach do it's job on that filtered list.
Because right now with your code, if the first encountered rate has a higher price than the second rate with the same name, you'll actually see both displayed. You're lucky that they are being displayed in the order that works :)

Please Log in or Create an account to join the conversation.

  • Posts: 128
  • Thank you received: 3
8 years 7 months ago #234437

I tried working on this by adding an extra foreach like you mentioned, but I'm losing something. I've not done anything quite like this before. This is what I have now:

$min_rates = array();
		foreach($this->rates as $min_rate) {
			if(array_key_exists($min_rate->shipping_name,$min_rates)){
				if($min_rate->shipping_price < $min_rates[$min_rate->shipping_name]){
					$min_rates[$min_rate->shipping_name]= $min_rate->shipping_price;
				}else{
					continue;
				}
			}else{
				$min_rates[$min_rate->shipping_name]= $min_rate->shipping_price;
			}
			foreach($min_rates as $rate) {
                           ......existing code

I then added a closing } for the extra foreach after:
				<div class="hikashop_checkout_shipping_description"><?php echo $rate->shipping_description;?></div>
			</td>
		</tr>
<?php

		$k = 1-$k;
	}
}   //added this closing for extra foreach

Now nothing is showing. I believe it has something to do with I'm losing values through the first foreach. Can you help me fix this?

Please Log in or Create an account to join the conversation.

  • Posts: 82863
  • Thank you received: 13372
  • MODERATOR
8 years 7 months ago #234438

Hi,

You've added the second foreach instead the first one. What I was saying was to have two separate foreach one after the other.

Please Log in or Create an account to join the conversation.

  • Posts: 128
  • Thank you received: 3
8 years 7 months ago #234515

I reworked my code to the following:

$min_rates = array();
            foreach($this->rates as $min_rate) {
                if(array_key_exists($min_rate->shipping_name,$min_rates)){
                    if($min_rate->shipping_price < $min_rates[$min_rate->shipping_name]->shipping_price){
                        $min_rates[$min_rate->shipping_name]= $min_rate;
                    }else{
                        continue;
                    }
                }else{
                    $min_rates[$min_rate->shipping_name]= $min_rate;
                }
			}
            foreach($min_rates as $rate) {
              .......existing code

I believe I have it working correctly now. I switched the order of the shipping plugins and added a new cheaper plugin with some of the same restrictions and it seems to be retrieving the cheapest of each method for each carrier now.

Please Log in or Create an account to join the conversation.

Time to create page: 0.087 seconds
Powered by Kunena Forum