Есть ли способ обновить цены Magento * Catalog * (не Корзина) с помощью кода купона? - PullRequest
1 голос
/ 01 февраля 2011

В поисках ответа на вопрос, похожий на этот вопрос, и здесь, и в Google, я удивляюсь, что не смог найти ничего подобного.

Я знаком с группами клиентов иМногоуровневое ценообразование, но оно не соответствует цели, которую поставил мой клиент.

Мы хотим, чтобы пользователь пришел в наш магазин Magento и увидел обычную домашнюю страницу с обычными ценами.В этот момент мы хотим, чтобы в текстовое поле для пользователя добавлялся код купона, по которому сайт будет обновлять и отображать новые цены со скидкой, а обычная цена будет вычеркнута (или «урезана» каким-либо другим визуальным методом.

Группы клиентов / Многоуровневое ценообразование не являются решением, поскольку они требуют, чтобы клиент входил в систему. Группа NOT LOGGED IN также не помогла бы, поскольку все пользователи увидели бы скидку.

Этого не может бытьлибо в Корзине покупок, либо потому, что к тому времени уже слишком поздно, это должно произойти на уровне Каталога.

В настоящее время мы используем OSCommerce и вскоре переходим к Magento. Прямо сейчас, что мы делаем, чтобы эмулировать это поведениедля этого нужно иметь текстовое поле на нашем обычном веб-сайте на странице доступа к магазину, где пользователь может щелкнуть по региону или ввести код купона. ЕСЛИ они вводят код, они перенаправляются в специализированный магазин со специальными ценами.

Я знаю, что легко воссоздать наш текущий метод в Magento от Creati.В представлении магазина, а затем с использованием той же функциональности, но, кажется, стыдно делать это, когда идея перейти на новую платформу, которая намного более мощная.

Я не видел каких-либо расширений, которые делают это.Есть ли у кого-нибудь понимание того, можно ли добиться чего-то подобного, и если да, то как?

Ответы [ 2 ]

2 голосов
/ 01 февраля 2011

Мне любопытно, Джонатон, как ты это сделал, я не выбрал твой подход, мой немного сложнее.Мой действительно позволяет кому-то также разместить код купона в URL, и я установил cookie и все это для него.Я в основном настраиваю свою собственную форму в заголовке, которую пользователь может ввести в код купона, и он будет применяться, а также помещать купон в URL для кампаний по электронной почте.

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

Переопределите контроллер корзины и добавьте свое собственное действие.

 public function couponExternalPostAction()
{
        $quote =  $this->_getQuote();
        $couponCode = (string) $this->getRequest()->getParam('coupon_code');
        $validateCoupon = Mage::getModel('package_module/coupon');
        $json = $validateCoupon->addCouponCode($couponCode, $quote, $this->getRequest());

        echo $json;
        return;
}

Мне также пришлось переопределить couponPostAction (), чтобы все работало нормально, как обычно.

У меня есть addCouponметод в моей собственной модели

 public function addCouponCode($code, $quote, $request){
    $couponCode = (string) $code;
    $removed = false;

    if ($request->getParam('remove') == 1) {
        $couponCode = '';
        $removed = true;
    }

    $oldCouponCode = $quote->getCouponCode();

    /* No point in applying the rule again if it is the same coupon code that is in the quote */
    if ($couponCode === $oldCouponCode) {
        $json = $this->_getResponseJson($removed, $couponCode, $quote, false, true);
        return $json;
    }
    // Set the code get the rule base on validation even if it doesn't validate (false), which will also add it to the session,  then get our response
    $quote->setCouponCode(strlen($couponCode) ? $couponCode : '');
    $rule = $this->_validateCoupon($quote,$couponCode);
    // add coupon code to cookie, so we can delete from quote if the user closes their browser and comes back
    if($rule && !$removed){
        Mage::getModel('core/cookie')->set('coupon_code', $couponCode, 0, '/', null, null, null, false);
    }else{
       Mage::getModel('core/cookie')->delete('coupon_code');
    }
    $json = $this->_getResponseJson($removed, $couponCode, $quote, $rule);

    //See if the quote id is set  before saving
    $quoteId = $quote->getQuoteId();

    //Save the quote since everything has been set if not the data wont be set on page refresh
    $quote->save();

    //Set the quote id if it wasn't set before saving the quote. This makes sure we work off the same quote and a new one isn't created.
    if(empty($quoteId)){
        $this->_setQuoteId($quote);
    }

    return $json;
}

Проверка купона

 protected function _validateCoupon($quote,$couponCode){
    $store = Mage::app()->getStore($quote->getStoreId());
    $validator = Mage::getModel('package_module/validator');
    $validator->init($store->getWebsiteId(), $quote->getCustomerGroupId(), $quote->getCouponCode());

    return $validator->isValidExternalCode($couponCode, $quote->getShippingAddress(),false);
}

Я расширил Mage_SalesRule_Model_Validator с помощью собственной функции проверки

 public function isValidExternalCode($couponCode, $address, $setCoupon = true){
    foreach ($this->_getRules() as $rule) {
        if ($rule->getCode() && (in_array(strtolower($couponCode),explode(',',strtolower($rule->getCode()))))) {
            if($setCoupon){
                $address->setCouponCode($couponCode);
            }
            return $rule;
        }
    }
    return false;
}

Здесь я генерирую jsonответ

rotected function _getResponseJson($removed, $couponCode, $quote, $rule = false, $isDup = false){
    $json = '{"Response":{';
    if($removed){
        $json .= '"success":"Promotional code was cancelled successfully."';
        Mage::getSingleton('checkout/session')->setData('coupon_rule',null);
    }
    if(!$removed && $isDup){
        $json .= '"error":"' . $couponCode . ' is already applied"';
    }else if(!$removed && $rule){
        $json .= '"success":"Promotional code ' . $couponCode . ' has been applied",';
        $json .= '"couponMessage":"<span>' . $rule->getName() . '</span>"';
        Mage::getSingleton('checkout/session')->setData('coupon_rule','<span>' . $rule->getName() .'</span>');
    }else if(!$removed){
        $json .= '"error":"' . $couponCode . ' is not valid"';
        $quote->setCouponCode('');
    }
    $json .= '}}';
    return $json;
}

Мне также пришлось переопределить метод сбора в Mage_SalesRule_Model_Quote_Discount

public function collect(Mage_Sales_Model_Quote_Address $address)
{
    Mage_Sales_Model_Quote_Address_Total_Abstract::collect($address);
    $quote = $address->getQuote();
    $store = Mage::app()->getStore($quote->getStoreId());


    $eventArgs = array(
        'website_id'        => $store->getWebsiteId(),
        'customer_group_id' => $quote->getCustomerGroupId(),
        'coupon_code'       => $quote->getCouponCode(),
    );

    $this->_calculator->init($store->getWebsiteId(), $quote->getCustomerGroupId(), $quote->getCouponCode());

    $items = $address->getAllItems();
    /* EDITS
     * Moved the if statement for no items in cart down past these previous methods and then if the address type is shipping and the coupon is set
     * add the coupon code to the address to allow the validation to still pick up the coupon code
     */
    if($quote->getCouponCode() && ($address->getAddressType() == Mage_Sales_Model_Quote_Address::TYPE_SHIPPING)){
        $address->setCouponCode($quote->getCouponCode());
    }
    if (!count($items)) {
        return $this;
    }

    $address->setDiscountDescription(array());

    foreach ($items as $item) {
        if ($item->getNoDiscount()) {
            $item->setDiscountAmount(0);
            $item->setBaseDiscountAmount(0);
        }
        else {
            /**
             * Child item discount we calculate for parent
             */
            if ($item->getParentItemId()) {
                continue;
            }

            $eventArgs['item'] = $item;
            Mage::dispatchEvent('sales_quote_address_discount_item', $eventArgs);

            if ($item->getHasChildren() && $item->isChildrenCalculated()) {
                foreach ($item->getChildren() as $child) {
                    $this->_calculator->process($child);
                    $eventArgs['item'] = $child;
                    Mage::dispatchEvent('sales_quote_address_discount_item', $eventArgs);
                    $this->_aggregateItemDiscount($child);
                }
            } else {
                $this->_calculator->process($item);
                $this->_aggregateItemDiscount($item);
            }
        }
    }

    /**
     * Process shipping amount discount
     */
    $address->setShippingDiscountAmount(0);
    $address->setBaseShippingDiscountAmount(0);
    if ($address->getShippingAmount()) {
        $this->_calculator->processShippingAmount($address);
        $this->_addAmount(-$address->getShippingDiscountAmount());
        $this->_addBaseAmount(-$address->getBaseShippingDiscountAmount());
    }

    $this->_calculator->prepareDescription($address);
    return $this;
}
1 голос
/ 01 февраля 2011

Это определенно может быть достигнуто. Он включает в себя написание пользовательского модуля (начало здесь и здесь ) с контроллером, который принимает значение поля вашего купона, инициирует сеанс проверки для этого пользователя ($session = Mage::getSingleton('checkout/session')) и сохраняет код купона в кассе ($session->setData('coupon_code',$coupon).

Затем вы расширите модель цены, чтобы проверить код купона в сеансе. Вы можете переопределить Mage_Catalog_Model_Product_Type_Price в своем собственном модуле, используя синтаксис <rewrite>. Получите код купона ($couponCode = Mage::getSingleton("checkout/session")->getData("coupon_code");). Обратите внимание, что объект Price отличается для Bundle и других непростых типов продуктов.

Если вам нужна дополнительная информация, я могу выложить примеры кода.

...