문제

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 magento.stackexchange
scroll top