Como permitir apenas um produto em um carrinho?

18

Temos um requisito, no qual um cliente poderá adicionar apenas um produto ao carrinho de cada vez. No entanto, ele / ela pode adicionar qualquer quantidade desse produto.

Como impedir que um produto seja adicionado ao carrinho se já houver um produto no carrinho?

Alguém pode ajudar nisso?

Shathish
fonte
11
Eu acho que é isso que você precisa: crearegroup-ecommerce.co.uk/blog/magento-tips/… A outra opção é reescrever a ação para adicionar um produto e disparar um evento personalizado checkout_cart_product_add_before lá, por exemplo markshust.com/2012/
08/27
@enenen: isso é legal, mas como posso impedir que o produto seja adicionado ao carrinho nesse observador?
Shathish 17/10/2013

Respostas:

20

Os eventos catalog_product_type_prepare_full_optionse catalog_product_type_prepare_lite_optionssão seus amigos

<?xml version="1.0"?>
<config>
    <modules>
        <Fooman_Example>
            <version>0.1.0</version>
        </Fooman_Example>
    </modules>
    <global>
        <models>
            <fooman_example>
                <class>Fooman_Example_Model</class>
            </fooman_example>
        </models>
        <helpers>
            <fooman_example>
                <class>Fooman_Example_Helper</class>
            </fooman_example>
        </helpers>
    </global>
    <frontend>
        <events>
            <catalog_product_type_prepare_full_options>
                <observers>
                    <fooman_example_catalog_product_type_prepare>
                        <class>Fooman_Example_Model_Observer</class>
                        <method>catalogProductTypePrepare</method>
                    </fooman_example_catalog_product_type_prepare>
                </observers>
            </catalog_product_type_prepare_full_options>
        </events>
    </frontend>
</config>

Então na sua classe Observer

<?php

class Fooman_Example_Model_Observer
{
    public function catalogProductTypePrepare($observer)
    {
        $quote = Mage::getSingleton('checkout/session')->getQuote();
        if($quote->getItemsCount()>=1){
            Mage::throwException('You can only buy one product at a time.');
        }
    }
}
Kristof na Fooman
fonte
catalog_product_type_prepare_lite_optionsé a primeira vez para mim! bem feito.
philwinkle
4
@philwinkle é muito útil para qualquer coisa antes de adicionar ao carrinho. Eu acho que isso é esquecido em muitas folhas de dicas, porque um grep normal apenas produz Mage :: dispatchEvent ($ eventName, faltando a linha anterior $ eventName = sprintf ('catalog_product_type_prepare_% s_options', $ processMode);
Kristof na Fooman
bem, que funcionou como um encanto.
Deepanshu Goyal
Fooman, é GRTS me
Amit Bera
8

Em vez de reescrever um controlador (por favor, oh, não faça isso), reescreva o addProductmétodo para considerar o limite:

class YourCompany_YourModule_Model_Cart extends Mage_Checkout_Model_Cart
{
    public function addProduct($productInfo, $requestInfo=null){
        if($this->getItemsCount()>1){
            Mage::throwException(Mage::helper('checkout')->__('Cannot add item - cart quantity would exceed checkout the limit of %s per person.', 1));
        }
        parent::addProduct($productInfo, $requestInfo);
    }
}

Se você quiser se divertir, substitua o item 1acima por Mage::getStoreConfig('checkout/options/max_cart_qty)e defina o seguinte config.xml do seu módulo:

<default>
    <checkout>
        <options>
            <max_cart_qty>1</max_cart_qty>
        </options>
    </checkout>
</default>

Agora esse valor é controlado pelo valor XML. Se você deseja ser realmente, realmente sofisticado , adicione isso ao system.xml do seu novo módulo:

<config>
    <sections>
        <checkout>
            <groups>
                <options>
                    <fields>
                        <max_cart_qty translate="label">
                            <label>Maximum Quantity Allowed in Cart (total qty)</label>
                            <frontend_type>text</frontend_type>
                            <sort_order>100</sort_order>
                            <show_in_default>1</show_in_default>
                        </max_cart_qty>
                    </fields>
                </options>
            </groups>
        </checkout>
    </sections>
</config>

Lembre-se de que você precisa definir um <depends>Mage_Checkout</depends>para o seu módulo, a fim de pegar carona na sua configuração de sistema predefinida.

philwinkle
fonte
Muito obrigado, sua resposta é "realmente chique", mas a resposta de Fooman estava alinhada com o que eu já estava tentando, então aceitei isso como resposta. Mas se eu não tivesse começado a usar observadores, teria usado seu método :).
Shathish
11
Claro! @fooman estava certo sobre - este foi educativa para mim também :)
philwinkle
2

Uma maneira possível é reescrever a addAction do Mage_Checkout_CartController.

Portanto, verifique se já existe um produto no carrinho e se sim, mostre uma mensagem de erro apropriada. Caso contrário, você pode chamar o método pai que está executando o processo de adição completo:

    if (count($this->_getCart()->getProductIds()) > 0) {
        $this->_goBack();
    } else {
        parent::addAction();
    }
Tobias
fonte
Me desculpe, $this->_goBack();não funciona! Entro na condição se, mas o produto ainda está sendo adicionado.
Shathish
O que acontece se você acabou de sair nesse ponto, apenas para depurar o que está realmente acontecendo, porque todo o processo addAction não deve ser executado
Tobias
dando saída naquele ponto sai a execução dando-me uma tela em branco
Shathish
mas adiciona o produto?
21313 Tobias
3
por favor, oh por favor, não reescrever controladores
philwinkle
1

Eu acho que você pode usar um observador e os seguintes eventos serão úteis para verificar as condições que você deseja. (Talvez alguns dos eventos não estejam na versão do Magento que você está usando).

checkout_cart_save_before

checkout_cart_product_add_after

checkout_cart_update_items_before

checkout_cart_update_items_after

checkout_cart_save_after
Sukeshini
fonte
Eu já estou tentando com o checkout_cart_product_add_afterevento, a questão é como posso impedir que o produto seja adicionado ao carrinho?
Shathish 17/10/2013
ou se já estiver adicionado, como removê-lo?
Shathish 17/10/2013
1

Talvez um pouco de uma idéia de campo esquerdo, mas que tal usar o catalog_product_is_salable_afterevento?

O que você pode fazer aqui é verificar se o produto está no carrinho ou se há outro produto no carrinho. Quando houver outro produto no carrinho, atualize o atributo 'is_salable' do objeto 'vendável' passado para o observador como false.

Observe que isso não foi testado e é apenas uma ideia. Ele falhará se o seu modelo não verificar$product->isSaleable()antes de exibir o botão. Também removeria apenas o botão e, na verdade, não interromperia o processo de adição se o usuário pudesse adivinhar o URL.

David Manners
fonte
1

Eu sei que este tópico é algo antigo, mas eu tive um problema semelhante. Quero apenas um item no carrinho e, se o cliente adicionar um novo, quero substituir o antigo pelo novo. Então, eu substituo o addAction (descrito aqui assim:

public function addAction(){
    $items = $this->_getCart()->getItems();
            foreach ($items as $item)
                    {
                            $itemId = $item->getItemId();
                            $this->_getCart()->removeItem($itemId);
                    }
    parent::addAction();

}

www.abo-killer.de
fonte