/** * Get billing address request data * * @param \Magento\Framework\Object $address * @return array */ protected function _getBillingAddress(\Magento\Framework\Object $address) { $request = array('billing_first_name' => $address->getFirstname(), 'billing_last_name' => $address->getLastname(), 'billing_city' => $address->getCity(), 'billing_state' => $address->getRegionCode() ? $address->getRegionCode() : $address->getCity(), 'billing_zip' => $address->getPostcode(), 'billing_country' => $address->getCountry()); // convert streets to tow lines format $street = $this->_customerAddress->convertStreetLines($address->getStreet(), 2); $request['billing_address1'] = isset($street[0]) ? $street[0] : ''; $request['billing_address2'] = isset($street[1]) ? $street[1] : ''; return $request; }
/** * 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); }
/** * 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; }
/** * 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; }
/** * 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]; }
/** * @param Object $request * @param Object $shipping * * @return Object */ public function setShipping($request, $shipping) { $request->setShiptofirstname($shipping->getFirstname())->setShiptolastname($shipping->getLastname())->setShiptostreet(implode(' ', $shipping->getStreet()))->setShiptocity($shipping->getCity())->setShiptostate($shipping->getRegionCode())->setShiptozip($shipping->getPostcode())->setShiptocountry($shipping->getCountryId()); return $request; }