/** * Collect tax totals for quote address * * @param Quote $quote * @param ShippingAssignmentInterface $shippingAssignment * @param Address\Total $total * @return $this * @throws RemoteServiceUnavailableException */ public function collect(Quote $quote, ShippingAssignmentInterface $shippingAssignment, Address\Total $total) { // If quote is virtual, getShipping will return billing address, so no need to check if quote is virtual $address = $shippingAssignment->getShipping()->getAddress(); $storeId = $quote->getStoreId(); // This will allow a merchant to configure default tax settings for their site using Magento's core tax // calculation and AvaTax's calculation will only kick in during cart/checkout. This is useful for countries // where merchants are required to display prices including tax (such as some countries that charge VAT tax). if (!$this->config->isModuleEnabled($storeId) || $this->config->getTaxMode($storeId) == Config::TAX_MODE_NO_ESTIMATE_OR_SUBMIT || !$this->config->isAddressTaxable($address, $storeId)) { return parent::collect($quote, $shippingAssignment, $total); } $postcode = $address->getPostcode(); // If postcode is not present, then collect totals is being run from a context where customer has not submitted // their address, such as on the product listing, product detail, or cart page. Once the user enters their // postcode in the "Estimate Shipping & Tax" form on the cart page, or submits their shipping address in the // checkout, then a postcode will be present. if (!$postcode) { return parent::collect($quote, $shippingAssignment, $total); } $this->clearValues($total); if (!$shippingAssignment->getItems()) { return $this; } $taxQuoteDetails = $this->getTaxQuoteDetails($shippingAssignment, $total, $storeId, false); $baseTaxQuoteDetails = $this->getTaxQuoteDetails($shippingAssignment, $total, $storeId, true); // Get array of tax details try { $taxDetailsList = $this->interactionGetTax->getTaxDetailsForQuote($quote, $taxQuoteDetails, $baseTaxQuoteDetails, $shippingAssignment); } catch (\Exception $e) { switch ($this->config->getErrorAction($quote->getStoreId())) { case Config::ERROR_ACTION_DISABLE_CHECKOUT: $this->coreRegistry->register(self::AVATAX_GET_TAX_REQUEST_ERROR, true, true); return parent::collect($quote, $shippingAssignment, $total); break; case Config::ERROR_ACTION_ALLOW_CHECKOUT_NATIVE_TAX: default: /** * Note: while this should return Magento's tax calculation, the tax calculation may be slightly * off, as these two collect methods will not have run: * @see \Magento\Tax\Model\Sales\Total\Quote\Shipping::collect() * @see \Magento\Tax\Model\Sales\Total\Quote\Subtotal::collect() */ return parent::collect($quote, $shippingAssignment, $total); break; } } $taxDetails = $taxDetailsList[InteractionGet::KEY_TAX_DETAILS]; $baseTaxDetails = $taxDetailsList[InteractionGet::KEY_BASE_TAX_DETAILS]; $itemsByType = $this->organizeItemTaxDetailsByType($taxDetails, $baseTaxDetails); if (isset($itemsByType[self::ITEM_TYPE_PRODUCT])) { $this->processProductItems($shippingAssignment, $itemsByType[self::ITEM_TYPE_PRODUCT], $total); } if (isset($itemsByType[self::ITEM_TYPE_SHIPPING])) { $shippingTaxDetails = $itemsByType[self::ITEM_TYPE_SHIPPING][self::ITEM_CODE_SHIPPING][self::KEY_ITEM]; $baseShippingTaxDetails = $itemsByType[self::ITEM_TYPE_SHIPPING][self::ITEM_CODE_SHIPPING][self::KEY_BASE_ITEM]; $this->processShippingTaxInfo($shippingAssignment, $total, $shippingTaxDetails, $baseShippingTaxDetails); } //Process taxable items that are not product or shipping $this->processExtraTaxables($total, $itemsByType); //Save applied taxes for each item and the quote in aggregation $this->processAppliedTaxes($total, $shippingAssignment, $itemsByType); if ($this->includeExtraTax()) { $total->addTotalAmount('extra_tax', $total->getExtraTaxAmount()); $total->addBaseTotalAmount('extra_tax', $total->getBaseExtraTaxAmount()); } return $this; }