Skip to content

Magento 2.4.4 Change shipping method when cart value changes by adding quantity

I am having a bit of a issue figuring out the correct method to implement this. I am using OneStepCheckout on my site with free delivery for minimum cart value. When customers add product to their cart and proceed to the checkout page and if their subtotal amount is lower than minimum order required for free shipping then table rate shipping is calculated and displayed at the shipping method. Many customers are adding product quantity to qualify for the free shipping method on the checkout page but some of them are not manually selecting free shipping after adding the required quantity.

Please help me out… is there a way I can make sure the cheapest available shipping method is selected even in this scenario, so by default free shipping will be selected when customers place their orders.

Thanks

My code for app/code/Mageplaza/Osc/Model/Plugin/Checkout/ShippingMethodManagement.php
is very different. would appreciate to know what edits should I make in this.

<?php
/**
 * Mageplaza
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Mageplaza.com license that is
 * available through the world-wide-web at this URL:
 * https://www.mageplaza.com/LICENSE.txt
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade this extension to newer
 * version in the future.
 *
 * @category    Mageplaza
 * @package     Mageplaza_Osc
 * @copyright   Copyright (c) Mageplaza (https://www.mageplaza.com/)
 * @license     https://www.mageplaza.com/LICENSE.txt
 */

namespace MageplazaOscModelPluginCheckout;

use Closure;
use Exception;
use MagentoCustomerApiAddressRepositoryInterface;
use MagentoFrameworkExceptionLocalizedException;
use MagentoFrameworkExceptionNoSuchEntityException;
use MagentoQuoteApiCartRepositoryInterface;
use MagentoQuoteApiDataAddressInterface;
use MagentoQuoteApiDataEstimateAddressInterface;
use MagentoQuoteModelShippingMethodManagement as QuoteShippingMethodManagement;
use MagentoCustomerApiDataAddressInterface as CustomerAddressInterface;
use MagentoQuoteModelQuote;

/**
 * Class ShippingMethodManagement
 *
 * @package MageplazaOscModelPluginCheckout
 */
class ShippingMethodManagement
{
    /**
     * Quote repository.
     *
     * @var CartRepositoryInterface
     */
    protected $quoteRepository;

    /**
     * Customer Address repository
     *
     * @var AddressRepositoryInterface
     */
    protected $addressRepository;

    /**
     * @param CartRepositoryInterface    $quoteRepository
     * @param AddressRepositoryInterface $addressRepository
     */
    public function __construct(
        CartRepositoryInterface $quoteRepository,
        AddressRepositoryInterface $addressRepository
    ) {
        $this->quoteRepository   = $quoteRepository;
        $this->addressRepository = $addressRepository;
    }

    /**
     * @param QuoteShippingMethodManagement $subject
     * @param Closure                       $proceed
     * @param                               $cartId
     * @param EstimateAddressInterface      $address
     *
     * @return mixed
     * @throws NoSuchEntityException
     */
    public function aroundEstimateByAddress(
        QuoteShippingMethodManagement $subject,
        Closure $proceed,
        $cartId,
        EstimateAddressInterface $address
    ) {
        $this->saveAddress($cartId, $address);

        return $proceed($cartId, $address);
    }

    /**
     * @param QuoteShippingMethodManagement $subject
     * @param Closure                       $proceed
     * @param                               $cartId
     * @param AddressInterface              $address
     *
     * @return mixed
     * @throws NoSuchEntityException
     */
    public function aroundEstimateByExtendedAddress(
        QuoteShippingMethodManagement $subject,
        Closure $proceed,
        $cartId,
        AddressInterface $address
    ) {
        foreach ($address->getCustomAttributes() as $attribute) {
            if (isset($attribute->getValue()['value'])) {
                $attribute->setValue($attribute->getValue()['value']);
            }
        }

        $this->saveAddress($cartId, $address);

        return $proceed($cartId, $address);
    }

    /**
     * @param QuoteShippingMethodManagement $subject
     * @param Closure                       $proceed
     * @param                               $cartId
     * @param                               $addressId
     *
     * @return mixed
     * @throws LocalizedException
     */
    public function aroundEstimateByAddressId(
        QuoteShippingMethodManagement $subject,
        Closure $proceed,
        $cartId,
        $addressId
    ) {
        $address = $this->addressRepository->getById($addressId);
        $this->saveAddress($cartId, $address);

        return $proceed($cartId, $addressId);
    }

    /**
     * @param                                                                    $cartId
     * @param EstimateAddressInterface|AddressInterface|CustomerAddressInterface $address
     *
     * @return $this
     * @throws NoSuchEntityException
     */
    private function saveAddress($cartId, $address)
    {
        /** @var Quote $quote */
        $quote = $this->quoteRepository->getActive($cartId);

        if (!$quote->isVirtual()) {
            $addressData = [
                AddressInterface::KEY_COUNTRY_ID      => $address->getCountryId(),
                AddressInterface::KEY_POSTCODE        => $address->getPostcode(),
                AddressInterface::KEY_REGION_ID       => $address->getRegionId(),
                AddressInterface::KEY_STREET          => $address->getStreet(),
                AddressInterface::KEY_CITY            => $address->getCity(),
                AddressInterface::CUSTOMER_ADDRESS_ID => $address->getId()
            ];

            $shippingAddress = $quote->getShippingAddress();
            try {
                $shippingAddress->addData($addressData)
                    ->save();
                $this->quoteRepository->save($quote);
            } catch (Exception $e) {
                return $this;
            }
        }

        return $this;
    }
}