Need to override Free shipping method
-
28-12-2020 - |
문제
In my site, I need to add a condition to ,
Display Free Shipping only for order total bigger than 150$. I've added Maximum Order Amount from backend. from Stores>Settings>Configuration>Sales>Shipping Methods->Free shipping
I need to hide Free shipping option if total amount is less than 150$.
This works correctly only if order item total is 150$ without any discounts or deductions. I added 10$ discount onto 150$ item.but it still shows free shipping option.
How can I fix this?
해결책
Take a look at the Magento\OfflineShipping\Model\Carrier\Freeshipping
class located at magento/module-offline-shipping/Model/Carrier/Freeshipping.php
:
/**
* FreeShipping Rates Collector
*
* @param RateRequest $request
* @return \Magento\Shipping\Model\Rate\Result|bool
*/
public function collectRates(RateRequest $request)
{
if (!$this->getConfigFlag('active')) {
return false;
}
/** @var \Magento\Shipping\Model\Rate\Result $result */
$result = $this->_rateResultFactory->create();
$this->_updateFreeMethodQuote($request);
if ($request->getFreeShipping() || $request->getBaseSubtotalInclTax() >= $this->getConfigData(
'free_shipping_subtotal'
)
) {
/** @var \Magento\Quote\Model\Quote\Address\RateResult\Method $method */
$method = $this->_rateMethodFactory->create();
$method->setCarrier('freeshipping');
$method->setCarrierTitle($this->getConfigData('title'));
$method->setMethod('freeshipping');
$method->setMethodTitle($this->getConfigData('name'));
$method->setPrice('0.00');
$method->setCost('0.00');
$result->append($method);
}
return $result;
}
as you can see it compares your configuration value (150) with a base subtotal with tax from the shipping rates request. There nothing about discount checked here. For your purpose, it is better to write an after-plugin for this method and make a different validation. Or rewrite this class completely.
Maybe this plugin can help you, but I have no time to test it right now:
Note: here the full plugin code on the GitHub
etc/di.xml
<?xml version="1.0"?>
<!--
/**
* Copyright © 2018 MageWorx. All rights reserved.
* See LICENSE.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<!-- PLUGINS: -->
<type name="Magento\OfflineShipping\Model\Carrier\Freeshipping">
<plugin name="mageworx_validate_subtotal_with_discount" type="MageWorx\FreeShippingWithDiscount\Plugin\FreeShipping"/>
</type>
</config>
MageWorx/FreeShippingWithDiscount/Plugin/FreeShipping.php
<?php
/**
* Copyright © 2018 MageWorx. All rights reserved.
* See LICENSE.txt for license details.
*/
namespace MageWorx\FreeShippingWithDiscount\Plugin;
use Magento\OfflineShipping\Model\Carrier\Freeshipping as OriginalFreeShipping;
use Magento\Checkout\Model\Session;
class FreeShipping
{
/** @var Session|\Magento\Backend\Model\Session\Quote */
protected $session;
/**
* FreeShipping constructor.
*
* @param Session $checkoutSession
* @param \Magento\Backend\Model\Session\Quote $backendQuoteSession
* @param \Magento\Framework\App\State $state
* @param \Magento\Customer\Model\Session $customerSession
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function __construct(
Session $checkoutSession,
\Magento\Backend\Model\Session\Quote $backendQuoteSession,
\Magento\Framework\App\State $state,
\Magento\Customer\Model\Session $customerSession
) {
if ($state->getAreaCode() == \Magento\Framework\App\Area::AREA_ADMINHTML) {
$this->session = $backendQuoteSession;
} else {
$this->session = $checkoutSession;
}
}
/**
* @param OriginalFreeShipping $subject
* @param callable $proceed
* @param $field
* @return float
*/
public function aroundGetConfigData(OriginalFreeShipping $subject, callable $proceed, $field)
{
$value = $proceed($field);
if ($field != 'free_shipping_subtotal') {
return $value;
}
// Add discount to the initial value from config
// In this case base subtotal with tax should be equal or greater then value including discount
// Lets
// Value == 150
// Subtotal == 140
// Tax == 14
// Discount == 28
// Default condition will check it like:
// 140 + 14 >= 150 returns true
// modified condition will check:
// 140 + 14 >= 150 + 28 returns false
/** @var \Magento\Quote\Model\Quote $quote */
$quote = $this->session->getQuote();
$shippingAddress = $quote->getShippingAddress();
$baseDiscount = $shippingAddress->getBaseDiscountAmount();
$value += abs($baseDiscount);
return $value;
}
}
Main idea is to add base discount amount to the validation value, like 150 + discount.
PS: we should use abs($baseDiscount)
becasue it is usually has a -
prefix.