Bhaveshpp

Professional Magento Developr - Healp eachother to grow

Magento2: Shipping restriction

11 Aug 2021 » magento2

define plugin

<?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\Rate\Result">
         <plugin name="afterGetAllRates" type="Bhaveshpp\ShippingRestriction\Plugin\Magento\Shipping\Model\Rate\Result" sortOrder="1" />
    </type>
</config>

Use Plugin

namespace Bhaveshpp\ShippingRestriction\Plugin\Magento\Shipping\Model\Rate;
use Magento\Shipping\Model\Rate\Result as Subject;
use Bhaveshpp\ShippingRestriction\Model\Check;

/**
 * Class Result 
 */
class Result  
{
    /**
     * @var Check $checkModel
     */
    protected $checkModel;
    
    /**
     * initialize 
     *
     * @param Check $checkModel
     */
    public function __construct(Check $checkModel)
    {
        $this->checkModel = $checkModel;
    }

    /**
     * After Plugin
     *
     * @param Subject $subject
     * @param array $result
     * @return array
     */
    public function afterGetAllRates(Subject $subject, $result)
    {
        return $this->checkModel->checkAndReturn($result);
    }
}

define systemconfig

<?xml version = "1.0"?>
<config xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation = "urn:magento:module:Magento_Config:etc/system_file.xsd">
    <system>
        <tab id="bhaveshpp" translate="label" sortOrder="100">
            <label>Bhaveshpp</label>
        </tab>
        <section id="shipping_rescriction" translate="label" sortOrder="100" showInDefault="1" showInWebsite="0" showInStore="0">
            <class>separator-top</class>
            <label>Shipping Rescriction</label>
            <tab>Bhaveshpp</tab>
            <resource>Bhaveshpp_ShippingRestriction::setting_configuration</resource>
            <group id="general" translate="label" type="text" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
                <label>General Configuration</label>
                <field id="enable" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
                    <label>Enable</label>
                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                </field>
            </group>
            <group id="from" translate="label" type="text" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
                <label>From</label>
                <field id="from_day" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
                    <label>From Day</label>
                    <source_model>Bhaveshpp\ShippingRestriction\Model\Config\Source\Day</source_model>
                </field>
                <field id="from_month" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
                    <label>From Month</label>
                    <source_model>Bhaveshpp\ShippingRestriction\Model\Config\Source\Month</source_model>
                </field>
            </group>
            <group id="to" translate="label" type="text" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
                <label>To</label>
                <field id="to_day" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
                    <label>To Day</label>
                    <source_model>Bhaveshpp\ShippingRestriction\Model\Config\Source\Day</source_model>
                </field>
                <field id="to_month" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
                    <label>To Month</label>
                    <source_model>Bhaveshpp\ShippingRestriction\Model\Config\Source\Month</source_model>
                </field>
            </group>
            <group id="shipping_method" translate="label" type="text" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
                <label>Shipping Method</label>
                <field id="allowed_method" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
                    <label>Allowed Method</label>
                    <source_model>Bhaveshpp\ShippingRestriction\Model\Config\Source\ShippingMethod</source_model>
                </field>
            </group>
        </section>
    </system>
</config>

define model Config Source

namespace Bhaveshpp\ShippingRestriction\Model\Config\Source;

class Day implements \Magento\Framework\Option\ArrayInterface
{
    /**
     * Options getter
     *
     * @return array
     */
    public function toOptionArray()
    {
        $return = [];
        for ($i=1; $i <= 31 ; $i++) { 
            $return[] = ['value' => $i, 'label' => $i];
        }
        return $return;
    }

    /**
     * Get options in "key-value" format
     *
     * @return array
     */
    public function toArray()
    {
        $return = [];
        for ($i=1; $i <= 31 ; $i++) { 
            $return[$i] = $i;
        }
        return $return;
    }
}

namespace Bhaveshpp\ShippingRestriction\Model\Config\Source;

/**
 * @api
 * @since 100.0.2
 */
class Month implements \Magento\Framework\Option\ArrayInterface
{
    /**
     * Options getter
     *
     * @return array
     */
    public function toOptionArray()
    {
        return [
            ['value' => 1, 'label' => __('January')], 
            ['value' => 2, 'label' => __('February')], 
            ['value' => 3, 'label' => __('March')], 
            ['value' => 4, 'label' => __('April')], 
            ['value' => 5, 'label' => __('May')], 
            ['value' => 6, 'label' => __('June')], 
            ['value' => 7, 'label' => __('July')], 
            ['value' => 8, 'label' => __('August')], 
            ['value' => 9, 'label' => __('September')], 
            ['value' => 10, 'label' => __('October')], 
            ['value' => 11, 'label' => __('November')], 
            ['value' => 12, 'label' => __('December')]
        ];
    }

    /**
     * Get options in "key-value" format
     *
     * @return array
     */
    public function toArray()
    {
        return [
            1 => __('January'), 
            2 => __('February'), 
            3 => __('March'), 
            4 => __('April'), 
            5 => __('May'), 
            6 => __('June'), 
            7 => __('July'), 
            8 => __('August'), 
            9 => __('September'), 
            10 => __('October'), 
            11 => __('November'), 
            12 => __('December')
        ];
    }
}

namespace Bhaveshpp\ShippingRestriction\Model\Config\Source;
use Magento\Shipping\Model\Config as ShippingConfig;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Option\ArrayInterface;

/**
 * Class ShippingMethod
 */
class ShippingMethod implements ArrayInterface
{
    /**
     * Core store config
     *
     * @var ScopeConfigInterface
     */
    protected $scopeConfig;
    
    /**
     * Get shipping methods
     *
     * @var ShippingConfig $shippingConfig
     */
    protected $shippingConfig;

    /**
     * Initialize
     *
     * @param ScopeConfigInterface $scopeConfig
     * @param ShippingConfig $shippingConfig
     */
    public function __construct(
        ScopeConfigInterface $scopeConfig,
        ShippingConfig $shippingConfig
    )
    {
        $this->scopeConfig = $scopeConfig;
        $this->shippingConfig = $shippingConfig;
    }

    /**
     * Return Shipping carriers grouped array
     *
     * @return array
     */
    public function getAllMethods()
    {
        $methods = [];
        $carriers = $this->shippingConfig->getAllCarriers();

        /** @var \Magento\Shipping\Model\Carrier\CarrierInterface $carrierModel */
        foreach ($carriers as $carrierCode => $carrierModel) {

            if (!$carrierModel->isActive()) {
                continue;
            }

            $carrierMethods = $carrierModel->getAllowedMethods();

            if (!$carrierMethods) {
                continue;
            }

            $carrierTitle = $this->scopeConfig->getValue(
                'carriers/' . $carrierCode . '/title',
                \Magento\Store\Model\ScopeInterface::SCOPE_STORE
            );

            if (empty($carrierTitle) || ctype_space($carrierTitle)) {
                $carrierTitle = $carrierCode;
            }
            // $methods[$carrierCode] = $carrierTitle;
            $methods[$carrierCode] = [
                'label' => $carrierTitle,
                'value' => $this->getRates($carrierMethods)
            ];
        }
        
        return $methods;
    }

    /**
     * Get shipping carrier allowd rates
     *
     * @param array $carrierMethods
     * @return array
     */
    public function getRates($carrierMethods = [])
    {
        foreach ($carrierMethods as $key => $value) {
            $rate[] = [
                'label' => $value,
                'value' => $key
            ];
        }
        return $rate;
    }

    /**
     * Options getter
     *
     * @return array
     */
    public function toOptionArray()
    {
        return $this->getAllMethods();
    }

}

use model

namespace Bhaveshpp\ShippingRestriction\Model;
use Magento\Checkout\Model\Cart;
use Magento\Catalog\Model\ProductRepository;
use Magento\Framework\Stdlib\DateTime\DateTime;
use Magento\Framework\App\Config\ScopeConfigInterface;

/**
 * Check and return allowed methods
 */
class Check  
{

    /**
     * system config is enable index
     */
    const CONFIG_ENABLE = "shipping_rescriction/general/enable";

    /**
     * system config from day index
     */

    const CONFIG_FROM_DAY = "shipping_rescriction/from/from_day";
    
    /**
     * system config from month index
     */
    const CONFIG_FROM_MONTH = "shipping_rescriction/from/from_month";
    
    /**
     * system config to day index
     */
    const CONFIG_TO_DAY = "shipping_rescriction/to/to_day";
    
    /**
     * system config from month index
     */
    const CONFIG_TO_MONTH = "shipping_rescriction/to/to_month";
    
    /**
     * system config allowed method index
     */
    const CONFIG_ALLOWED_METHOD = "shipping_rescriction/shipping_method/allowed_method";

    /**
     * @var Cart $cart
     */
    protected $cart;
    
    /**
     * @var ProductRepository $productRepository
     */
    protected $productRepository;
    
    /**
     * @var DateTime $dateTime
     */
    protected $dateTime;
    
    /**
     * @var ScopeConfigInterface $scopConfig
     */
    protected $scopConfig;

    /**
     * Initialize
     *
     * @param Cart $cart
     * @param ProductRepository $productRepository
     * @param DateTime $dateTime
     * @param ScopeConfigInterface $scopConfig
     */
    public function __construct(
        Cart $cart,
        ProductRepository $productRepository,
        DateTime $dateTime,
        ScopeConfigInterface $scopConfig
    )
    {
        $this->cart = $cart;
        $this->productRepository = $productRepository;
        $this->dateTime = $dateTime;
        $this->scopConfig = $scopConfig;
    }

    /**
     * Check and return all allowd methods
     *
     * @param array $rates
     * @return array
     */
    public function checkAndReturn($rates)
    {
        if ($this->scopConfig->getValue(self::CONFIG_ENABLE)) {
            return $this->getAllowedMethods($rates);
        }
        return $rates;

    }
    
    /**
     * Return all allowd methods
     *
     * @param array $rates
     * @return array
     */
    public function getAllowedMethods($rates)
    {
        if ($this->getDateCondition() && $this->checkCartItems()) {   
            foreach ($rates as $key => $rate) {
                if ($rate->getData('method') != $this->scopConfig->getValue(self::CONFIG_ALLOWED_METHOD)) {
                    unset($rates[$key]);
                }
            }
        }
        return $rates;
    }

    /**
     * Check cart items has restricted item
     *
     * @return bool
     */
    public function checkCartItems()
    {
        $items = $this->cart->getQuote()->getAllItems();
        foreach ($items as $key => $item) {
            $product = $this->productRepository->getById($item->getProductId());
            if ($product->getData('is_shipping_restricted')) {
                return true;
            }
        }
        
        return false;
    }

    /**
     * Check current date meet condition
     *
     * @return void
     */
    public function getDateCondition()
    {
        $date['day'] = (int)$this->dateTime->date('d'); 
        $date['month'] = (int)$this->dateTime->date('m'); 

        // get config value
        $from['day'] = (int)$this->scopConfig->getValue(self::CONFIG_FROM_DAY);
        $from['month'] = (int)$this->scopConfig->getValue(self::CONFIG_FROM_MONTH);

        $to['day'] = (int)$this->scopConfig->getValue(self::CONFIG_TO_DAY);
        $to['month'] = (int)$this->scopConfig->getValue(self::CONFIG_TO_MONTH);

        if (($from['month'] <= $date['month']) && ($date['month'] <= $to['month'])) {
            if ($from['month'] == $date['month']) {
                if($from['day'] <= $date['day']){
                    return true;
                }
            }
            elseif ($to['month'] == $date['month']) {
                if($to['day'] >= $date['day']){
                    return true;
                }
            }else{
                return true;
            }
        }
        return false;
    }

}


Add Product attribute using datapatch


namespace Tecksky\ShippingRestriction\Setup\Patch\Data;
use Magento\Framework\Setup\Patch\DataPatchInterface;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\ModuleDatasetupInterface;
use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface;
use Magento\Catalog\Model\Product\Attribute\Source\Boolean as SourceBoolean;
use Magento\Catalog\Model\Product\Attribute\Backend\Boolean as BackendBoolean;

/**
 * Class ShippingRestrictedProduct
 */
class ShippingRestrictedProduct implements DataPatchInterface 
{
    /**
     * @var EavSetupFactory $eavSetupFactory
     */
    protected $eavSetupFactory;
    
    /**
     * @var ModuleDataSetupInterface $moduleDataSetup
     */
    protected $moduleDataSetup;
    
    /**
     * Initialize
     *
     * @param EavSetupFactory $eavSetupFactory
     * @param ModuleDataSetupInterface $moduleDataSetup
     */ 
    public function __construct(
        EavSetupFactory $eavSetupFactory,
        ModuleDataSetupInterface $moduleDataSetup
    )
    {
        $this->eavSetupFactory = $eavSetupFactory;
        $this->moduleDataSetup = $moduleDataSetup;
    }

    /**
     * Add product attirbute 
     * Run patch
     *
     * @return void
     */
    public function apply()
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $this->moduleDataSetup]);
        $eavSetup->addAttribute('catalog_product','is_shipping_restricted',[
            'type' => 'int',
            'label' => 'Is Shipping Restricted',
            'input' => 'boolean',
            'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
            'backend' => BackendBoolean::class,
            'source' => SourceBoolean::class,
            'global' => ScopedAttributeInterface::SCOPE_GLOBAL,
            'default' => 0,
            'visible' => true,
            'used_in_product_listing' => true,
            'user_defined' => true,
            'required' => false,
            'group' => 'General',
            'sort_order' => 80
        ]);
    }
    
    /**
     * {@inheritdoc}
     */
    public static function getDependencies() {
        return [];
    }
    
    /**
     * {@inheritdoc}
     */
    public function getAliases() {
        return [];
    }

}