Aplicar cupons/regras de desconto dinamicamente via PHP no Magento

Olá Galera,

Já faz algum tempo que não escrevo aqui em meu blog, mas acreditem: não é por falta de vontade. A vida de um desenvolvedor Magento anda bastante badalada no momento.

Bem, vamos ao que interessa. Estes dias precisei resolver um problema que não foi muito simples de se aplicar uma solução. Um cliente precisava que em seu carrinho existisse um desconto dinâmico que seria calculado onlive de acordo com os produtos e quantidades que o usuário colocasse no carrinho. Tentei imaginar como poderia aplicar isso com regras de desconto para catálogo ou para carrinho. Pensei até mesmo no fabuloso Tier Price do Magento, mas nenhuma destas soluções poderia resolver o problema uma vez que o valor do desconto seria calculado dinamicamente e apenas seria aplicado quando houvesse mais de um produto no carrinho. Não vou entrar em detalhes do porquê, mas o fato do valor ter que ser calculado On the Fly impossibilitou que eu utilizasse as ferramentas que o Magento já possui e realmente colocasse a mão na massa, quer dizer no código.

A lógico implementada para a solução deste problema foi: cria-se um cupom de desconto on the fly, aplica-se este cupom do pedido e, no momento que o cliente finalizar a compra, exclui permanentemente este cupom para que o painel do administrador não fique com tanta sujeira.

Pois bem, sabendo o que foi preciso fazer, primeiramente precisei criar o cupom de desconto quando o cliente colocasse qualquer produto no carrinho. Para tal, utilizei 3 eventos:

checkout_cart_add_product_complete = ocorre após o cliente adicionar qualquer produto ao carrinho;

checkout_cart_update_items_after = ocorre quando o cliente atualiza a quantidade dos produtos no carrinho;

sales_quote_remove_item = disparado quando o cliente remove qualquer produto do carrinho.

<config>
	...
	<frontend>
		<events>
			<checkout_cart_add_product_complete>
				<observers>
					<tiagosampaio_checkout_cart_add_product_complete>
						<type>singleton</type>
						<class>tiagosampaio/observer</class>
						<method>applyDiscountIfApplicable</method>
					</tiagosampaio_checkout_cart_add_product_complete>
				</observers>
			</checkout_cart_add_product_complete>
			<checkout_cart_update_items_after>
				<observers>
					<tiagosampaio_checkout_cart_update_items_after>
						<type>singleton</type>
						<class>tiagosampaio/observer</class>
						<method>applyDiscountIfApplicable</method>
					</tiagosampaio_checkout_cart_update_items_after>
				</observers>
			</checkout_cart_update_items_after>
			<sales_quote_remove_item>
				<observers>
					<tiagosampaio_sales_quote_remove_item>
						<type>singleton</type>
						<class>tiagosampaio/observer</class>
						<method>applyDiscountIfApplicable</method>
					</tiagosampaio_sales_quote_remove_item>
				</observers>
			</sales_quote_remove_item>
			<checkout_type_onepage_save_order_after>
				<observers>
					<tiagosampaio_checkout_type_onepage_save_order_after>
						<type>singleton</type>
						<class>tiagosampaio/observer</class>
						<method>unsetAutoGeneratedCoupon</method>
					</tiagosampaio_checkout_type_onepage_save_order_after>
				</observers>
			</checkout_type_onepage_save_order_after>
		</events>
	</frontend>
	...
</config>

O código que cria o cupom segue logo abaixo:

public function getNewRandomCoupon($value = 0)
{
    if(!$value) {
        return;
    }

    $groupIds = Mage::getModel('customer/group')->getCollection()->getAllIds();
    $websiteIds = Mage::getModel('core/website')->getCollection()->getAllIds();

    $data = array(
        'product_ids' => null,
        'name' => 'AUTO GENERATED COUPOM - ' . date('YmdHis'),
        'description' => $this->__('This rule was generated automatically by Tiago Sampaio.'),
        'is_active' => 1,
        'website_ids' => $websiteIds,
        'customer_group_ids' => $groupIds,
        'coupon_type' => Mage_SalesRule_Model_Rule::COUPON_TYPE_SPECIFIC,
        'coupon_code' => Mage::helper('core')->getRandomString(10),
        'uses_per_coupon' => 1,
        'uses_per_customer' => 1,
        'from_date' => Mage::getModel('core/date')->date('d/m/Y'),
        'to_date' => Mage::getModel('core/date')->date('d/m/Y'),
        'sort_order' => null,
        'is_rss' => 1,
        'rule' => array(
            'conditions' => array(
                array(
                    'type' => 'salesrule/rule_condition_combine',
                    'aggregator' => 'all',
                    'value' => 1,
                    'new_child' => null
                )
            )
        ),
        'simple_action' => Mage_SalesRule_Model_Rule::CART_FIXED_ACTION,
        'discount_amount' => $value,
        'discount_qty' => 0,
        'discount_step' => null,
        'apply_to_shipping' => 0,
        'simple_free_shipping' => 0,
        'stop_rules_processing' => 0,
        'rule' => array(
            'actions' => array(
                array(
                    'type' => 'salesrule/rule_condition_product_combine',
                    'aggregator' => 'all',
                    'value' => 1,
                    'new_child' => null
                )
            )
        ),
        'store_labels' => array('Premium Discount'),
    );

    $rule = Mage::getModel('salesrule/rule');
    $data = $this->_filterDates($data, array('from_date', 'to_date'));
    $validateResult = $rule->validateData(new Varien_Object($data));

    if ($validateResult == true) {
        if (isset($data['simple_action']) && $data['simple_action'] == 'by_percent'
                && isset($data['discount_amount'])) {
            $data['discount_amount'] = min(100, $data['discount_amount']);
        }
        if (isset($data['rule']['conditions'])) {
            $data['conditions'] = $data['rule']['conditions'];
        }
        if (isset($data['rule']['actions'])) {
            $data['actions'] = $data['rule']['actions'];
        }

        unset($data['rule']);
        $rule->loadPost($data);
        $rule->save();

        return $rule;
    }
}

Perfeito, este pequeno trecho de código criará para você um cupom de desconto para todo o carrinho com um valor que pode ser estipulado como parâmetro do método e com um código aleatório de 10 caracteres.
Agora precisamos aplicar a lógica para que este cupom seja aplicado e após isso aplicar o cupom ao objeto Quote do Magento:

/**
 * The method that decides if a coupon will be applied to a quote
 *
 * @param Varien_Event_Observer $observer
 */
public function applyDiscountIfApplicable(Varien_Event_Observer $observer)
{
    $session = Mage::getSingleton('checkout/session');

    if($session->hasQuote()) {
        $quote = $session->getQuote();

        /**
         * Toda sua lógica da regra vem aqui ...
         */

        $discount = $this->_calculateDiscount($quote);
        $couponCode = $this->getNewRandomCoupon($discount);

        if($couponCode && $quote) {
            $quote->getShippingAddress()->setCollectShippingRates(true);
            $quote->setCouponCode($couponCode)->collectTotals()->save();
        }
    }
}

Caso preciso remover o cupom em algum momento basta usar este trecho de código:

$quote->getShippingAddress()->setCollectShippingRates(true);
$quote->setCouponCode(null)->collectTotals()->save();

Atenção, é preciso muito cuidado ao implementar qualquer método no Magento que dê descontos automático para os clientes. O código é preciso ser muito bem testado e implementado antes de ir para produção.
Espero sinceramente que este post os ajude em algum momento de sua vida de programador.

1 Comment

  1. Tiago eu vendo pelo Peixe Urbano e preciso configurar o cupom de desconto para que ele aceite qualquer cupom inserido no campo de cupom de desconto, pois utilizarei o cupom inserido somente após checar no validador do peixe urbano se o cupom é válido. O peixe urbano não me passa antecipadamente os cupons que ele vai liberar para o cliente que realizou a compra.

    Eu tenho um site de tênis feito com o magento. E faço ofertas no peixe urbano. O cliente que compra no peixe urbano insere o cupom de desconto no meu e-commerce.

    Por isso preciso saber como configurar o cupom para aceitar qualquer numeração.

    Sou analista de sistemas e trabalho com o magente a quase 2 anos. Abraço e agradeço se souber me passar a solução.

Leave A Reply

Navigate