To override the functionality of flatrate using plugin for private method.
1st Step: we need to add in 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\OfflineShipping\Model\Carrier\Flatrate">
<plugin name="vendor_module_offlineshipping_carrier_flatrate" type="Vendor\Module\Plugin\Flatrate" />
</type>
<type name="Magento\OfflineShipping\Model\Config\Source\Flatrate">
<plugin name="vendor_module_option_variable" type="Vendor\Module\Model\Config\Source\Flatrate"/>
</type>
</config>
2nd step: we need to override the optionArray for flatrate using plugin to show vendor option in admin side
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Vendor\Module\Model\Config\Source;
/**
* @api
* @since 100.0.2
*/
class Flatrate
{
/**
* {@inheritdoc}
*/
public function afterToOptionArray(\Magento\OfflineShipping\Model\Config\Source\Flatrate $subject,
$result)
{
$result= [
['value' => '', 'label' => __('None')],
['value' => 'O', 'label' => __('Per Order')],
['value' => 'I', 'label' => __('Per Item')],
['value' => 'V', 'label' => __('Per Vendor')]
];
return $result;
}
}
3rd step: You will see the option in admin panel under
stores => settings => configuration => sales => shipping methods =>
flatrate

4th step: main file to override the shipping price
Vendor/Module/Plugin/Flatrate.php
<?php
namespace Vendor\Module\Plugin;
use Magento\OfflineShipping\Model\Carrier\Flatrate as Subject;
use Magento\Quote\Model\Quote\Address\RateRequest;
use Magento\Shipping\Model\Rate\Result;
class Flatrate
{
/**
* @var string
*/
protected $_code = 'flatrate';
/**
* @var bool
*/
protected $_isFixed = true;
/**
* @var \Magento\Shipping\Model\Rate\ResultFactory
*/
protected $_rateResultFactory;
/**
* @var \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory
*/
protected $_rateMethodFactory;
/**
* @var ItemPriceCalculator
*/
private $itemPriceCalculator;
public function __construct(
\Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
\Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory,
\Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
\Magento\OfflineShipping\Model\Carrier\Flatrate\ItemPriceCalculator $itemPriceCalculator
) {
$this->_rateResultFactory = $rateResultFactory;
$this->_rateMethodFactory = $rateMethodFactory;
$this->_rateErrorFactory=$rateErrorFactory;
$this->itemPriceCalculator=$itemPriceCalculator;
}
public function aroundCollectRates(Subject $subject,\Closure $proceed,RateRequest $request)
{
if (!$subject->getConfigFlag('active')) {
return false;
}
$freeBoxes = $subject->getFreeBoxesCount($request);
$subject->setFreeBoxes($freeBoxes);
if (!subject->getConfigFlag('active')) {
return false;
}
$freeBoxes = $subject->getFreeBoxesCount($request);
$subject->setFreeBoxes($freeBoxes);
/** @var Result $result */
$result = $this->_rateResultFactory->create();
$shippingPrice = $this->getShippingPrice($subject,$request, $freeBoxes);
if ($shippingPrice !== false) {
$method = $this->createResultMethod($shippingPrice,$subject,$request);
$result->append($method);
}
return $result;
}
private function createResultMethod($shippingPrice,$subject,$request)
{
/** @var \Magento\Quote\Model\Quote\Address\RateResult\Method $method */
$method = $this->_rateMethodFactory->create();
$method->setCarrier('flatrate');
$method->setCarrierTitle($subject->getConfigData('title'));
$method->setMethod('flatrate');
$method->setMethodTitle($subject->getConfigData('name'));
$method->setPrice($shippingPrice);
$method->setCost($shippingPrice);
return $method;
}
private function getShippingPrice($subject,$request, $freeBoxes)
{
$shippingPrice = false;
$configPrice = $subject->getConfigData('price');
if ($subject->getConfigData('type') === 'O') {
// per order
$shippingPrice = $this->itemPriceCalculator->getShippingPricePerOrder($request, $configPrice, $freeBoxes);
} elseif ($subject->getConfigData('type') === 'I') {
// per item
$shippingPrice = $this->itemPriceCalculator->getShippingPricePerItem($request, $configPrice, $freeBoxes);
// per vendor
}else if ($this->getConfigData('type') === 'V') {
$shippingPrice = $this->itemPriceCalculator->getShippingPricePerVendor($request, $configPrice, $freeBoxes);
}
$shippingPrice = $subject->getFinalPriceWithHandlingFee($shippingPrice);
if ($shippingPrice !== false && $request->getPackageQty() == $freeBoxes) {
$shippingPrice = '0.00';
}
return $shippingPrice;
}
}