1

I want to disable free shipping...if I select a product with some custom attribute...is there any way to achieve this.

Thanks in advance.

  • That is a bit of complicated process you should create a module for it and check for couple of thing. Show what you have done so far, then it is easier to help you. – Korbin Jul 30 at 11:14
1

Try it like this:- first create a custom module using below link https://www.mageplaza.com/magento-2-module-development/

now follow up form here

vendor/module/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">
    <type name="Magento\Shipping\Model\Shipping">
        <plugin disabled="false" name="Vendor_Module_Plugin_Magento_Shipping_Model_Shipping" sortOrder="10" type="Vendor\Module\Plugin\Magento\Shipping\Model\FreeShipping"/>
    </type>
</config>

now create freeshipping.php file

Vendor\Module\Plugin\Magento\Shipping\Model

<?php
namespace Vendor\Module\Plugin\Magento\Shipping\Model;
class FreeShipping
{
    protected $product;
    public function __construct(
        \Magento\Catalog\Model\ProductFactory $product
    ) {
        $this->product = $product; 
    }
 
    public function aroundCollectCarrierRates(
        \Magento\Shipping\Model\Shipping $subject,
        \Closure $proceed,
        $carrierCode,
        $request
    ) {
        $noFreeShipping = false;
        $allItems = $request->getAllItems();
         
        // iterate all cart products to check if no_free_shipping is true
        foreach ($allItems as $item) {    
            $_product = $this->product->create()->load($item->getProduct()->getId());
            // if product has no_free_shipping true
            if ($_product->getNoFreeShipping()) {
                $noFreeShipping = true;
                break;
            }
        }
        // if no_free_shipping is yes and shipping method free shipping return nothing
        if ($noFreeShipping && $carrierCode == 'freeshipping') {
            return false;
        }
        $result = $proceed($carrierCode, $request);
        return $result;
    }
}

Now you just need to create a custom attribute on which you will disable the free shipping for selected products

Vendor\Module\Setup\InstallData.php

<?php
namespace Vendor\Module\Setup;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;

/**
 * @codeCoverageIgnore
 */
class InstallData implements InstallDataInterface
{
    /**
     * EAV setup factory
     *
     * @var EavSetupFactory
     */
    private $eavSetupFactory;

    /**
     * Init
     *
     * @param EavSetupFactory $eavSetupFactory
     */
    public function __construct(EavSetupFactory $eavSetupFactory)
    {
        $this->eavSetupFactory = $eavSetupFactory;
    }

    /**
     * {@inheritdoc}
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
     */
    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        /** @var EavSetup $eavSetup */
        $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);

        /**
         * Add attributes to the eav/attribute
         */

        $eavSetup->addAttribute(
                \Magento\Catalog\Model\Product::ENTITY,
                'no_free_shipping',
                [
                    'group' => 'General',
                    'type' => 'int',
                    'backend' => '',
                    'frontend' => '',
                    'label' => 'no_free_shipping',
                    'input' => 'boolean',
                    'class' => '',
                    'source' => \Magento\Eav\Model\Entity\Attribute\Source\Boolean::class,
                    'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
                    'visible' => true,
                    'required' => false,
                    'user_defined' => false,
                    'default' => '1',
                    'searchable' => false,
                    'filterable' => false,
                    'comparable' => false,
                    'visible_on_front' => false,
                    'used_in_product_listing' => false,
                    'unique' => false,
                    'apply_to' => 'simple,configurable,bundle'
                ]
            );
    }
}

you are done

| improve this answer | |
0

Add a new Js file to check out page. app/design/frontend/vendor/theme/Magento_Checkout/layout/checkout_index_index.xml

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <head>
        <!-- Add local resources -->
        <script src="VendorName_ModuleName::js/checkout.js"/>
    </head>
    <body>
        <move element="logo" destination="porto_header"/>
    </body>
</page>

only add script inside head tag after page tag.

head>
        <script src="VendorName_ModuleName::js/checkout.js"/>
   head

now add this file here.

app/code/vendorname/modulename/view/frontend/web/js/checkout.js

setTimeout(function(){ 
    hidefreeshipping();
 }, 10);
setTimeout(function(){ 
    hidefreeshipping();
 }, 50);
setTimeout(function(){ 
    hidefreeshipping();
 }, 100);
setTimeout(function(){ 
    hidefreeshipping();
 }, 200);
setTimeout(function(){ 
    hidefreeshipping();
 }, 500);
setTimeout(function(){ 
    hidefreeshipping();
 }, 1500);
setTimeout(function(){ 
    hidefreeshipping();
 }, 2500);
setTimeout(function(){ 
    hidefreeshipping();
 }, 5000);
setTimeout(function(){ 
    hidefreeshipping();
 }, 10000);
setTimeout(function(){ 
    hidefreeshipping();
 }, 20000);
function hidefreeshipping(){
    jQuery.ajax({
        url: "../check_attribute_data/fetchdata",
        cache: false,
        async : false,
        data:{},
        type: "POST",
        dataType:'json',
        success: function(response){
            
            if(response=='yes'){
                    jQuery('.table-checkout-shipping-method:nth-child(2)').css('display':'none');
                   }
                    
               
                 
            //console.log(response);
        }
    });
}

Now for ajax action url add this file. app/code/vendorname/modulname/Controller/Fetchdata.php

<?php
namespace vendorname\modulname\Controller;

class Fetchdata extends \Magento\Framework\App\Action\Action
{
    protected $_pageFactory;

    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $pageFactory)
    {
        $this->_pageFactory = $pageFactory;
        return parent::__construct($context);
    }

    public function execute()
    {
        $product_attribut_exists='No';
        //run foreach loop on cart items and check attribute of products, 
        //if attribute exist change $product_attribut_exists='Yes
        echo $product_attribut_exists;
        
    }
}

for publick URL, you can use this file.

app/code/vendorname/modulename/etc/frontend/routes.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd">
    <router id="standard">
        <route id="check_attribute_data" frontName="check_attribute_data">
            <module name="vendorname_modulename" />
        </route>
    </router>
</config>

Now in browser, run this url http://yourmagentourl.com/fetch_rest_api_data/fetchdata i-e http://yourmagentourl.com/RoutFrontName/ControllerName

| improve this answer | |
0

If you using Magento default Free Shipping \Magento\OfflineShipping\Model\Carrier\Freeshipping Shipping method then you can try below solution.

Create a after plugin on \Magento\OfflineShipping\Model\Carrier\Freeshipping::collectRates

And check here you the custom attribute of the product and return false if condition match

Create di.xml

Create di.xml at app/code/StackExchange/MagentoTest/etc/di.xml and declare plugin class.

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\OfflineShipping\Model\Carrier\Freeshipping">
        <plugin disabled="false" name="StackExchange_MagentoTest_Plugin_Magento_OfflineShipping_Model_Carrier_Freeshipping" sortOrder="10" type="StackExchange\MagentoTest\Plugin\Magento\OfflineShipping\Model\Carrier\Freeshipping"/>
    </type>
</config>

Create Plugin class at app/code/StackExchange/MagentoTest/Plugin/Magento/OfflineShipping/Model/Carrier/Freeshipping.php.

And Define the plugin class here.

<?php
namespace StackExchange\MagentoTest\Plugin\Magento\OfflineShipping\Model\Carrier;

use Magento\Quote\Model\Quote\Address\RateRequest;

class Freeshipping
{

    public function afterCollectRates(
        \Magento\OfflineShipping\Model\Carrier\Freeshipping $subject,
        $result,
        RateRequest $request
    ) {

       if($result instanceof  \Magento\Shipping\Model\Rate\Result){
           $check = false;
           foreach ($request->getAllItems() as $item) {
               if ($item->getParentItem()) {
                   continue;
               }
               $attributeValue = $item->getProduct()->getYOUR_ATTRIBUTECODE();
               // here condition match
               if({YourCondition}){
                   $check = true;
                   break;
               }

               /*
               if ($item->getHasChildren() && $item->isShipSeparately()) {
                   foreach ($item->getChildren() as $child) {
                       if ($child->getProduct()->isVirtual()) {

                       }
                   }
               }*/
           }

           /**
            * If check variable is true return  false.
            * False means hide Free Shipping method at Checkout
            */
           if($check){
               return false;
           }
       }
        return $result;
    }
}
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.