For a specific product I've got a Shopping Cart Rule which makes shipping for it free. It would be logical to not show shipping information and bypass shipping method selection for such product. Is there any easy way to do this?
Asked
Active
Viewed 2,821 times
0
-
It wouldn't make sense to skip the shipping address field as it is a physical product, right? I can see the desire to skip shipping method selection if you have a single option and it is free shipping. Do you have a use case where you have options other than free? – Lee Saferite Sep 01 '11 at 11:27
-
Yes there are lot's of options, but some products just have to have free shipping and it would be nice if we could remove any mentioning of shipping thing from checkout process for such products. – jayarjo Sep 02 '11 at 06:53
1 Answers
4
This can be easily accomplished with an extension module.
/app/etc/modules/YourCompany_SkipShipping.xml
<?xml version="1.0"?>
<config>
<modules>
<YourCompany_SkipShipping>
<active>true</active>
<codePool>local</codePool>
<depends>
<Mage_Checkout />
</depends>
</YourCompany_SkipShipping>
</modules>
</config>
/app/code/local/YourCompany/SkipShipping/etc/config.xml
<?xml version="1.0"?>
<config>
<modules>
<YourCompany_SkipShipping>
<version>0.0.1</version>
</YourCompany_SkipShipping>
</modules>
<frontend>
<routers>
<checkout>
<modules before="Mage_Checkout">YourCompany_SkipShipping<modules>
</checkout>
</routers>
</frontend>
</config>
/app/code/local/YourCompany/SkipShipping/controllers/OnepageController.php
<?php
include "Mage/Checkout/controller/OnepageController.php"
class YourCompany_SkipShippingMethod_OnepageController
extends Mage_Checkout_OnepageController
{
public function saveBillingAction()
{
if ($this->_expireAjax()) {
return;
}
if ($this->getRequest()->isPost()) {
$data = $this->getRequest()->getPost('billing', array());
$customerAddressId = $this->getRequest()->getPost('billing_address_id', false);
if (isset($data['email'])) {
$data['email'] = trim($data['email']);
}
$result = $this->getOnepage()->saveBilling($data, $customerAddressId);
if (!isset($result['error'])) {
/* check quote for virtual */
if ($this->getOnepage()->getQuote()->isVirtual()) {
$result['goto_section'] = 'payment';
$result['update_section'] = array(
'name' => 'payment-method',
'html' => $this->_getPaymentMethodsHtml()
);
} elseif (isset($data['use_for_shipping']) && $data['use_for_shipping'] == 1) {
$method = $this->getAutoShippingMethod($data, $customerAddressId);
if (!empty($method)) {
$result = $this->getOnepage()->saveShippingMethod($method);
if(!$result) {
Mage::dispatchEvent('checkout_controller_onepage_save_shipping_method', array(
'request'=>$this->getRequest(),
'quote'=>$this->getOnepage()->getQuote()
));
$result['goto_section'] = 'payment';
$result['update_section'] = array(
'name' => 'payment-method',
'html' => $this->_getPaymentMethodsHtml()
);
}
} else {
$result['goto_section'] = 'shipping_method';
$result['update_section'] = array(
'name' => 'shipping-method',
'html' => $this->_getShippingMethodsHtml()
);
$result['allow_sections'] = array('shipping');
$result['duplicateBillingInfo'] = 'true';
}
} else {
$result['goto_section'] = 'shipping';
}
}
$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
}
}
public function saveShippingAction()
{
if ($this->_expireAjax()) {
return;
}
if ($this->getRequest()->isPost()) {
$data = $this->getRequest()->getPost('shipping', array());
$customerAddressId = $this->getRequest()->getPost('shipping_address_id', false);
$result = $this->getOnepage()->saveShipping($data, $customerAddressId);
if (!isset($result['error'])) {
$method = $this->getAutoShippingMethod($data, $customerAddressId);
if (!empty($method)) {
if(!$result) {
Mage::dispatchEvent('checkout_controller_onepage_save_shipping_method', array(
'request'=>$this->getRequest(),
'quote'=>$this->getOnepage()->getQuote()
));
$result['goto_section'] = 'payment';
$result['update_section'] = array(
'name' => 'payment-method',
'html' => $this->_getPaymentMethodsHtml()
);
}
} else {
$result['goto_section'] = 'shipping_method';
$result['update_section'] = array(
'name' => 'shipping-method',
'html' => $this->_getShippingMethodsHtml()
);
}
}
$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
}
}
public function getAutoShippingMethod($data, $customerAddressId)
{
// This is where you put your code to process the cart/order for orders that can auto-select shipping method
// For now, skip
return '';
}
}
I'll leave the specifics of how you check the shipping method to you, but if you cannot figure it out, post a comment and I'll add that as well.
NB: All examples are based on Magento 1.5

Lee Saferite
- 3,124
- 22
- 30
-
Btw, just a question to you as Magento developer (you are the one I bet) do you find such approach to extending core functionality convenient or at least acceptable? I mean don't you think that one has to write too much to achieve so little in Magento? And what happens if other modules extend the same code? Is there any conflict resolution system for such cases? – jayarjo Sep 03 '11 at 10:10
-
1The way this particular extension works, there should be little to no problem. The only problem I could see is if another module wanted to change the billing or shipping action behaviour. Do I think it's a lot of work for a small task? Yes and no. It's a complex task with lots of edge cases. I think Magento makes tapping into code to solve some of those easy while others are very hard. In any case, as it matures it adds more places that making changes is easy. – Lee Saferite Sep 03 '11 at 16:13
-
1In this case, it would have been MUCH easier if they fired events after processing but before returning the result. Then we could just listen for an event and make the modifications there. It would have been very unobtrusive and mix well with other modules as the coupling would have been very low. – Lee Saferite Sep 03 '11 at 16:14