Question

I have been working on a project which requires customers to get a automatic discount code applied to their basket based on items that are in there.

I thought this was working perfectly with the code logic below. I was seeing the code get generated (in back end and showed discount on cart). However today it has been raised that customer credit cannot be exclusively used to pay for an order.

I have successfully narrowed it down to this module which when disabled the problem is not present. My believe however is that since we're generating the code on the fly and letting Magento handle the actual discount this should work as normal. Debugging shows that the grand total is still the original price when checking if it is available in the free checkout.

Is there some additional logic which I require to enter for this to be compatible?

Please be aware that I have masked namespace/module name slightly due to client confidentiality reasons so you might spot some errors below in this but please disregard such as the code does execute and run what I expected it to.

Expectations:

If a customer meets the criteria for a discount a discount code is generated and they get a discount against the cart.

If customer has sufficient store credit to pay in full they should be able to pay in full with store credit.

Actual:

Discount code is generated (when applicable)

Customer is unable to use store credit to pay in full for their purchase.

Observer: checkout_cart_product_add_after

public function checkout_cart_product_add_after($observer)
{
    if (!Mage::helper('core')->isModuleOutputEnabled('Namespace_WholesaleDiscount')) {
        return;
    }

    /*
     * When emptying the cart this observer is updated
     * due to the setting of it to 0 for deletion.
     * This prevents running the observer and thus resetting items in quote.
     */
    $request = Mage::app()->getRequest()->getParam('update_cart_action');
    if ($request == 'empty_cart') {
        return;
    }



    try {
        $model = Mage::getModel('salesrule/rule')
            ->getCollection()
            ->addFieldToSelect('*')
            ->addFieldToFilter('name', array('eq' => sprintf('WHOLESALE AUTO_%s', Mage::getSingleton('customer/session')->getSessionId())))
            ->load();

        if ($model->count() < 1) {
            // No coupon yet.
            $helper = Mage::helper('wholesalediscount');
            $helper->createDiscountCode($helper->getDiscountAmount(), Mage::getSingleton('customer/session')->getSessionId());

            $model = Mage::getModel('salesrule/rule')
                ->getCollection()
                ->addFieldToFilter('name', array('eq' => sprintf('WHOLESALE AUTO_%s', Mage::getSingleton('customer/session')->getSessionId())))
                ->getFirstItem();

        } else {
            $helper = Mage::helper('wholesalediscount');

            $model = $model->getFirstItem();


            $model->setDiscountAmount($helper->getDiscountAmount());
            $code = Mage::helper('core')->getRandomString(16);

            // Magento initializes the coupon_code, but on model load it is code.
            $model->setCouponCode($code);
            $model->setCode($code);

            $model->save();
        }

        $couponCode = $model->getCode();
        /* END This part is my extra, just to load our coupon for this specific customer */

        Mage::getSingleton('checkout/cart')
            ->getQuote()
            ->getShippingAddress()
            ->setCollectShippingRates(true);

        Mage::getSingleton('checkout/cart')
            ->getQuote()
            ->setCouponCode(strlen($couponCode) ? $couponCode : '')
            ->collectTotals()
            ->save();

    } catch (Exception $e) {
        Mage::logException($e);
    }

    return $this;
}

Helper Logic: Again as above I have masked anything which I feel would potentially reveal either business logic or breach any client confidentiality. As before, the two methods here simply generate the discount code coupon (which I can see working in admin and does apply a discount) and calculates a discount (this is entirely business logic)

public function createDiscountCode($discount, $reference)
    {
        $now = new Zend_Date();
        $now->setTimezone('UTC');
        $data = array(
            'product_ids' => null,
            'name' => sprintf('WHOLESALE AUTO_%s', $reference),
            'description' => null,
            'is_active' => 1,
            'website_ids' => array(Mage::app()->getWebsite()->getId()),
            'customer_group_ids' => array(Mage::getSingleton('customer/session')->getCustomerGroupId()),
            'coupon_type' => 2,
            'coupon_code' => Mage::helper('core')->getRandomString(16),
            'uses_per_coupon' => 1,
            'uses_per_customer' => 1,
            'from_date' => $now->getFullYear() . "-". $now->getMonth() . "-" . $now->getDay(),
            'to_date' => null,
            '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' => 'cart_fixed',
            'discount_amount' => $this->getDiscountAmount(),
            '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('E-Liquids With Kits')
        );

        $model = Mage::getModel('salesrule/rule');

        $validateResult = $model->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']);

            $model->setData($data);

            $model->save();
        }
    }

    /*
     * Use this to calculate how much money off is allowed based on whats in the cart.
     */
    public function getDiscountAmount()
    {
        $customer   = Mage::getSingleton('customer/session')->getCustomer();
        $cart       = Mage::getModel('checkout/cart');
        $discountItems = array();
        /* Exclude some Business logic here */
        foreach ($cart->getQuote()->getAllVisibleItems() as $_item) {
            $product = Mage::getModel('catalog/product')->load($_item->getProduct()->getId());

            /* Business Logic to decide if this item is relevent */
            $discountItems[] = $_item;

        }

        // Calculate Discount
        $appliedDiscounts = 0;
        $discount = 0;
        foreach ($discountitem as $_item) {
            if ($appliedDiscounts < $allowed) {
                $i = 0;
                while ($appliedDiscounts < $allowed && $i < $_item->getQty()) {

                    $appliedDiscounts++;
                    $discount += $_item->getProduct()->getFinalPrice();

                    $i++;

                }
            }
        }
        return $discount;
    }
Was it helpful?

Solution

So in case anyone comes across a similar problem in the future, I have managed to work out what the cause of my issue was. The collect totals was setting a flag causing it not to re count after the discount was applied.

Mage::getSingleton('checkout/cart')
        ->getQuote()
        ->setCouponCode(strlen($couponCode) ? $couponCode : '')
        ->collectTotals()
        ->save();

Replacing the above with:

Mage::getSingleton('checkout/cart')
            ->getQuote()
            ->setCouponCode(strlen($couponCode) ? $couponCode : '')
            ->save();

This means that when attempting to apply the customer credit, it re calculates the total and becomes eligible for the zero payment checkout.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top