Exemple #1
0
 /**
  * Collect rates by address
  *
  * @param \Magento\Framework\Object $address
  * @param null|bool|array $limitCarrier
  * @return $this
  */
 public function collectRatesByAddress(\Magento\Framework\Object $address, $limitCarrier = null)
 {
     /** @var $request \Magento\Sales\Model\Quote\Address\RateRequest */
     $request = $this->_shipmentRequestFactory->create();
     $request->setAllItems($address->getAllItems());
     $request->setDestCountryId($address->getCountryId());
     $request->setDestRegionId($address->getRegionId());
     $request->setDestPostcode($address->getPostcode());
     $request->setPackageValue($address->getBaseSubtotal());
     $request->setPackageValueWithDiscount($address->getBaseSubtotalWithDiscount());
     $request->setPackageWeight($address->getWeight());
     $request->setFreeMethodWeight($address->getFreeMethodWeight());
     $request->setPackageQty($address->getItemQty());
     $request->setStoreId($this->_storeManager->getStore()->getId());
     $request->setWebsiteId($this->_storeManager->getStore()->getWebsiteId());
     $request->setBaseCurrency($this->_storeManager->getStore()->getBaseCurrency());
     $request->setPackageCurrency($this->_storeManager->getStore()->getCurrentCurrency());
     $request->setLimitCarrier($limitCarrier);
     $request->setBaseSubtotalInclTax($address->getBaseSubtotalInclTax());
     return $this->collectRates($request);
 }
 /**
  * Compare data and rates for two tax rate requests for same products (product tax class ids).
  * Returns true if requests are similar (i.e. equal taxes rates will be applied to them)
  *
  * Notice:
  * a) productClassId MUST be identical for both requests, because we intend to check selling SAME products to DIFFERENT locations
  * b) due to optimization productClassId can be array of ids, not only single id
  *
  * @param   \Magento\Framework\Object $first
  * @param   \Magento\Framework\Object $second
  * @return  bool
  */
 public function compareRequests($first, $second)
 {
     $country = $first->getCountryId() == $second->getCountryId();
     // "0" support for admin dropdown with --please select--
     $region = (int) $first->getRegionId() == (int) $second->getRegionId();
     $postcode = $first->getPostcode() == $second->getPostcode();
     $taxClass = $first->getCustomerClassId() == $second->getCustomerClassId();
     if ($country && $region && $postcode && $taxClass) {
         return true;
     }
     /**
      * Compare available tax rates for both requests
      */
     $firstReqRates = $this->_getResource()->getRateIds($first);
     $secondReqRates = $this->_getResource()->getRateIds($second);
     if ($firstReqRates === $secondReqRates) {
         return true;
     }
     /**
      * If rates are not equal by ids then compare actual values
      * All product classes must have same rates to assume requests been similar
      */
     $productClassId1 = $first->getProductClassId();
     // Save to set it back later
     $productClassId2 = $second->getProductClassId();
     // Save to set it back later
     // Ids are equal for both requests, so take any of them to process
     $ids = is_array($productClassId1) ? $productClassId1 : array($productClassId1);
     $identical = true;
     foreach ($ids as $productClassId) {
         $first->setProductClassId($productClassId);
         $rate1 = $this->getRate($first);
         $second->setProductClassId($productClassId);
         $rate2 = $this->getRate($second);
         if ($rate1 != $rate2) {
             $identical = false;
             break;
         }
     }
     $first->setProductClassId($productClassId1);
     $second->setProductClassId($productClassId2);
     return $identical;
 }
 /**
  * Get cache key value for specific tax rate request
  *
  * @param   \Magento\Framework\Object $request
  * @return  string
  */
 protected function _getRequestCacheKey($request)
 {
     $store = $request->getStore();
     $key = '';
     if ($store instanceof \Magento\Store\Model\Store) {
         $key = $store->getId() . '|';
     } elseif (is_numeric($store)) {
         $key = $store . '|';
     }
     $key .= $request->getProductClassId() . '|' . $request->getCustomerClassId() . '|' . $request->getCountryId() . '|' . $request->getRegionId() . '|' . $request->getPostcode();
     return $key;
 }
 /**
  * Returns tax rates for request - either pereforms SELECT from DB, or returns already cached result
  * Notice that productClassId due to optimization can be array of ids
  *
  * @param \Magento\Framework\Object $request
  * @return array
  */
 protected function _getRates($request)
 {
     // Extract params that influence our SELECT statement and use them to create cache key
     $storeId = $this->_storeManager->getStore($request->getStore())->getId();
     $customerClassId = $request->getCustomerClassId();
     $countryId = $request->getCountryId();
     $regionId = $request->getRegionId();
     $postcode = $request->getPostcode();
     // Process productClassId as it can be array or usual value. Form best key for cache.
     $productClassId = $request->getProductClassId();
     $ids = is_array($productClassId) ? $productClassId : array($productClassId);
     foreach ($ids as $key => $val) {
         $ids[$key] = (int) $val;
         // Make it integer for equal cache keys even in case of null/false/0 values
     }
     $ids = array_unique($ids);
     sort($ids);
     $productClassKey = implode(',', $ids);
     // Form cache key and either get data from cache or from DB
     $cacheKey = implode('|', array($storeId, $customerClassId, $productClassKey, $countryId, $regionId, $postcode));
     if (!isset($this->_ratesCache[$cacheKey])) {
         // Make SELECT and get data
         $select = $this->_getReadAdapter()->select();
         $select->from(array('main_table' => $this->getMainTable()), array('tax_calculation_rate_id', 'tax_calculation_rule_id', 'customer_tax_class_id', 'product_tax_class_id'))->where('customer_tax_class_id = ?', (int) $customerClassId);
         if ($productClassId) {
             $select->where('product_tax_class_id IN (?)', $productClassId);
         }
         $ifnullTitleValue = $this->_getReadAdapter()->getCheckSql('title_table.value IS NULL', 'rate.code', 'title_table.value');
         $ruleTableAliasName = $this->_getReadAdapter()->quoteIdentifier('rule.tax_calculation_rule_id');
         $select->join(array('rule' => $this->getTable('tax_calculation_rule')), $ruleTableAliasName . ' = main_table.tax_calculation_rule_id', array('rule.priority', 'rule.position', 'rule.calculate_subtotal'))->join(array('rate' => $this->getTable('tax_calculation_rate')), 'rate.tax_calculation_rate_id = main_table.tax_calculation_rate_id', array('value' => 'rate.rate', 'rate.tax_country_id', 'rate.tax_region_id', 'rate.tax_postcode', 'rate.tax_calculation_rate_id', 'rate.code'))->joinLeft(array('title_table' => $this->getTable('tax_calculation_rate_title')), "rate.tax_calculation_rate_id = title_table.tax_calculation_rate_id " . "AND title_table.store_id = '{$storeId}'", array('title' => $ifnullTitleValue))->where('rate.tax_country_id = ?', $countryId)->where("rate.tax_region_id IN(?)", array(0, (int) $regionId));
         $postcodeIsNumeric = is_numeric($postcode);
         $postcodeIsRange = false;
         $originalPostcode = null;
         if (is_string($postcode) && preg_match('/^(.+)-(.+)$/', $postcode, $matches)) {
             if ($countryId == self::USA_COUNTRY_CODE && is_numeric($matches[2]) && strlen($matches[2]) == 4) {
                 $postcodeIsNumeric = true;
                 $originalPostcode = $postcode;
                 $postcode = $matches[1];
             } else {
                 $postcodeIsRange = true;
                 $zipFrom = $matches[1];
                 $zipTo = $matches[2];
             }
         }
         if ($postcodeIsNumeric || $postcodeIsRange) {
             $selectClone = clone $select;
             $selectClone->where('rate.zip_is_range IS NOT NULL');
         }
         $select->where('rate.zip_is_range IS NULL');
         if ($postcode != '*' || $postcodeIsRange) {
             $select->where("rate.tax_postcode IS NULL OR rate.tax_postcode IN('*', '', ?)", $postcodeIsRange ? $postcode : $this->_createSearchPostCodeTemplates($postcode, $originalPostcode));
             if ($postcodeIsNumeric) {
                 $selectClone->where('? BETWEEN rate.zip_from AND rate.zip_to', $postcode);
             } elseif ($postcodeIsRange) {
                 $selectClone->where('rate.zip_from >= ?', $zipFrom)->where('rate.zip_to <= ?', $zipTo);
             }
         }
         /**
          * @see ZF-7592 issue http://framework.zend.com/issues/browse/ZF-7592
          */
         if ($postcodeIsNumeric || $postcodeIsRange) {
             $select = $this->_getReadAdapter()->select()->union(array('(' . $select . ')', '(' . $selectClone . ')'));
         }
         $select->order('priority ' . \Magento\Framework\DB\Select::SQL_ASC)->order('tax_calculation_rule_id ' . \Magento\Framework\DB\Select::SQL_ASC)->order('tax_country_id ' . \Magento\Framework\DB\Select::SQL_DESC)->order('tax_region_id ' . \Magento\Framework\DB\Select::SQL_DESC)->order('tax_postcode ' . \Magento\Framework\DB\Select::SQL_DESC)->order('value ' . \Magento\Framework\DB\Select::SQL_DESC);
         $fetchResult = $this->_getReadAdapter()->fetchAll($select);
         $filteredRates = array();
         if ($fetchResult) {
             foreach ($fetchResult as $rate) {
                 if (!isset($filteredRates[$rate['tax_calculation_rate_id']])) {
                     $filteredRates[$rate['tax_calculation_rate_id']] = $rate;
                 }
             }
         }
         $this->_ratesCache[$cacheKey] = array_values($filteredRates);
     }
     return $this->_ratesCache[$cacheKey];
 }