应用优惠券代码后的 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 中默认有四种类型的规则
- 产品价格折扣百分比
- 固定金额折扣
- 整个购物车的固定金额折扣
- 买 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];
}
}
我正在使用带有 Amasty_Promo
模块的 Magento 2。这个模块允许在购物车中添加一些 promo/free 礼物来对抗一些购物车 rules.Test 情况是这样的
如果我的购物车中有一些 free/promo 商品,然后如果我应用了优惠券或任何错误的优惠券代码,那么它会从购物车中删除与免费商品/促销商品相关的先前规则。所以没有免费的礼物。
你能帮我告诉我为什么会这样吗?非常感谢
我已经找到原因了,而且是非常扎实的原因。
在 Magento 2 中默认有四种类型的规则
- 产品价格折扣百分比
- 固定金额折扣
- 整个购物车的固定金额折扣
- 买 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];
}
}