¿Cómo permitir solo un producto en un carrito?

18

Tenemos un requisito, en el que un cliente podrá agregar solo un producto al carrito a la vez. Sin embargo, él / ella puede agregar cualquier cantidad de ese producto.

¿Cómo puedo evitar que un producto se agregue al carrito si ya hay un producto presente en el carrito?

¿Alguien puede ayudar en esto?

Shathish
fuente
1
Creo que esto es lo que necesita: crearegroup-ecommerce.co.uk/blog/magento-tips/… La otra opción es reescribir la acción para agregar un producto y activar un evento personalizado checkout_cart_product_add_before allí, por ejemplo markshust.com/2012/
27/08
@enenen: eso es genial, pero ¿cómo puedo evitar que el producto se agregue al carrito en ese observador?
Shathish

Respuestas:

20

Los eventos catalog_product_type_prepare_full_optionsy catalog_product_type_prepare_lite_optionsson tus 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>

Luego en tu clase de observador

<?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 en Fooman
fuente
catalog_product_type_prepare_lite_optionses el primero para mi! bien hecho.
philwinkle
44
@philwinkle es muy útil para cualquier cosa antes de agregar al carrito. Creo que se pierde de muchas hojas de trucos porque un grep normal solo produce Mage :: dispatchEvent ($ eventName, falta la línea anterior $ eventName = sprintf ('catalog_product_type_prepare_% s_options', $ processMode);
Kristof en Fooman el
bueno, eso funcionó a las mil maravillas.
Deepanshu Goyal
Fooman, es mi amor
Amit Bera
8

En lugar de reescribir un controlador (por favor, oh, no hagas eso), más bien, reescribe el addProductmétodo para tener en cuenta el límite:

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);
    }
}

Si quieres ponerte elegante, reemplaza lo 1anterior con Mage::getStoreConfig('checkout/options/max_cart_qty)y configura lo siguiente config.xml de tu módulo:

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

Ese valor ahora se controla a través del valor XML. Si quieres ponerte realmente sofisticado , agrega esto al system.xml de tu nuevo 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>

Recuerde que debe configurar <depends>Mage_Checkout</depends>a su módulo para aprovechar su configuración de sistema predefinida.

philwinkle
fuente
Muchas gracias, su respuesta es "realmente elegante", pero la respuesta de Fooman estaba en línea con lo que ya estaba intentando, así que acepté eso como respuesta. Pero si no hubiera comenzado a usar observadores, habría usado tu método :).
Shathish
1
¡Por supuesto! @fooman estaba en lo cierto - esto también fue educativo para mí :)
philwinkle
2

Una forma posible es reescribir el addAction de Mage_Checkout_CartController.

Por lo tanto, compruebe si ya hay un producto en el carrito y, en caso afirmativo, muestre un mensaje de error apropiado. Si no, puede llamar al método principal que está haciendo el proceso de adición completo:

    if (count($this->_getCart()->getProductIds()) > 0) {
        $this->_goBack();
    } else {
        parent::addAction();
    }
Tobias
fuente
Lo siento, $this->_goBack();no funciona! Entro en la condición if pero el producto todavía se está agregando.
Shathish
¿Qué sucede si acaba de salir en ese punto, solo para depurar lo que realmente está sucediendo, porque todo el proceso addAction no debe ejecutarse
Tobias
dar salida en ese punto sale de la ejecución y me da una pantalla en blanco
Shathish
pero agrega el producto?
Tobias
3
por favor, oh por favor no reescriba los controladores
philwinkle
1

Creo que puede usar un observador y los siguientes eventos serán útiles para verificar las condiciones que desee. (Quizás algunos de los eventos no estén en la versión de Magento que está utilizando).

checkout_cart_save_before

checkout_cart_product_add_after

checkout_cart_update_items_before

checkout_cart_update_items_after

checkout_cart_save_after
Sukeshini
fuente
Ya estoy intentando con el checkout_cart_product_add_afterevento, la pregunta es ¿cómo puedo evitar que el producto se agregue al carrito?
Shathish
o si ya está agregado, ¿cómo eliminarlo?
Shathish
1

Tal vez sea un poco una idea de campo izquierdo, pero ¿qué hay de usar el catalog_product_is_salable_afterevento?

Lo que puede hacer aquí es verificar si el producto está en el carrito o si hay otro producto en el carrito. Cuando haya otro producto en el carrito, actualice el atributo 'is_salable' del objeto 'vendible' pasado al observador como falso.

TEN EN CUENTA que esto no ha sido probado y es solo una idea. Fallará si su plantilla no se verifica$product->isSaleable()antes de mostrar el botón. También solo eliminaría el botón y no detendría el proceso de agregar si el usuario pudiera adivinar la URL.

David modales
fuente
1

Sé que este tema es algo antiguo, pero tuve un problema similar. Solo quiero un artículo en el carrito y si el cliente agrega uno nuevo, quiero reemplazar el anterior por el nuevo. Así que anulo la addAction (descrita aquí así:

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

}

www.abo-killer.de
fuente