/** * @return array */ public function getBindings() { $bind = [':website_id' => (int) $this->request->getWebsiteId(), ':country_id' => $this->request->getDestCountryId(), ':region_id' => (int) $this->request->getDestRegionId(), ':postcode' => $this->request->getDestPostcode()]; // Render condition by condition name if (is_array($this->request->getConditionName())) { $i = 0; foreach ($this->request->getConditionName() as $conditionName) { $bindNameKey = sprintf(':condition_name_%d', $i); $bindValueKey = sprintf(':condition_value_%d', $i); $bind[$bindNameKey] = $conditionName; $bind[$bindValueKey] = $this->request->getData($conditionName); $i++; } } else { $bind[':condition_name'] = $this->request->getConditionName(); $bind[':condition_value'] = $this->request->getData($this->request->getConditionName()); } return $bind; }
/** * @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; if ($request->getAllItems()) { $freePackageValue = 0; 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()) { $freeShipping = is_numeric($item->getFreeShipping()) ? $item->getFreeShipping() : 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) { /** @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')); if ($request->getFreeShipping() === true || $request->getPackageQty() == $freeQty) { $shippingPrice = 0; } else { $shippingPrice = $this->getFinalPriceWithHandlingFee($rate['price']); } $method->setPrice($shippingPrice); $method->setCost($rate['cost']); $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; }
/** * Return table rate array or false by rate request * * @param \Magento\Quote\Model\Quote\Address\RateRequest $request * @return array|bool */ public function getRate(\Magento\Quote\Model\Quote\Address\RateRequest $request) { $connection = $this->getConnection(); $bind = [':website_id' => (int) $request->getWebsiteId(), ':country_id' => $request->getDestCountryId(), ':region_id' => (int) $request->getDestRegionId(), ':postcode' => $request->getDestPostcode()]; $select = $connection->select()->from($this->getMainTable())->where('website_id = :website_id')->order(['dest_country_id DESC', 'dest_region_id DESC', 'dest_zip DESC'])->limit(1); // Render destination condition $orWhere = '(' . implode(') OR (', ["dest_country_id = :country_id AND dest_region_id = :region_id AND dest_zip = :postcode", "dest_country_id = :country_id AND dest_region_id = :region_id AND dest_zip = ''", "dest_country_id = :country_id AND dest_region_id = :region_id AND dest_zip = '*'", "dest_country_id = :country_id AND dest_region_id = 0 AND dest_zip = '*'", "dest_country_id = '0' AND dest_region_id = :region_id AND dest_zip = '*'", "dest_country_id = '0' AND dest_region_id = 0 AND dest_zip = '*'", "dest_country_id = :country_id AND dest_region_id = 0 AND dest_zip = ''", "dest_country_id = :country_id AND dest_region_id = 0 AND dest_zip = :postcode", "dest_country_id = :country_id AND dest_region_id = 0 AND dest_zip = '*'"]) . ')'; $select->where($orWhere); // Render condition by condition name if (is_array($request->getConditionName())) { $orWhere = []; $i = 0; foreach ($request->getConditionName() as $conditionName) { $bindNameKey = sprintf(':condition_name_%d', $i); $bindValueKey = sprintf(':condition_value_%d', $i); $orWhere[] = "(condition_name = {$bindNameKey} AND condition_value <= {$bindValueKey})"; $bind[$bindNameKey] = $conditionName; $bind[$bindValueKey] = $request->getData($conditionName); $i++; } if ($orWhere) { $select->where(implode(' OR ', $orWhere)); } } else { $bind[':condition_name'] = $request->getConditionName(); $bind[':condition_value'] = $request->getData($request->getConditionName()); $select->where('condition_name = :condition_name'); $select->where('condition_value <= :condition_value'); } $result = $connection->fetchRow($select, $bind); // Normalize destination zip code if ($result && $result['dest_zip'] == '*') { $result['dest_zip'] = ''; } return $result; }