Tags/topics: 
15
Answers
Vote up!
1
Vote down!

How to hide checkout panes based on shipping method?

I have 4 shipping methods(Flat rate) and 2 custom shipping information panes(Commerce Fieldgroup Panes).

So I am trying to do something like this:
1. Method one - Show default shipping information pane, hide other shipping information panes.
2. Method two - Show custom shipping information pane for Method two and hide other shipping information panes.
3. Method three - Show custom shipping information pane for Method three and hide other shipping information panes.
4. Method four - Hide all shipping information panes.

How to do it?

As I understand, there is no option to use rules for hiding and showing panes based on shipping method? I think, it is very much needed functionality. Why do write custom module for simple task like this if I could do it with rules?

As I can't use rules for this functionality, I try to do it with custom module, but my programming skills are not good enough for this.
I hoped to get this code working, but no luck:
Code from: http://drupal.org/node/1285902

<?php
/*
* Hook hook_commerce_checkout_pane_info_alter($checkout_pane)
*/
function mymodule_commerce_checkout_pane_info_alter(&$checkout_pane) {
    global
$user;
   
// $checkout_pane actually holds ALL the panes...
   
foreach($checkout_pane as $pane_name => &$pane_data) {
       
// ...we only need to override one of them
       
if($pane_name == 'customer_profile_shipping' && $pane_data['enabled']) {
           
// load current order
           
$order = commerce_cart_order_load($user->uid);
           
// array $order->data was detected with dsm()
            // it doesn't contain anything except 'shipping_method' string element
            // rules_pick_up is the ID of a cloned flat_rate shipping method
           
if($order->data['shipping_method'] == 'flat_rate|rules_pick_up') {
               
// the pane is enabled by default, so we need to disable it
               
$pane_data['enabled'] = 0;
            }
        }
    }
}
?>

It gives me error:

Notice: Undefined index: shipping_method in mymodule_commerce_checkout_pane_info_alter() (line 34 of ............./sites/all/modules/mymodule/mymodule.module). Backtrace:

mymodule_commerce_checkout_pane_info_alter(Array, NULL, NULL) module.inc:1022
drupal_alter('commerce_checkout_pane_info', Array) commerce_checkout.module:494
commerce_checkout_panes(Array) commerce_checkout.module:402
commerce_checkout_pages() commerce_checkout.module:287
commerce_checkout_commerce_order_status_info()
call_user_func_array('commerce_checkout_commerce_order_status_info', Array) module.inc:823
module_invoke_all('commerce_order_status_info') commerce_order.module:1103
commerce_order_statuses(Array) commerce_cart.module:678
commerce_cart_order_is_cart(Object) commerce_cart.module:534
commerce_cart_commerce_order_load(Array)
call_user_func_array('commerce_cart_commerce_order_load', Array) entity.inc:334
DrupalDefaultEntityController->attachLoad(Array, ) commerce_order.controller.inc:121
CommerceOrderEntityController->attachLoad(Array, ) entity.inc:204
DrupalDefaultEntityController->load(Array, Array) common.inc:7623
entity_load('commerce_order', Array, Array, ) commerce_order.module:775
commerce_order_load_multiple(Array, Array) commerce_order.module:744
commerce_order_load('1') menu.inc:592
_menu_load_objects(Array, Array) menu.inc:759
_menu_translate(Array, Array) menu.inc:471
menu_get_item() menu.inc:1751
menu_get_custom_theme(1) menu.inc:1766
menu_set_custom_theme() common.inc:5043
_drupal_bootstrap_full() bootstrap.inc:2186
drupal_bootstrap(7) index.php:20

Can you please help me get this code working or write better one? :)

Asked by: UrmasZ
on June 17, 2012

15 Answers

Vote up!
4
Vote down!

I got it working.

Problem is that $order->data is empty, there is nothing to check. So to get this code working I needed something else to check. For example $order->commerce_order_total. It contains shipping method that user picked.

So working code is:

<?php
/*
* Hook hook_commerce_checkout_pane_info_alter($checkout_pane)
*/
function mymodule_commerce_checkout_pane_info_alter(&$checkout_pane) {
    global
$user;
   
// $checkout_pane actually holds ALL the panes...
   
foreach($checkout_pane as $pane_name => &$pane_data) {
       
// ...we only need to override one of them
       
if($pane_name == 'customer_profile_shipping' && $pane_data['enabled']) {
           
// load current order
           
$order = commerce_cart_order_load($user->uid);
           
// array $order->data was detected with dsm()
            // it doesn't contain anything except 'shipping_method' string element
            // rules_pick_up is the ID of a cloned flat_rate shipping method
           
if($order->commerce_order_total['und']['0']['data']['components']['2']['name'] == 'flat_rate_pick_up') {
               
// the pane is enabled by default, so we need to disable it
               
$pane_data['enabled'] = 0;
            }
        }
    }
}
?>

Next to components is number 2 because 0 is subtotal, 1 is tax and 2 is shipping method. If I remember correctly. I need to check shipping method, so I use number 2. Of course you can check all of them for just in case. You also need to enable the pane if customer did not chose the pick up.

I am sure there is much batter way to do it, but I don't know one and this one does what I need. :)
Of course my result code is more complicated. Here I just fixed this code.

Still it would be nice to do it with rules. :) It would be soooooo easy to implement that kind shipping methods.

Answer by: UrmasZ
Posted: Jul 13, 2012
Vote up!
1
Vote down!

If I say shipping method, I mean shipping service. :)

If you do not use taxes, then you have to change number 2 to number 1. So in you result code you might want to check does 0 or 1 or 2 or 3 contain this flat rate. I mean check all of them, not only one.

1. Shipping services are on first page and shipping information should be on next page.
2. Should be correct.
3. If you crate flat rate shipping service called Pick up(Machine name: pick_up), then in code you have to use flat_rate_pick_up. If you crate flat rate shipping service called Whatever, then in code you use flat_rate_whatever. You have to add flat_rate_ at the beginning in code, not when creating a flat rate shipping service. :)

Answer by: UrmasZ
Posted: Jul 18, 2012

Comments

I just added commerce coupon and that throw my number off as well. Just another FYI to watch out for.

- switch on July 30, 2012
Vote up!
0
Vote down!

Install Devel module and learn to use dsm(). It is very helpful. Or dpm() - "A note from the devel module: dsm() is a legacy function that was poorly named; use dpm() instead, since the 'p' maps to 'print_r'. http://drupal.org/node/174575".

Use it in your module like this:
dpm($order->commerce_order_total); and see what it contains.
If you use dpm($order->data); you should see that this is empty and that's the reason original code is not working.
Or if you use dpm($order); you should see data and commerce_order_total and everything else that this order contains.

Answer by: UrmasZ
Posted: Jul 18, 2012
Vote up!
0
Vote down!

Awesome! Thanks UrmasZ!!! I had Devel installed but dsm wasn't working for the module I created for this...until I disabled then re-enabled my module.

Then I was getting the error: Notice: Undefined index: 2
I used dsm($order), now switching to dpm() thank you :), and I was able to navigate down the tree till i got to the 2 in your: commerce_order_total['und']['0']['data']['components']['2']['name'] and as you said above, since i wasn't using taxes I switched the ['2'] to a ['1'] and it worked!

I was also not able to view my checkout page on my local and it was giving me a "The connection was reset" error. I just had to comment out the dpm() and it came up.

From all my reading on this subject, I thought the Shipping Page wasn't supposed to show up if there were no panes enabled on it. My Shipping Page is still showing up.

Did you have this problem?

Answer by: switch
Posted: Jul 19, 2012
Vote up!
0
Vote down!

I am using Billing Information pane(Using pick up shipping service I can use this for reserving product.) on Shipping page also, so this page is never empty for me. So this is no problem for me. But I disabled Billing Information pane for testing now and have same problem. But like I said, I do not have this page ever empty, so I do not care about this problem. :D
But considering that if there is no panes on that page, it should be disabled. Skipped. So this problem is bit strange. Maybe you need some other hook that disables or skips this page. I am not going to investigate that. :)

Answer by: UrmasZ
Posted: Jul 21, 2012
Vote up!
0
Vote down!

I'll move my Billing info over there too. Weird that checkout page skip doesn't work though.

Answer by: Anonymous (not verified)
Posted: Jul 26, 2012
Vote up!
0
Vote down!

@UrmasZ, with this code, have you gotten the error:
Notice: Undefined index: 2 in my_module_commerce_checkout_pane_info_alter()
(I know your index is different) when you you first log on to a site and nothing is in your cart?

I dpm()'d it and the only thing that shows up in the components is the base_price.

Do you have some sort of error handling for that?

Thanks!
=>switch<=

Answer by: switch
Posted: Aug 2, 2012
Vote up!
0
Vote down!

Think I got it. check out the revised code:

/*
* Hook hook_commerce_checkout_pane_info_alter($checkout_pane)
*/
function my_module_commerce_checkout_pane_info_alter(&$checkout_pane) {
    global $user;
    // $checkout_pane actually holds ALL the panes...
    foreach($checkout_pane as $pane_name => &$pane_data) {
        // ...we only need to override one of them
        if($pane_name == 'customer_profile_shipping' && $pane_data['enabled']) {
            // load current order
            $order = commerce_cart_order_load($user->uid);
            // flat_rate_pick_up is the ID of a cloned flat_rate shipping method
                        //make sure there is an order
if ($order!=false && !empty($order->commerce_line_items)) {
                                //check through the components so we don't have to hard code a number
foreach($order->commerce_order_total['und']['0']['data']['components'] as $order_component => &$component_data) {
                                        //hide the shipping info if it's pickup and show for the other shipping services
if($component_data['name'] == 'flat_rate_pick_up'){
$pane_data['enabled'] = 0;
}else if($component_data['name'] == 'flat_rate_delivery_charge'){
$pane_data['enabled'] = 1;
}else if($component_data['name'] == 'flat_rate_delivery'){
$pane_data['enabled'] = 1;
}
}
}

        }

    }
}
Answer by: switch
Posted: Aug 6, 2012
Vote up!
0
Vote down!

Didn't work for me :'-(

Answer by: Anonymous (not verified)
Posted: Sep 18, 2012
Vote up!
0
Vote down!

sorry, but i've to create a new module? were exactly?

Answer by: Anonymous (not verified)
Posted: Oct 9, 2012
Vote up!
0
Vote down!

Guys, another option would be to use http://drupal.org/project/customer_profile_type_ui

It gives some rules to enable and disable customer profile types too. You can not disable all panes with it, but you can disable and enable billing and shipping panes with rules. And if you make another customer profile types with it, you can enable and disable them too. So there is actually no need to write a module for "pick up" shipping method. :)

I have added two custom profile types too to collect information for another two shipping methods.
So with this module I can do what I wanted to do in the first place - 3 custom shipping methods without having to write any custom modules. Too bad I did not try this module sooner. :D

Answer by: UrmasZ
Posted: Oct 22, 2012

Comments

Hi,

that's a good module for this purpose, but you can show/hide panes on select shipping service event?

I can't have this working.

Thanks

- bessone on November 15, 2012
Vote up!
0
Vote down!

Dependent shipping module doesn't work for me. I don't have experience on module development but this seems to be a simple task to complete. Could you please explain what changes should I make to that script in order to hide shipping information for my "pick up from store" shipping service option?

Answer by: Anonymous (not verified)
Posted: Nov 1, 2012
Vote up!
-1
Vote down!

You might re-consider what you are trying to do with your shipping methods or find someone who is willing to write some of this logic into a module (developers need to eat, too).

Josh Miller
Answer by: Josh Miller
Posted: Jul 5, 2012

Comments

Hi Josh,
I don't mean to offend you but this is not a very constructive comment. You basically told him to go hire someone. I would like to see this method built out more. I look forward to his findings and will try to contribute where I can.
Pete

- switch on July 16, 2012

Not offended. I always try to give some form of answer to every question. Very glad to see there was a better answer given below :D

- Josh Miller on August 14, 2012
Vote up!
-1
Vote down!

Hey UrmasZ, thanks very much for this! In the first paragraph below the code, did you mean that number 2 was the shipping service and not shipping method? And that you created a flat rate shipping service called flat_rate_pick_up?

I still can't get this to work.

1. I moved the shipping info pane to the 2nd checkout page. And that's the only thing I have on that page.
2. Created a shipping service from the flat rate shipping method that has a base rate of $0 called pick_up
3. Created a custom module called pickup_or_delivery, pasted your code in there and changed the name of the function to match my module name as well as changed the name of the shipping service in your if statement to pick_up (the name of the flat rate shipping service I created).

Since I'm new to coding modules I'm probably off there somewhere but I can't figure it out. I can't even get anything to come up with dsm($checkout_pane); in my function.

Did you have any issues around this? Or can you see anything I might have missed?

Thanks so much for all your help UrmasZ!

Pete

Answer by: switch
Posted: Jul 16, 2012