Программно установить бесплатную доставку от наблюдателя


Я программирую модуль, в котором мне нужно установить бесплатную доставку, если выполняются определенные условия. Эти условия очень специфичны и не могут быть смоделированы с использованием "Правил цены корзины покупок". Логика определения того, должен ли пользователь получать бесплатную доставку, выполнена, но я не знаю, как на самом деле сделать доставку бесплатной. Я пробовал это:

$address = $quote->getShippingAddress();
$address->setFreeShipping(true);

Я вызываю это из обработчика событий checkout_cart_update_items_after

Он основан на продажах бесплатной доставки правило, которое работает с переменной данных free_shipping. Однако это не работает. После обновления корзины стоимость доставки остается ненулевой.

Я также пробовал это:

$address = $quote->getShippingAddress();
$address->setShippingMethod('freeshipping_freeshipping');

Это работает, но проблема в том, что для этого в бэкэнде должна быть включена бесплатная доставка. Это означает, что пользователь может забрать его при оформлении заказа в любое время - даже если он не должен получать бесплатную доставку в соответствии с моими условиями.

Есть ли какой-нибудь хороший способ установить бесплатную доставку от наблюдателя (обработчика событий)?

Author: clime, 2013-05-12

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

Он хорошо работает в режиме одиночной доставки. Множественная доставка, вероятно, потребует некоторых корректировок.

 7
Author: clime, 2013-05-15 22:58:08

Вы хотите пропустить указание способа доставки?

Если да, переопределите контроллер одной страницы и переопределите следующие функции вместо (в 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()
    );
}
 1
Author: Shathish, 2016-04-19 07:51:27