123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\OfflineShipping\Model\Carrier;
- use Magento\Framework\Exception\LocalizedException;
- use Magento\Quote\Model\Quote\Address\RateRequest;
- /**
- * Table rate shipping model
- *
- * @api
- * @since 100.0.2
- */
- class Tablerate extends \Magento\Shipping\Model\Carrier\AbstractCarrier implements
- \Magento\Shipping\Model\Carrier\CarrierInterface
- {
- /**
- * @var string
- */
- protected $_code = 'tablerate';
- /**
- * @var bool
- */
- protected $_isFixed = true;
- /**
- * @var string
- */
- protected $_defaultConditionName = 'package_weight';
- /**
- * @var array
- */
- protected $_conditionNames = [];
- /**
- * @var \Magento\Shipping\Model\Rate\ResultFactory
- */
- protected $_rateResultFactory;
- /**
- * @var \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory
- */
- protected $_resultMethodFactory;
- /**
- * @var \Magento\OfflineShipping\Model\ResourceModel\Carrier\TablerateFactory
- */
- protected $_tablerateFactory;
- /**
- * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
- * @param \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory
- * @param \Psr\Log\LoggerInterface $logger
- * @param \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory
- * @param \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $resultMethodFactory
- * @param \Magento\OfflineShipping\Model\ResourceModel\Carrier\TablerateFactory $tablerateFactory
- * @param array $data
- * @throws LocalizedException
- * @SuppressWarnings(PHPMD.UnusedLocalVariable)
- */
- public function __construct(
- \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
- \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
- \Psr\Log\LoggerInterface $logger,
- \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory,
- \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $resultMethodFactory,
- \Magento\OfflineShipping\Model\ResourceModel\Carrier\TablerateFactory $tablerateFactory,
- array $data = []
- ) {
- $this->_rateResultFactory = $rateResultFactory;
- $this->_resultMethodFactory = $resultMethodFactory;
- $this->_tablerateFactory = $tablerateFactory;
- parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
- foreach ($this->getCode('condition_name') as $k => $v) {
- $this->_conditionNames[] = $k;
- }
- }
- /**
- * Collect rates.
- *
- * @param RateRequest $request
- * @return \Magento\Shipping\Model\Rate\Result
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
- * @SuppressWarnings(PHPMD.NPathComplexity)
- * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
- */
- public function collectRates(RateRequest $request)
- {
- if (!$this->getConfigFlag('active')) {
- return false;
- }
- // exclude Virtual products price from Package value if pre-configured
- if (!$this->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 = $this->getConfigData('condition_name');
- $request->setConditionName($conditionName ? $conditionName : $this->_defaultConditionName);
- }
- // Package weight and qty free shipping
- $oldWeight = $request->getPackageWeight();
- $oldQty = $request->getPackageQty();
- $request->setPackageWeight($request->getFreeMethodWeight());
- $request->setPackageQty($oldQty - $freeQty);
- /** @var \Magento\Shipping\Model\Rate\Result $result */
- $result = $this->_rateResultFactory->create();
- $rate = $this->getRate($request);
- $request->setPackageWeight($oldWeight);
- $request->setPackageQty($oldQty);
- if (!empty($rate) && $rate['price'] >= 0) {
- if ($request->getPackageQty() == $freeQty) {
- $shippingPrice = 0;
- } else {
- $shippingPrice = $this->getFinalPriceWithHandlingFee($rate['price']);
- }
- $method = $this->createShippingMethod($shippingPrice, $rate['cost']);
- $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 = $this->getRate($request);
- if (!empty($rate) && $rate['price'] >= 0) {
- $method = $this->createShippingMethod(0, 0);
- $result->append($method);
- }
- } else {
- /** @var \Magento\Quote\Model\Quote\Address\RateResult\Error $error */
- $error = $this->_rateErrorFactory->create(
- [
- 'data' => [
- 'carrier' => $this->_code,
- 'carrier_title' => $this->getConfigData('title'),
- 'error_message' => $this->getConfigData('specificerrmsg'),
- ],
- ]
- );
- $result->append($error);
- }
- return $result;
- }
- /**
- * Get rate.
- *
- * @param \Magento\Quote\Model\Quote\Address\RateRequest $request
- * @return array|bool
- */
- public function getRate(\Magento\Quote\Model\Quote\Address\RateRequest $request)
- {
- return $this->_tablerateFactory->create()->getRate($request);
- }
- /**
- * Get code.
- *
- * @param string $type
- * @param string $code
- * @return array
- * @throws \Magento\Framework\Exception\LocalizedException
- */
- public function getCode($type, $code = '')
- {
- $codes = [
- 'condition_name' => [
- 'package_weight' => __('Weight vs. Destination'),
- 'package_value_with_discount' => __('Price vs. Destination'),
- 'package_qty' => __('# of Items vs. Destination'),
- ],
- 'condition_name_short' => [
- 'package_weight' => __('Weight (and above)'),
- 'package_value_with_discount' => __('Order Subtotal (and above)'),
- 'package_qty' => __('# of Items (and above)'),
- ],
- ];
- if (!isset($codes[$type])) {
- throw new LocalizedException(
- __('The "%1" code type for Table Rate is incorrect. Verify the type and try again.', $type)
- );
- }
- if ('' === $code) {
- return $codes[$type];
- }
- if (!isset($codes[$type][$code])) {
- throw new LocalizedException(
- __('The "%1: %2" code type for Table Rate is incorrect. Verify the type and try again.', $type, $code)
- );
- }
- return $codes[$type][$code];
- }
- /**
- * Get allowed shipping methods
- *
- * @return array
- */
- public function getAllowedMethods()
- {
- return ['bestway' => $this->getConfigData('name')];
- }
- /**
- * 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)
- {
- /** @var \Magento\Quote\Model\Quote\Address\RateResult\Method $method */
- $method = $this->_resultMethodFactory->create();
- $method->setCarrier('tablerate');
- $method->setCarrierTitle($this->getConfigData('title'));
- $method->setMethod('bestway');
- $method->setMethodTitle($this->getConfigData('name'));
- $method->setPrice($shippingPrice);
- $method->setCost($cost);
- return $method;
- }
- }
|