Программно установить бесплатную доставку от наблюдателя
Я программирую модуль, в котором мне нужно установить бесплатную доставку, если выполняются определенные условия. Эти условия очень специфичны и не могут быть смоделированы с использованием "Правил цены корзины покупок". Логика определения того, должен ли пользователь получать бесплатную доставку, выполнена, но я не знаю, как на самом деле сделать доставку бесплатной. Я пробовал это:
$address = $quote->getShippingAddress();
$address->setFreeShipping(true);
Я вызываю это из обработчика событий checkout_cart_update_items_after
Он основан на продажах бесплатной доставки правило, которое работает с переменной данных free_shipping
. Однако это не работает. После обновления корзины стоимость доставки остается ненулевой.
Я также пробовал это:
$address = $quote->getShippingAddress();
$address->setShippingMethod('freeshipping_freeshipping');
Это работает, но проблема в том, что для этого в бэкэнде должна быть включена бесплатная доставка. Это означает, что пользователь может забрать его при оформлении заказа в любое время - даже если он не должен получать бесплатную доставку в соответствии с моими условиями.
Есть ли какой-нибудь хороший способ установить бесплатную доставку от наблюдателя (обработчика событий)?
2 answers
Итак, вот как я это сделал.
Во-первых, я использовал более подходящее событие для этой цели, то есть sales_quote_collect_totals_before
. И во-вторых, мне нужно было прокомментировать (в локальной копии, конечно) одну строку в Mage_SalesRule_Model_Quote_Freeshipping:
public function collect(Mage_Sales_Model_Quote_Address $address)
{
parent::collect($address);
$quote = $address->getQuote();
$store = Mage::app()->getStore($quote->getStoreId());
//$address->setFreeShipping(0); # clime: we set this in module
...
}
Вот и все. Теперь хорошо работает следующее:
$address = $quote->getShippingAddress();
$address->setFreeShipping(true); # the value must be true, not 1
Он хорошо работает в режиме одиночной доставки. Множественная доставка, вероятно, потребует некоторых корректировок.
Вы хотите пропустить указание способа доставки?
Если да, переопределите контроллер одной страницы и переопределите следующие функции вместо (в public function saveBillingAction()
):
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) {
$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';
}
}
Вставьте этот код:
if (!isset($result['error'])) {
if($data['use_for_shipping'] != 0){
$method = 'freeshipping_freeshipping';
$result = $this->getOnepage()->saveShippingMethod($method);
}
if (!isset($result['error'])) {
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) {
$result['goto_section'] = 'payment';
$result['update_section'] = array(
'name' => 'payment-method',
'html' => $this->_getPaymentMethodsHtml()
);
$result['allow_sections'] = array('shipping');
$result['duplicateBillingInfo'] = 'true';
} else {
$result['goto_section'] = 'shipping';
}
}
}
И в public function saveShippingAction()
добавьте это:
if (!isset($result['error'])) {
$method = 'freeshipping_freeshipping';
$result = $this->getOnepage()->saveShippingMethod($method);
if (!isset($result['error'])) {
$result['goto_section'] = 'payment';
$result['update_section'] = array(
'name' => 'payment-method',
'html' => $this->_getPaymentMethodsHtml()
);
}
}
Вместо этого:
if (!isset($result['error'])) {
$result['goto_section'] = 'shipping_method';
$result['update_section'] = array(
'name' => 'shipping-method',
'html' => $this->_getShippingMethodsHtml()
);
}