1

I have a bug with magento2.0.7 at checkout page.

I built a custom cart price rule that applies 60% to the most expensive product in the cart.

Everything works fine and the discount is applied to the right product and in the database the discount is applied in the quote tables on the right cart item.

In the cart page the discount is visible and the total is correct but when going to checkout page, the discount applied appears for a few seconds then an ajax call from a totals.js is refreshing and the discount disappears.

Please if you have any idea for a workaround to get over this bug, share your solution with me.

1 Answer 1

0

I found out the problem. I was applying the discount and then subtracting the discount from the array with the rule_id. This was supposed to prevent the discount to apply twice. But it was also setting the discount to zero and thus at checkout page when it seems that the cart rule is getting verified again, it was refreshed and the discount disappeared. I post here the rule code maybe somebody can get help from it.

<?php
namespace MageDiscount\Discount\Model\SalesRule\Rule\Action\Discount;

use \Magento\SalesRule\Model\Rule\Action\Discount\AbstractDiscount;

/**
* Class GetMostExpensiveDiscount
* @see \Magento\SalesRule\Model\Rule\Action\Discount\BuyXGetY
*/

class GetMostExpensiveDiscount extends AbstractDiscount
{
/**
 * @var \MageDiscount\Discount\Helper\Data
 */
protected $helper;
/**
 * @var \MageDiscount\Discount\Helper\Rules
 */
protected $rulesHelper;

/**
 * GetMostExpensiveDiscount constructor.
 * @param \Magento\SalesRule\Model\Validator $validator
 * @param \Magento\SalesRule\Model\Rule\Action\Discount\DataFactory $discountDataFactory
 * @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency
 * @param \MageDiscount\Discount\Helper\Data $helper
 */
public function __construct(
    \Magento\SalesRule\Model\Validator $validator,
    \Magento\SalesRule\Model\Rule\Action\Discount\DataFactory $discountDataFactory,
    \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency,
    \MageDiscount\Discount\Helper\Data $helper,
    \MageDiscount\Discount\Helper\Rules $rulesHelper
) {
    parent::__construct($validator, $discountDataFactory, $priceCurrency);

    $this->helper = $helper;
    $this->rulesHelper = $rulesHelper;
}

/**
 * @param \Magento\SalesRule\Model\Rule $rule
 * @param \Magento\Quote\Model\Quote\Item\AbstractItem $item
 * @param float $qty
 * @return \Magento\SalesRule\Model\Rule\Action\Discount\Data
 */
public function calculate($rule, $item, $qty)
{
    /** @var \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData */
    $discountData = $this->discountFactory->create();

    if (!$this->helper->isAvailable()) {
        return $discountData;
    }

    /** @var \Magento\Quote\Model\Quote $quote */
    $quote = $item->getQuote();

    /** @var \Magento\Quote\Model\Quote\Address $address */
    $address = $item->getAddress();

    $difRules = $address->getXgCartGetMostExpensiveDiscountRules();

    //\Zend_Debug::dump($difRules, null, true);

    if (!(is_array($difRules) && isset($difRules[$rule->getId()]))) {
        $difRules[$rule->getId()] = $rule->getDiscountAmount();
    }

    //\Zend_Debug::dump($difRules, null, true);


        if ($difRules[$rule->getId()] > 0) {

            $x = $rule->getDiscountStep();
            $y = $rule->getDiscountAmount();

            $rulePercent = min(100, $y);
            //\Zend_Debug::dump($rulePercent);

            $cartCategories = array();
            $i = 0;
            $totalCartQty = 0;

            foreach ($quote->getAllVisibleItems() as $vit)
            {
                $cartCategories[$i]['itemId'] = $vit->getId();
                $cartCategories[$i]['qty'] = $vit->getQty();
                $totalCartQty += $vit->getQty();
                $cartCategories[$i]['itemPrice'] = $this->validator->getItemPrice($vit);
                $cartCategories[$i]['baseItemPrice'] = $this->validator->getItemBasePrice($vit);
                $cartCategories[$i]['itemOriginalPrice'] = $this->validator->getItemOriginalPrice($vit);
                $cartCategories[$i]['baseItemOriginalPrice'] = $this->validator->getItemBaseOriginalPrice($vit);
                $i++;

            }

            // sort array after price from higher to lower
            $this->aaVSort($cartCategories, 'itemPrice');
            //\Zend_Debug::dump($cartCategories, null, true);

            //this is not usable for this rule!
            // if(count($cartCategories) === 1)
            // {
            //     return $discountData;
            // }

            //\Zend_Debug::dump($cartCategories[0]['itemId'], null, true);
            //\Zend_Debug::dump($item->getId(), null, true);


             if($item->getId() !==  $cartCategories[0]['itemId'])
             {

                return $discountData;
             }


            $discountQtymin = min($difRules[$rule->getId()], $qty);

            //\Zend_Debug::dump($discountQtymin, null, true);

            //\Zend_Debug::dump($totalCartQty, null, true);

            //only one item to be discounted
            $discountQty = 1;

            //for thisrule we must have only one item discounted
            // if ($x) {
            //     $discountQty = floor( $totalCartQty / ($x + 1));
            // }
            // else
            // {
            //     $discountQty = 1;
            // }

            // this line here is not needed - subtracting the discount           form the rule array
            //$difRules[$rule->getId()] -= $discountQty * $y;
            //$difRules[$rule->getId()] += ($discountQty - 1) * $y;

            //\Zend_Debug::dump($discountQty, null, true);

            $discountAmount = 0;
            $discountAmountBase = 0;
            $discountAmountOrig = 0;
            $discountAmountBaseOrig = 0;

            $_rulePct = $rulePercent / 100;
            //\Zend_Debug::dump($_rulePct, null, true);


            $itemsToBeDiscounted = array();

            //cover cases while $discountQty > 0 and shift most expensive item from array
            while( $discountQty > 0)
            {
                //in order to discount the highest price we remove the first item from the price ordered array
                $itemsToBeDiscounted[] = array_shift($cartCategories);
                $discKey = count($itemsToBeDiscounted);

                $availableQty = $itemsToBeDiscounted[$discKey - 1]['qty'];

                if( $discountQty >= $availableQty)
                {
                    $discountAmount += (($itemsToBeDiscounted[$discKey - 1]['itemPrice'] * $availableQty ) * $_rulePct);
                    $discountAmountBase += (($itemsToBeDiscounted[$discKey - 1]['baseItemPrice'] * $availableQty ) * $_rulePct);
                    $discountAmountOrig += (($itemsToBeDiscounted[$discKey - 1]['itemOriginalPrice'] * $availableQty ) * $_rulePct);
                    $discountAmountBaseOrig += (($itemsToBeDiscounted[$discKey - 1]['baseItemOriginalPrice'] * $availableQty ) * $_rulePct);
                    $discountQty -= $availableQty;

                }
                else
                {
                    $discountAmount += (($itemsToBeDiscounted[$discKey - 1]['itemPrice'] * $discountQty ) * $_rulePct);
                    $discountAmountBase += (($itemsToBeDiscounted[$discKey - 1]['baseItemPrice'] * $discountQty ) * $_rulePct);
                    $discountAmountOrig += (($itemsToBeDiscounted[$discKey - 1]['itemOriginalPrice'] * $discountQty ) * $_rulePct);
                    $discountAmountBaseOrig += (($itemsToBeDiscounted[$discKey - 1]['baseItemOriginalPrice'] * $discountQty ) * $_rulePct);

                    $itemsToBeDiscounted[$discKey - 1]['qty'] = $discountQty;

                    $discountQty = 0;
                }

                //\Zend_Debug::dump($discountQty, null, true);

                  if($discountQty === 0)
                  {
                      break;
                  }

            }


            //\Zend_Debug::dump($discountAmount, null, true);

            //\Zend_Debug::dump($itemsToBeDiscounted, null, true);

            $discountData->setAmount($discountAmount);
            $discountData->setBaseAmount($discountAmountBase);
            $discountData->setOriginalAmount($discountAmountOrig);
            $discountData->setBaseOriginalAmount($discountAmountBaseOrig);

        }

        $address->setXgCartGetMostExpensiveDiscountRules($difRules);

        //\Zend_Debug::dump($difRules, null, true);
        //\Zend_Debug::dump($discountData, null, true);
        //\Zend_Debug::dump($item->getId(), null, true);

    return $discountData;

}


    /**
    * Sort Multi Dimension array based on Numerical value + array_values
         *
         * @author Mohamed Meabed <[email protected]> modified by Andrada Crisan
         *
         * @param $array
         * @param $key
         */
    public function aaVSort(&$array, $key)
{
        $sorter = array();
        $ret = array();
        reset($array);
        foreach ($array as $ii => $va) {
            $sorter[$ii] = $va[$key];
        }

        arsort($sorter, SORT_NUMERIC);

        foreach ($sorter as $ii => $va) {
                $ret[$ii] = $array[$ii];
        }

        $array = array_values($ret);
}
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.