Magento 2.4.4 – 为运费计算添加包装的皮重

huangapple go评论48阅读模式
英文:

Magento 2.4.4 - Add a Tare weight for packaging for shipping calculation

问题

问题是我们有很多非常小的物品,重量在2-50克之间,而一个盒子加上包装的重量为100-200克。

包装通常是最重的部分。

如果我们将物品的重量(在产品中)设置为实际物品的重量,那么当人们订购很多东西时,盒子的重量可能会使总重量超过所选择的邮费方式。

如果我们将盒子的重量加到物品上,那么邮费的成本会变得非常昂贵,这意味着人们不会购买。

我该如何为每种包装类型设置一个盒子的重量?

是否有一个扩展程序可以实现这个功能,或者是否有一种方法可以在Magento计算包装重量之前添加一些逻辑来添加一个盒子的皮重。

这似乎很奇怪,因为这似乎是每个在线销售物品的人都必须做的事情。

我想我需要一个检查订单物品重量的东西。

如果物品总重量小于1千克,则添加(输入小盒子的重量)。

如果物品总重量小于2千克但大于1千克,则添加(输入中盒子的重量)。

如果物品总重量大于2千克,则添加(输入大盒子的重量)。

期望能够输入包装的基本重量。

英文:

The issue is that we have lots of items that are very small 2-50g and a box + packaging weighs 100-200g

The package is often the heaviest part

If we set the item weight (in the product) as the actual weight of the item then when people order lots of things the box weight can make the total weight go over the chosen postage method.

If we ad the box weight to the item then it makes the cost of postage massively expensive and means people don't make the purchase.

How can I set a box weight for each each package type.

is there an extension for this or is there a way to add some logic to add a tare weight for the box before Magento calculates the weight of a package.
It seems odd that this isn't a feature of Magento as this seems like something everyone that sells items online would have to do.

I guess i would need some thing that checks order items weight

IF items total weight is less than 1KG THEN add (entered weight for small box)
IF items total weight is less the 2GK but Greater than 1KG then add (entered weight for Medium box)
IF items total is greater than 2KG then add (entered weight for Large Box)

expecting to be able to enter a packaging base weight for parcels

答案1

得分: 1

这个流程是基于以下假设的:包裹的重量和类型信息是为管理员和运费固定的。

步骤1:创建etc/db_schema.xml文件

<?xml version="1.0"?>

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="sales_order" resource="default" engine="innodb" comment="sales_order">
        <column xsi:type="int" name="box_weight" default="0" comment="Box Weight" />
        <column xsi:type="varchar" name="box_type" nullable="false" length="255" comment="Box Type" />
    </table>
    <table name="sales_order_grid" resource="default" engine="innodb" comment="sales_order">
        <column xsi:type="int" name="box_weight" default="0" comment="Box Weight" />
        <column xsi:type="varchar" name="box_type" nullable="false" length="255" comment="Box Type" />
    </table>
</schema>

步骤2:创建Model/ResourceModel/Order/Grid/Collection.php文件

<?php

namespace Sunarc\Custom\Model\ResourceModel\Order\Grid;

use Magento\Framework\Data\Collection\Db\FetchStrategyInterface as CoreFetchStrategy;
use Magento\Framework\Data\Collection\EntityFactoryInterface as CoreEntityFactory;
use Magento\Framework\Event\ManagerInterface as CoreEventManager;
use Magento\Sales\Model\ResourceModel\Order\Grid\Collection as CoreSalesGrid;
use Psr\Log\LoggerInterface as Logger;


class Collection extends CoreSalesGrid
{
    /**
     * @param CoreEntityFactory $entityFactory
     * @param Logger            $logger       
     * @param CoreFetchStrategy $fetchStrategy
     * @param CoreEventManager  $eventManager 
     * @param string            $mainTable    
     * @param string            $resourceModel
     */
    public function __construct(
        CoreEntityFactory $entityFactory,
        Logger $logger,
        CoreFetchStrategy $fetchStrategy,
        CoreEventManager $eventManager,
        $mainTable = 'sales_order_grid',
        $resourceModel = \Magento\Sales\Model\ResourceModel\Order::class
    ) {
        parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $mainTable, $resourceModel);
    }

    protected function _renderFiltersBefore()
    {
        $joinTable = $this->getTable('sales_order');
        $this->getSelect()->joinLeft(
            $joinTable,
            'main_table.entity_id = sales_order.entity_id',
            ['box_weight','box_type']
        );
        parent::_renderFiltersBefore();
    }
}

步骤3:现在,创建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">
    <preference for="Magento\Sales\Controller\Order\History" type="Sunarc\Custom\Controller\Order\History" />

    <type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
        <arguments>
            <argument name="collections" xsi:type="array">
                <item name="sales_order_grid_data_source" xsi:type="string">Sunarc\Custom\Model\ResourceModel\Order\Grid\Collection</item>
            </argument>
        </arguments>
    </type>
    <type name="Sunarc\Custom\Model\ResourceModel\Order\Grid\Collection">
        <arguments>
            <argument name="mainTable" xsi:type="string">sales_order_grid</argument>
            <argument name="resourceModel" xsi:type="string">Magento\Sales\Model\ResourceModel\Order</argument>
        </arguments>
    </type>

</config>

步骤4:创建view/adminhtml/ui_component/sales_order_grid.xml文件

<?xml version="1.0" encoding="UTF-8"?>

<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <columns name="sales_order_columns">

        <column name="box_weight">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="filter" xsi:type="string">text</item>
                    <item name="label" xsi:type="string" translate="true">Parcel Weight</item>
                </item>
            </argument>
        </column>

        <column name="box_type">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="filter" xsi:type="string">text</item>
                    <item name="label" xsi:type="string" translate="true">Box Type</item>
                </item>
            </argument>
        </column>
    </columns>
</listing>

步骤5:创建etc/events.xml文件

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="sales_order_save_before">
        <observer name="weight" instance="Sunarc\Custom\Observer\Weight" />
    </event>
</config>

步骤6:创建Observer/Weight.php文件并编写自定义逻辑

<?php

namespace Sunarc\Custom\Observer;

use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Quote\Model\QuoteFactory;

class Weight implements ObserverInterface
{

    public function __construct(QuoteFactory $quoteFactory)
    {
        $this->quoteFactory = $quoteFactory;
    }
    /**
     * Below is the method that will fire whenever the event runs!
     *
     * @param Observer $observer
     */
    public function execute(Observer $observer)
    {

        //WRITE YOUR CUSTOM LOGIC HERE
        $order = $observer->getEvent()->getOrder();

        if ($order->getData('weight') == 1) {
            $order->setData('box_weight', 5); // Assumed wight of small parcel
            $order->setData('box_type', 'Small');
        } elseif ($order->getData('weight') > 1 && $order->getData('weight') <= 2) {
            $order->setData('box_weight', 7); // Assumed wight of Medium parcel
            $order->setData('box_type', 'Medium');
        } else {
            $order->setData('box_weight', 10);  // Assumed wight of Large parcel
            $order->setData('box_type', 'Large');
        }
    }
}

以上是要翻译的内容。

英文:

This flow is set on Assumption that the Parcel weight and type information is for the admin And shipping charge is fixed.

Step 1:- create etc/db_schema.xml

<?xml version="1.0"?>

&lt;schema xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:noNamespaceSchemaLocation=&quot;urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd&quot;&gt;
	&lt;table name=&quot;sales_order&quot; resource=&quot;default&quot; engine=&quot;innodb&quot; comment=&quot;sales_order&quot;&gt;
		&lt;column xsi:type=&quot;int&quot; name=&quot;box_weight&quot; default=&quot;0&quot; comment=&quot;Box Weight&quot; /&gt;
		&lt;column xsi:type=&quot;varchar&quot; name=&quot;box_type&quot; nullable=&quot;false&quot; length=&quot;255&quot; comment=&quot;Box Type&quot; /&gt;
	&lt;/table&gt;
	&lt;table name=&quot;sales_order_grid&quot; resource=&quot;default&quot; engine=&quot;innodb&quot; comment=&quot;sales_order&quot;&gt;
		&lt;column xsi:type=&quot;int&quot; name=&quot;box_weight&quot; default=&quot;0&quot; comment=&quot;Box Weight&quot; /&gt;
		&lt;column xsi:type=&quot;varchar&quot; name=&quot;box_type&quot; nullable=&quot;false&quot; length=&quot;255&quot; comment=&quot;Box Type&quot; /&gt;
	&lt;/table&gt;
&lt;/schema&gt;

Step 2: Create Model/ResourceModel/Order/Grid/Collection.php file

&lt;?php

namespace Sunarc\Custom\Model\ResourceModel\Order\Grid;
 
use Magento\Framework\Data\Collection\Db\FetchStrategyInterface as CoreFetchStrategy;
use Magento\Framework\Data\Collection\EntityFactoryInterface as CoreEntityFactory;
use Magento\Framework\Event\ManagerInterface as CoreEventManager;
use Magento\Sales\Model\ResourceModel\Order\Grid\Collection as CoreSalesGrid;
use Psr\Log\LoggerInterface as Logger;
 

class Collection extends CoreSalesGrid
{
    /**
     * @param CoreEntityFactory $entityFactory
     * @param Logger            $logger       
     * @param CoreFetchStrategy $fetchStrategy
     * @param CoreEventManager  $eventManager 
     * @param string            $mainTable    
     * @param string            $resourceModel
     */
    public function __construct(
        CoreEntityFactory $entityFactory,
        Logger $logger,
        CoreFetchStrategy $fetchStrategy,
        CoreEventManager $eventManager,
        $mainTable = &#39;sales_order_grid&#39;,
        $resourceModel = \Magento\Sales\Model\ResourceModel\Order::class
    ) {
        parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $mainTable, $resourceModel);
    }
 
    protected function _renderFiltersBefore()
    {
        $joinTable = $this-&gt;getTable(&#39;sales_order&#39;);
        $this-&gt;getSelect()-&gt;joinLeft(
            $joinTable,
            &#39;main_table.entity_id = sales_order.entity_id&#39;,
            [&#39;box_weight&#39;,&#39;box_type&#39;]
        );
        parent::_renderFiltersBefore();
    }
}

Step 3: Now, Create etc/di.xml file to add custom column data into order grid.

&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;config xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:noNamespaceSchemaLocation=&quot;urn:magento:framework:ObjectManager/etc/config.xsd&quot;&gt;
    &lt;preference for=&quot;Magento\Sales\Controller\Order\History&quot; type=&quot;Sunarc\Custom\Controller\Order\History&quot; /&gt;

    &lt;type name=&quot;Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory&quot;&gt;
        &lt;arguments&gt;
            &lt;argument name=&quot;collections&quot; xsi:type=&quot;array&quot;&gt;
                &lt;item name=&quot;sales_order_grid_data_source&quot; xsi:type=&quot;string&quot;&gt;Sunarc\Custom\Model\ResourceModel\Order\Grid\Collection&lt;/item&gt;
            &lt;/argument&gt;
        &lt;/arguments&gt;
    &lt;/type&gt;
    &lt;type name=&quot;Sunarc\Custom\Model\ResourceModel\Order\Grid\Collection&quot;&gt;
        &lt;arguments&gt;
            &lt;argument name=&quot;mainTable&quot; xsi:type=&quot;string&quot;&gt;sales_order_grid&lt;/argument&gt;
            &lt;argument name=&quot;resourceModel&quot; xsi:type=&quot;string&quot;&gt;Magento\Sales\Model\ResourceModel\Order&lt;/argument&gt;
        &lt;/arguments&gt;
    &lt;/type&gt;

&lt;/config&gt;

Step 4 : create view/adminhtml/ui_component/sales_order_grid.xml

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;

&lt;listing xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:noNamespaceSchemaLocation=&quot;urn:magento:module:Magento_Ui:etc/ui_configuration.xsd&quot;&gt;
    &lt;columns name=&quot;sales_order_columns&quot;&gt;

        &lt;column name=&quot;box_weight&quot;&gt;
            &lt;argument name=&quot;data&quot; xsi:type=&quot;array&quot;&gt;
                &lt;item name=&quot;config&quot; xsi:type=&quot;array&quot;&gt;
                    &lt;item name=&quot;filter&quot; xsi:type=&quot;string&quot;&gt;text&lt;/item&gt;
                    &lt;item name=&quot;label&quot; xsi:type=&quot;string&quot; translate=&quot;true&quot;&gt;Parcel Weight&lt;/item&gt;
                &lt;/item&gt;
            &lt;/argument&gt;
        &lt;/column&gt;

        &lt;column name=&quot;box_type&quot;&gt;
            &lt;argument name=&quot;data&quot; xsi:type=&quot;array&quot;&gt;
                &lt;item name=&quot;config&quot; xsi:type=&quot;array&quot;&gt;
                    &lt;item name=&quot;filter&quot; xsi:type=&quot;string&quot;&gt;text&lt;/item&gt;
                    &lt;item name=&quot;label&quot; xsi:type=&quot;string&quot; translate=&quot;true&quot;&gt;Box Type&lt;/item&gt;
                &lt;/item&gt;
            &lt;/argument&gt;
        &lt;/column&gt;
    &lt;/columns&gt;
&lt;/listing&gt;

Step 5:- Create etc/events.xml

&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;config xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:noNamespaceSchemaLocation=&quot;urn:magento:framework:Event/etc/events.xsd&quot;&gt;
    &lt;event name=&quot;sales_order_save_before&quot;&gt;
        &lt;observer name=&quot;weight&quot; instance=&quot;Sunarc\Custom\Observer\Weight&quot; /&gt;
    &lt;/event&gt;
&lt;/config&gt;

step 6: Create Observer/Weight.php and write your custom logic

&lt;?php

namespace Sunarc\Custom\Observer;

use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Quote\Model\QuoteFactory;

class Weight implements ObserverInterface
{

    public function __construct(QuoteFactory $quoteFactory)
    {
        $this-&gt;quoteFactory = $quoteFactory;
    }
    /**
     * Below is the method that will fire whenever the event runs!
     *
     * @param Observer $observer
     */
    public function execute(Observer $observer)
    {

        //WRITE YOUR CUSTOM LOGIC HERE
        $order = $observer-&gt;getEvent()-&gt;getOrder();

        if ($order-&gt;getData(&#39;weight&#39;) == 1) {
            $order-&gt;setData(&#39;box_weight&#39;, 5); // Assumed wight of small parcel
            $order-&gt;setData(&#39;box_type&#39;, &#39;Small&#39;);
        } elseif ($order-&gt;getData(&#39;weight&#39;) &gt; 1 &amp;&amp; $order-&gt;getData(&#39;weight&#39;) &lt;= 2) {
            $order-&gt;setData(&#39;box_weight&#39;, 7); // Assumed wight of Medium parcel
            $order-&gt;setData(&#39;box_type&#39;, &#39;Medium&#39;);
        } else {
            $order-&gt;setData(&#39;box_weight&#39;, 10);  // Assumed wight of Large parcel
            $order-&gt;setData(&#39;box_type&#39;, &#39;Large&#39;);
        }
    }
}

答案2

得分: 1

步骤1:创建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\OfflineShipping\Model\Carrier\Tablerate'>         
        <plugin name='tablerate_plugin' type='Sunarc\Custom\Plugin\TableratePlugin' sortOrder='10' disabled='false'  />     
    </type>

</config>

步骤2:创建一个插件来添加自定义代码


namespace Sunarc\Custom\Plugin;

use Magento\Framework\Exception\LocalizedException;
use Magento\Quote\Model\Quote\Address\RateRequest;

class TableratePlugin
{


    /**
     * @var \Magento\Catalog\Api\ProductRepositoryInterface
     */
    private $productRepository;

    /**
     * @var \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory
     */
    private $rateErrorFactory;

    /**
     * @var string
     */
    protected $_code = 'tablerate';
    /**
     * @var string
     */
    protected $_defaultConditionName = 'package_weight';

    /**
     * @var \Magento\Shipping\Model\Rate\ResultFactory
     */
    protected $_rateResultFactory;

    /**
     * @var \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory
     */
    protected $_resultMethodFactory;

    public function __construct(
        \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory,
        \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $resultMethodFactory,
        \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
        \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
    ) {
        $this->_rateResultFactory = $rateResultFactory;
        $this->_resultMethodFactory = $resultMethodFactory;
        $this->rateErrorFactory = $rateErrorFactory;
        $this->productRepository = $productRepository;
    }
    public function aroundCollectRates(
        \Magento\OfflineShipping\Model\Carrier\Tablerate $subject,
        \Closure $proceed,
        RateRequest $request
    ) {

        if (!$subject->getConfigFlag('active')) {
            return false;
        }
        // exclude Virtual products price from Package value if pre-configured
        if (!$subject->getConfigFlag('include_virtual_price') && $request->getAllItems()) {
            foreach ($request->getAllItems() as $item) {
                if ($item->getParentItem()) {
                    continue;
                }
                if ($item->getHasChildren() && $item->isShipSeparately()) {
                    foreach ($item->getChildren() as $child) {
                        if ($child->getProduct()->isVirtual()) {
                            $request->setPackageValue($request->getPackageValue() - $child->getBaseRowTotal());
                        }
                    }
                } elseif ($item->getProduct()->isVirtual()) {
                    $request->setPackageValue($request->getPackageValue() - $item->getBaseRowTotal());
                }
            }
        }

        // Free shipping by qty
        $freeQty = 0;
        $freePackageValue = 0;

        if ($request->getAllItems()) {
            foreach ($request->getAllItems() as $item) {
                if ($item->getProduct()->isVirtual() || $item->getParentItem()) {
                    continue;
                }

                if ($item->getHasChildren() && $item->isShipSeparately()) {
                    foreach ($item->getChildren() as $child) {
                        if ($child->getFreeShipping() && !$child->getProduct()->isVirtual()) {
                            $freeShipping = is_numeric($child->getFreeShipping()) ? $child->getFreeShipping() : 0;
                            $freeQty += $item->getQty() * ($child->getQty() - $freeShipping);
                        }
                    }
                } elseif ($item->getFreeShipping() || $item->getAddress()->getFreeShipping()) {
                    $freeShipping = $item->getFreeShipping() ?
                        $item->getFreeShipping() : $item->getAddress()->getFreeShipping();
                    $freeShipping = is_numeric($freeShipping) ? $freeShipping : 0;
                    $freeQty += $item->getQty() - $freeShipping;
                    $freePackageValue += $item->getBaseRowTotal();
                }
            }
            $oldValue = $request->getPackageValue();
            $request->setPackageValue($oldValue - $freePackageValue);
        }

        if (!$request->getConditionName()) {
            $conditionName = $subject->getConfigData('condition_name');
            $request->setConditionName($conditionName ? $conditionName : $this->_defaultConditionName);
        }


        // Package weight and qty free shipping
        $oldWeight = $request->getPackageWeight();
        $oldQty = $request->getPackageQty();


        // ADD YOUR CUSTOM CODE HERE //

        if ($request->getFreeMethodWeight() == 1) {
            $request->setPackageWeight(50);
        } elseif ($request->getFreeMethodWeight() > 1 && $request->getFreeMethodWeight() <= 2) {
            $request->setPackageWeight(40);
        } else {
            $request->setPackageWeight(40);
        }

        // $request->setPackageWeight($request->getFreeMethodWeight());
        $request->setPackageQty($oldQty - $freeQty);

        /** @var \Magento\Shipping\Model\Rate\Result $result */
        $result = $this->_rateResultFactory->create();
        $rate = $subject->getRate($request);

        $request->setPackageWeight($oldWeight);
        $request->setPackageQty($oldQty);

        if (!empty($rate) && $rate['price'] >= 0) {
            if ($request->getPackageQty() == $freeQty) {
                $shippingPrice = 0;
            } else {
                $shippingPrice = $subject->getFinalPriceWithHandlingFee($rate['price']);
            }
            $method = $this->createShippingMethod($shippingPrice, $rate['cost'], $subject, $request);
            $result->append($method);
        } elseif ($request->getPackageQty() == $freeQty) {

            /**
             * Promotion rule was applied for the whole cart.
             *  In this case all other shipping methods could be omitted
             * Table rate shipping method with 0$ price must be shown if grand total is more than minimal value.
             * Free package weight has been already taken into account.
             */
            $request->setPackageValue($freePackageValue);
            $request->setPackageQty($freeQty);
            $rate = $subject->getRate($request);
            if (!empty($rate) && $rate['price'] >= 0) {
                $method = $this->createShippingMethod(0, 0, $subject, $request);
                $result->append($method);
            }
        } else {
            /** @var \Magento\Quote\Model\Quote\Address\RateResult\Error $error */
            $error = $this->rateErrorFactory->create(
                [
                    'data' => [
                        'carrier' => $this->_code,
                        'carrier_title' => $subject->getConfigData('title'),
                        'error_message' => $subject->getConfigData('specificerrmsg'),
                    ],
                ]
            );
            $result->append($error);
        }
        return $result;
    }

    /**
     * Get the method object based on the shipping price and cost
     *
     * @param float $shippingPrice
     * @param float $cost
     * @return \Magento\Quote\Model\Quote\Address\RateResult\Method
     */
    private function createShippingMethod($shippingPrice, $cost, $subject, $request)
    {

        /** @var  \Magento\Quote\Model\Quote\Address\RateResult\Method $method */
        $method = $this->_resultMethodFactory->create();

        $method->setCarrier('tablerate');
        $method->setCarrierTitle($subject->getConfigData('title'));

        $method->setMethod('bestway');
        $method->setMethodTitle($subject->getConfigData('name'));

        $method->setPrice($shippingPrice);
        $method->setCost($cost);
        return $method;
    }
}

根据你的逻辑代码计算重量,价格将相应更新。

<details>
<summary>英文:</summary>

Step 1:- Create di.xml

    &lt;?xml version=&quot;1.0&quot;?&gt; &lt;config xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:noNamespaceSchemaLocation=&quot;urn:magento:framework:ObjectManager/etc/config.xsd&quot;&gt;
    
        &lt;type name=&#39;Magento\OfflineShipping\Model\Carrier\Tablerate&#39;&gt;         
            &lt;plugin name=&#39;tablerate_plugin&#39; type=&#39;Sunarc\Custom\Plugin\TableratePlugin&#39; sortOrder=&#39;10&#39; disabled=&#39;false&#39;  /&gt;     
        &lt;/type&gt;
    
    &lt;/config&gt;

Step 2:- Create a plugin to add your custom code

    &lt;?php
    
    namespace Sunarc\Custom\Plugin;
    
    use Magento\Framework\Exception\LocalizedException;
    use Magento\Quote\Model\Quote\Address\RateRequest;
    
    class TableratePlugin
    {
    
    
        /**
         * @var \Magento\Catalog\Api\ProductRepositoryInterface
         */
        private $productRepository;
    
        /**
         * @var \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory
         */
        private $rateErrorFactory;
    
        /**
         * @var string
         */
        protected $_code = &#39;tablerate&#39;;
        /**
         * @var string
         */
        protected $_defaultConditionName = &#39;package_weight&#39;;
    
        /**
         * @var \Magento\Shipping\Model\Rate\ResultFactory
         */
        protected $_rateResultFactory;
    
        /**
         * @var \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory
         */
        protected $_resultMethodFactory;
    
        public function __construct(
            \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory,
            \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $resultMethodFactory,
            \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
            \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
        ) {
            $this-&gt;_rateResultFactory = $rateResultFactory;
            $this-&gt;_resultMethodFactory = $resultMethodFactory;
            $this-&gt;rateErrorFactory = $rateErrorFactory;
            $this-&gt;productRepository = $productRepository;
        }
        public function aroundCollectRates(
            \Magento\OfflineShipping\Model\Carrier\Tablerate $subject,
            \Closure $proceed,
            RateRequest $request
        ) {
    
            if (!$subject-&gt;getConfigFlag(&#39;active&#39;)) {
                return false;
            }
            // exclude Virtual products price from Package value if pre-configured
            if (!$subject-&gt;getConfigFlag(&#39;include_virtual_price&#39;) &amp;&amp; $request-&gt;getAllItems()) {
                foreach ($request-&gt;getAllItems() as $item) {
                    if ($item-&gt;getParentItem()) {
                        continue;
                    }
                    if ($item-&gt;getHasChildren() &amp;&amp; $item-&gt;isShipSeparately()) {
                        foreach ($item-&gt;getChildren() as $child) {
                            if ($child-&gt;getProduct()-&gt;isVirtual()) {
                                $request-&gt;setPackageValue($request-&gt;getPackageValue() - $child-&gt;getBaseRowTotal());
                            }
                        }
                    } elseif ($item-&gt;getProduct()-&gt;isVirtual()) {
                        $request-&gt;setPackageValue($request-&gt;getPackageValue() - $item-&gt;getBaseRowTotal());
                    }
                }
            }
    
            // Free shipping by qty
            $freeQty = 0;
            $freePackageValue = 0;
    
            if ($request-&gt;getAllItems()) {
                foreach ($request-&gt;getAllItems() as $item) {
                    if ($item-&gt;getProduct()-&gt;isVirtual() || $item-&gt;getParentItem()) {
                        continue;
                    }
    
                    if ($item-&gt;getHasChildren() &amp;&amp; $item-&gt;isShipSeparately()) {
                        foreach ($item-&gt;getChildren() as $child) {
                            if ($child-&gt;getFreeShipping() &amp;&amp; !$child-&gt;getProduct()-&gt;isVirtual()) {
                                $freeShipping = is_numeric($child-&gt;getFreeShipping()) ? $child-&gt;getFreeShipping() : 0;
                                $freeQty += $item-&gt;getQty() * ($child-&gt;getQty() - $freeShipping);
                            }
                        }
                    } elseif ($item-&gt;getFreeShipping() || $item-&gt;getAddress()-&gt;getFreeShipping()) {
                        $freeShipping = $item-&gt;getFreeShipping() ?
                            $item-&gt;getFreeShipping() : $item-&gt;getAddress()-&gt;getFreeShipping();
                        $freeShipping = is_numeric($freeShipping) ? $freeShipping : 0;
                        $freeQty += $item-&gt;getQty() - $freeShipping;
                        $freePackageValue += $item-&gt;getBaseRowTotal();
                    }
                }
                $oldValue = $request-&gt;getPackageValue();
                $request-&gt;setPackageValue($oldValue - $freePackageValue);
            }
    
            if (!$request-&gt;getConditionName()) {
                $conditionName = $subject-&gt;getConfigData(&#39;condition_name&#39;);
                $request-&gt;setConditionName($conditionName ? $conditionName : $this-&gt;_defaultConditionName);
            }
    
    
            // Package weight and qty free shipping
            $oldWeight = $request-&gt;getPackageWeight();
            $oldQty = $request-&gt;getPackageQty();
    
    
            // ADD YOUR CUSTOM CODE HERE //
    
            if ($request-&gt;getFreeMethodWeight() == 1) {
                $request-&gt;setPackageWeight(50);
            } elseif ($request-&gt;getFreeMethodWeight() &gt; 1 &amp;&amp; $request-&gt;getFreeMethodWeight() &lt;= 2) {
                $request-&gt;setPackageWeight(40);
            } else {
                $request-&gt;setPackageWeight(40);
            }
    
            // $request-&gt;setPackageWeight($request-&gt;getFreeMethodWeight());
            $request-&gt;setPackageQty($oldQty - $freeQty);
    
            /** @var \Magento\Shipping\Model\Rate\Result $result */
            $result = $this-&gt;_rateResultFactory-&gt;create();
            $rate = $subject-&gt;getRate($request);
    
            $request-&gt;setPackageWeight($oldWeight);
            $request-&gt;setPackageQty($oldQty);
    
            if (!empty($rate) &amp;&amp; $rate[&#39;price&#39;] &gt;= 0) {
                if ($request-&gt;getPackageQty() == $freeQty) {
                    $shippingPrice = 0;
                } else {
                    $shippingPrice = $subject-&gt;getFinalPriceWithHandlingFee($rate[&#39;price&#39;]);
                }
                $method = $this-&gt;createShippingMethod($shippingPrice, $rate[&#39;cost&#39;], $subject, $request);
                $result-&gt;append($method);
            } elseif ($request-&gt;getPackageQty() == $freeQty) {
    
                /**
                 * Promotion rule was applied for the whole cart.
                 *  In this case all other shipping methods could be omitted
                 * Table rate shipping method with 0$ price must be shown if grand total is more than minimal value.
                 * Free package weight has been already taken into account.
                 */
                $request-&gt;setPackageValue($freePackageValue);
                $request-&gt;setPackageQty($freeQty);
                $rate = $subject-&gt;getRate($request);
                if (!empty($rate) &amp;&amp; $rate[&#39;price&#39;] &gt;= 0) {
                    $method = $this-&gt;createShippingMethod(0, 0, $subject, $request);
                    $result-&gt;append($method);
                }
            } else {
                /** @var \Magento\Quote\Model\Quote\Address\RateResult\Error $error */
                $error = $this-&gt;rateErrorFactory-&gt;create(
                    [
                        &#39;data&#39; =&gt; [
                            &#39;carrier&#39; =&gt; $this-&gt;_code,
                            &#39;carrier_title&#39; =&gt; $subject-&gt;getConfigData(&#39;title&#39;),
                            &#39;error_message&#39; =&gt; $subject-&gt;getConfigData(&#39;specificerrmsg&#39;),
                        ],
                    ]
                );
                $result-&gt;append($error);
            }
            return $result;
        }
    
        /**
         * Get the method object based on the shipping price and cost
         *
         * @param float $shippingPrice
         * @param float $cost
         * @return \Magento\Quote\Model\Quote\Address\RateResult\Method
         */
        private function createShippingMethod($shippingPrice, $cost, $subject, $request)
        {
    
            /** @var  \Magento\Quote\Model\Quote\Address\RateResult\Method $method */
            $method = $this-&gt;_resultMethodFactory-&gt;create();
    
            $method-&gt;setCarrier(&#39;tablerate&#39;);
            $method-&gt;setCarrierTitle($subject-&gt;getConfigData(&#39;title&#39;));
    
            $method-&gt;setMethod(&#39;bestway&#39;);
            $method-&gt;setMethodTitle($subject-&gt;getConfigData(&#39;name&#39;));
    
            $method-&gt;setPrice($shippingPrice);
            $method-&gt;setCost($cost);
            return $method;
        }
    }

You can calculate the weight according to your logic code and price will get updated accordingly.

</details>



huangapple
  • 本文由 发表于 2023年1月8日 21:54:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/75048282.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定