cancel
Showing results for 
Search instead for 
Did you mean: 

Magento 2.1 - How can I handel special transport agencies for some products?

Magento 2.1 - How can I handel special transport agencies for some products?

Hi,

 

i need little bit help with the delivery costs. I have Magento 2.1

What can I do, if special big products can only be shipped with a special transport agency? Can I use in Magento "delivery groups". In my plans every product has 1 of my 3 delivery settings.

  1. DHL parcel (Table Rate (depends on weight))
  2. bulk goods (that is 1. + fixed charge)
  3. special logistic company (fixed charge)

Every product can only be shipped with one of this 3 points. I have this data for each product in my inventory control system, but I dont know how to handel it in magento2.

Can anybody give me some ideas how to implement this in magento?

thank you

regards

1 REPLY

Re: Magento 2.1 - How can I handel special transport agencies for some products?

To solve this, you need to customize the default Magento OR use one of the ready-to-implement solutions. Below, we're going to describe a possible workaround on the example of one of our extensions.

NOTE

Online, you can find a bunch of articles that describe how to create an extension from scratch, register it, add the required files, etc.. Hence, to save time and space here, we won't go through those basic steps. Instead, we'll focus on the essential details.    


1. First, you need 2 plugins that will be responsible for checking availability of your shipping methods. Those that are unavailable at the shopping cart, will be automatically disabled. For example, 2 out of 3 shipping methods can be disabled if a customer puts a special big product (with the weight more than 100, as in your example) into a cart.

Register your plugins in the `di.xml` module at the global level.

 

<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="mageworx_shippingrules_update_rate_result"
                type="MageWorx\ShippingRules\Model\Plugin\Shipping\Rate\Result\Append"
                sortOrder="10"
                disabled="false"/>
        <plugin name="mageworx_shippingrules_update_disabled_or_enabled_rates"
                type="MageWorx\ShippingRules\Model\Plugin\Shipping\Rate\Result\GetAllRates"
                sortOrder="11"
                disabled="false"/>
    </type>
</config> 

And create corresponding classes:  `MageWorx\ShippingRules\Model\Plugin\Shipping\Rate\Result\Append` and  `MageWorx\ShippingRules\Model\Plugin\Shipping\Rate\Result\GetAllRates`.

NOTE

`MageWorx\ShippingRules` is the name of our company/extension. Feel free to replace it with your data wherever needed.

In the plugin `mageworx_shippingrules_update_rate_result`, we add validation necessary for each method, using `beforeAppend`. We'll get something like this:

 

/**
 * Validate each shipping method before append.
 * Apply the rules action if validation was successful.
 * Can mark some rules as disabled. The disabled rules will be removed in the class
 * @see MageWorx\ShippingRules\Observer\Sales\Quote\Address\CollectTotalsAfter
 * by checking the value of this mark in the rate object.
 *
 * NOTE: If you have some problems with the rules and the shipping methods, start debugging from here.
 *
 * @param \Magento\Shipping\Model\Rate\Result $subject
 * @param \Magento\Quote\Model\Quote\Address\RateResult\AbstractResult|\Magento\Shipping\Model\Rate\Result $result
 * @return array
 */
public function beforeAppend($subject, $result)
{
    if (!$result instanceof \Magento\Quote\Model\Quote\Address\RateResult\Method) {
        return [$result];
    }

    $methodsUnavailableForHeavyWeightItems = [
        'faltrate_flatrate',
        'ups_XDM',
        'ups_XPR',
        'ups_WXS',
        'carrier_method',
        // ... add here your method codes
    ];
    $methodCode = $result->getCarrier() . '_' . $result->getMethod();
    if (!in_array($methodCode, $methodsUnavailableForHeavyWeightItems)) {
        return [$result];
    }

    /** @var \Magento\Quote\Model\Quote $quote */
    $quote = $this->session->getQuote();
    $quoteItems = $quote->getAllItems();
    $heavyWeightFlag = false;
    foreach ($quoteItems as $item) {
        if ($item->getWeight() > 100) {
            $heavyWeightFlag = true;
            continue;
        }
    }

    if ($heavyWeightFlag) {
        $result->setIsDisabled(true);
    }

    return [$result];
}



The 1-st check will cut down unnecessary classes in the body of the method. There's no any use in them. What we are interested in is the instance of the class `\Magento\Quote\Model\Quote\Address\RateResult\Method`.


In the variable `$methodsUnavailableForHeavyWeightItems`, we store the codes of those methods, that won't be used if there's is a big, 'heavy' product in a shopping cart (although, it's possible to use any condition for such a check).

The 2-nd check will let you figure out whether it's worth to process the current method.  If not (this method is not in the array), we don't need to to anything - just bring back the result, as it is.

Next, we are sorting all quote items in search of the 'heavy' big product (as I said, in our example, it's a product with the weight more than 100 items). If we find such a product, we mark it with the flag `$heavyWeightFlag` in the true value and finish a cycle.

The last thing that is left to do is to check the flag. And in case it contains the true value, using the corresponding mark set our method as 'is_disabled'. That is done to identify this method in the future and exclude it from the list.  

NOTE


In the attribute `$this->session`, there is an instance of one of the `Session|\Magento\Backend\Model\Session\Quote` classes. In order to get front-end and back-end sessions (depending on the place where method selection takes place - on the front-end or at the back-end), use the following code in your plugin constructor.

 

/** @var Session|\Magento\Backend\Model\Session\Quote */
protected $session;

/**
 * @param \Magento\Checkout\Model\Session $checkoutSession
 * @param \Magento\Backend\Model\Session\Quote $backendQuoteSession
 * @param \Magento\Framework\App\State $state
 * @internal param Session $session
 */
public function __construct(
    \Magento\Checkout\Model\Session $checkoutSession,
    \Magento\Backend\Model\Session\Quote $backendQuoteSession,
    \Magento\Framework\App\State $state
) {
    if ($state->getAreaCode() == \Magento\Framework\App\Area::AREA_ADMINHTML) {
        $this->session = $backendQuoteSession;
    } else {
        $this->session = $checkoutSession;
    }
}

With the second plugin, we acquire all available shipping methods and check weather each of them is disabled or not.

This is how this class looks like:

 

 

/**
 * Copyright © 2016 MageWorx. All rights reserved.
 * See LICENSE.txt for license details.
 */

namespace MageWorx\ShippingRules\Model\Plugin\Shipping\Rate\Result;

class GetAllRates
{

    /**
     * Disable the marked shipping rates. Rates disabling in the
     * @see MageWorx\ShippingRules\Model\RulesApplier::disableShippingMethod()
     *
     * NOTE: If you can not see some of the shipping rates, start debugging from here. At first, check 'is_disabled'
     * param in the shipping rate object.
     *
     * @param \Magento\Shipping\Model\Rate\Result $subject
     * @param array $result
     * @return array
     */
    public function afterGetAllRates($subject, $result)
    {
        foreach ($result as $key => $rate) {
            if ($rate->getIsDisabled()) {
                unset($result[$key]);
            }
        }

        return $result;
    }
}

If some of the methods has the 'is_disabled' mark as the real value, we just exclude it from the results.

As a results, on any page with shipping methods, be it an estimate shipping block in shopping cart or the cart page itself, you'll see only those methods that correspond to your set conditions.

NOTE

You can obtain a list of all available system shipping methods from the code the following way:

 

 

/**
 * Return array of carriers.
 * If $isActiveOnlyFlag is set to true, will return only active carriers
 *
 * @param bool $isActiveOnlyFlag
 * @return array
 */
public function getAvailableMethods($isActiveOnlyFlag = false)
{
    $carriers = $this->shippingConfig->getAllCarriers();
    foreach ($carriers as $carrierCode => $carrierModel) {
        if (!$carrierModel->isActive() && (bool)$isActiveOnlyFlag === true) {
            continue;
        }
        $carrierMethods = $carrierModel->getAllowedMethods();
        if (!$carrierMethods) {
            continue;
        }
        foreach ($carrierMethods as $methodCode => $methodTitle) {
            $methods[] = $carrierCode . '_' . $methodCode;
        }
    }

    return !empty($methods) ? $methods : [];
}

Where `$this->shippingConfig` is an instance of the class `Magento\Shipping\Model\Config`

The result of of the 1st plugin for a product with the weight of 1 item looks like this:
b0f2cce678c0c9e7461b12341f458c45.png

This is the shopping cart result, ups_WXS shipping method is still available because the weight limit is not exceeded:

3dc10f3161ac2e4679383558c66bee47.png

 

However, if you change it, and make, for example, 101, this shipping method will disappear from the list:
1552bac38ddea1d4fbb9ad4ad0e42186.png

 

It will be available again, if you delete it from the list:
84b204377b2a7f1a0d4721fde3c0053b.png


e7d537176f0f917a71045623d69b60ec.png

 

At the checkout:


f3d3cac03678318af2d569d757fc7e79.png

 

 

This is how disabling shipping methods works in our extension - Shipping Suite.

Should you have any questions, feel free to drop me a line. 

______________________________________________________________
Innovative, top-performing Magento Extensions (with an array of FREE tools).