应用优惠券代码后的 Magento 2 不应用其他购物车规则

Magento 2 after apply coupon code does not apply other cart rules

我正在使用带有 Amasty_Promo 模块的 Magento 2。这个模块允许在购物车中添加一些 promo/free 礼物来对抗一些购物车 rules.Test 情况是这样的

如果我的购物车中有一些 free/promo 商品,然后如果我应用了优惠券或任何错误的优惠券代码,那么它会从购物车中删除与免费商品/促销商品相关的先前规则。所以没有免费的礼物。

你能帮我告诉我为什么会这样吗?非常感谢

我已经找到原因了,而且是非常扎实的原因。

在 Magento 2 中默认有四种类型的规则

  1. 产品价格折扣百分比
  2. 固定金额折扣
  3. 整个购物车的固定金额折扣
  4. 买 X 送 Y

所以看到以上四个规律我们就可以得出结论了

  • 所有规则都与折扣有关,没有任何促销免费赠品的默认规则。
  • 当我们将优惠券应用到购物车时,只有那些有优惠券的规则才适用,而不适用那些没有优惠券的规则

如果我们只有基于折扣的促销,上述结论是有道理的。但是如果我们添加新规则或者如果我们添加任何第 3 方模块,例如 Amasty Promo 模块。我们还有一些选项可以添加免费礼物相关规则。

所以现在在上面的场景里我们的网站都会提供折扣和免费赠品。如果客户购物车同时针对基于优惠券的规则提供折扣和赠品,则 Magento 将仅应用基于优惠券的规则而忽略所有其他规则。

解决方案:

我们可以通过覆盖 \Magento\SalesRule\Model\Validator

来实现我们的要求

etc/di.xml会变成这样

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">

    <!-- We override it to apply the Amasty_Promo rules even after apply the coupon code -->
    <preference for="\Magento\SalesRule\Model\Validator" type="\YourPackage\YourModule\Rewrite\SalesRule\Model\Validator" />
</config>

YourPackage\YourModule\Rewrite\SalesRule\Model\Validator.php

namespace YourPackage\YourModule\Rewrite\SalesRule\Model;

use Magento\Quote\Model\Quote\Address;
use Magento\Quote\Model\Quote\Item\AbstractItem;

class Validator extends \Magento\SalesRule\Model\Validator
{
    /**
     * Quote item discount calculation process
     *
     * @param AbstractItem $item
     * @return $this
     */
    public function process(AbstractItem $item)
    {
        $item->setDiscountAmount(0);
        $item->setBaseDiscountAmount(0);
        $item->setDiscountPercent(0);

        $itemPrice = $this->getItemPrice($item);
        if ($itemPrice < 0) {
            return $this;
        }

        $appliedRuleIds = array();

        if($this->getCouponCode()) {
            $appliedRuleIds = $this->rulesApplier->applyRules(
                $item,
                $this->_getRules($item->getAddress()),
                $this->_skipActionsValidation,
                $this->getCouponCode()
            );
        }
        $promoItemRuleIds = $this->rulesApplier->applyRules(
            $item,
            $this->_getPromoItemRules($item->getAddress()),
            $this->_skipActionsValidation,
            $this->getCouponCode()
        );

        $appliedRuleIds = array_merge($appliedRuleIds,$promoItemRuleIds );

        $this->rulesApplier->setAppliedRuleIds($item, $appliedRuleIds);

        return $this;
    }

    /**
     * Get rules of promo items
     *
     * @param Address|null $address
     * @return \Magento\SalesRule\Model\ResourceModel\Rule\Collection
     */
    protected function _getPromoItemRules(Address $address = null)
    {
        $addressId = $this->getAddressId($address);
        $key = $this->getWebsiteId() . '_'
            . $this->getCustomerGroupId() . '_'
            . '_'
            . $addressId;
        if (!isset($this->_rules[$key])){
            $this->_rules[$key] = $this->_collectionFactory->create()
                ->setValidationFilter(
                    $this->getWebsiteId(),
                    $this->getCustomerGroupId(),
                    '',
                    null,
                    $address
                )
                ->addFieldToFilter('is_active', 1)
                ->addFieldToFilter('simple_action', array('like'=>'%ampromo%'))//Condition for promo rules only
                ->load();
        }
        return $this->_rules[$key];
    }
}