/** * Process invoice or credit memo * * @param \Magento\Sales\Api\Data\InvoiceInterface|\Magento\Sales\Api\Data\CreditmemoInterface $object * @return \ClassyLlama\AvaTax\Api\Data\GetTaxResponseInterface * @throws \ClassyLlama\AvaTax\Exception\TaxCalculationException */ public function processSalesObject($object) { $storeId = $object->getStoreId(); $taxService = $this->taxService; try { /** @var $getTaxRequest GetTaxRequest */ $getTaxRequest = $this->interactionTax->getGetTaxRequestForSalesObject($object); } catch (\Exception $e) { $message = __('Error while building the request to send to AvaTax. '); $this->avaTaxLogger->error($message, ['entity_id' => $object->getEntityId(), 'object_class' => get_class($object), 'exception' => sprintf('Exception message: %s%sTrace: %s', $e->getMessage(), "\n", $e->getTraceAsString())]); throw new \ClassyLlama\AvaTax\Exception\TaxCalculationException($message . $e->getMessage(), $e->getCode(), $e); } if (is_null($getTaxRequest)) { $message = '$getTaxRequest was empty so not running getTax request.'; $this->avaTaxLogger->warning($message); throw new \ClassyLlama\AvaTax\Exception\TaxCalculationException($message); } try { $getTaxResult = $taxService->getTax($getTaxRequest, $storeId); if ($getTaxResult->getResultCode() == \AvaTax\SeverityLevel::$Success) { // Since credit memo tax amounts come back from AvaTax as negative numbers, get absolute value $avataxTaxAmount = abs($getTaxResult->getTotalTax()); $unbalanced = $avataxTaxAmount != $object->getBaseTaxAmount(); /** @var $response \ClassyLlama\AvaTax\Api\Data\GetTaxResponseInterface */ $response = $this->getTaxResponseFactory->create(); $response->setIsUnbalanced($unbalanced)->setBaseAvataxTaxAmount($avataxTaxAmount); return $response; } else { $message = $this->getErrorMessageFromGetTaxResult($getTaxResult); $this->avaTaxLogger->warning($message, ['request' => var_export($getTaxRequest, true), 'result' => var_export($getTaxResult, true)]); throw new \ClassyLlama\AvaTax\Exception\TaxCalculationException($message); } } catch (\SoapFault $exception) { $message = "Exception: \n"; if ($exception) { $message .= $exception->faultstring; } $message .= $taxService->__getLastRequest() . "\n"; $message .= $taxService->__getLastResponse() . "\n"; $this->avaTaxLogger->critical("Exception: \n" . $exception ? $exception->faultstring : "", ['request' => var_export($taxService->__getLastRequest(), true), 'result' => var_export($taxService->__getLastResponse(), true)]); throw new \ClassyLlama\AvaTax\Exception\TaxCalculationException($message); } }
/** * Accepts an invoice or creditmemo and returns an \AvaTax\Line object * * @param \Magento\Sales\Api\Data\InvoiceInterface|\Magento\Sales\Api\Data\CreditmemoInterface $data * @return \AvaTax\Line|bool */ public function getNegativeAdjustmentLine($data) { $amount = $data->getBaseAdjustmentNegative(); if ($amount == 0) { return false; } $storeId = $data->getStoreId(); $itemCode = $this->config->getSkuAdjustmentNegative($storeId); $data = ['No' => $this->getLineNumber(), 'ItemCode' => $itemCode, 'Description' => self::ADJUSTMENT_NEGATIVE_LINE_DESCRIPTION, 'Qty' => 1, 'Amount' => $amount, 'Discounted' => false, 'TaxIncluded' => true]; try { $data = $this->metaDataObject->validateData($data); } catch (ValidationException $e) { $this->avaTaxLogger->error('Error validating line: ' . $e->getMessage(), ['data' => var_export($data, true)]); } /** @var $line \AvaTax\Line */ $line = $this->lineFactory->create(); $this->populateLine($data, $line); return $line; }
/** * Creates and returns a populated getTaxRequest for a invoice * * @param \Magento\Sales\Api\Data\InvoiceInterface|\Magento\Sales\Api\Data\CreditmemoInterface $object * @return GetTaxRequest */ public function getGetTaxRequestForSalesObject($object) { $order = $this->orderRepository->get($object->getOrderId()); $lines = []; $items = $object->getItems(); $this->taxClassHelper->populateCorrectTaxClasses($items, $object->getStoreId()); /** @var \Magento\Tax\Api\Data\QuoteDetailsItemInterface $item */ foreach ($items as $item) { $line = $this->interactionLine->getLine($item); if ($line) { $lines[] = $line; } } $objectIsCreditMemo = $object instanceof \Magento\Sales\Api\Data\CreditmemoInterface; $credit = $objectIsCreditMemo; $line = $this->interactionLine->getShippingLine($object, $credit); if ($line) { $lines[] = $line; } $line = $this->interactionLine->getGiftWrapItemsLine($object, $credit); if ($line) { $lines[] = $line; } $line = $this->interactionLine->getGiftWrapOrderLine($object, $credit); if ($line) { $lines[] = $line; } $line = $this->interactionLine->getGiftWrapCardLine($object, $credit); if ($line) { $lines[] = $line; } if ($objectIsCreditMemo) { $line = $this->interactionLine->getPositiveAdjustmentLine($object); if ($line) { $lines[] = $line; } $line = $this->interactionLine->getNegativeAdjustmentLine($object); if ($line) { $lines[] = $line; } } /** @var \Magento\Sales\Api\Data\OrderAddressInterface $address */ if (!$order->getIsVirtual()) { $address = $order->getShippingAddress(); } else { $address = $order->getBillingAddress(); } $avaTaxAddress = $this->address->getAddress($address); $store = $this->storeRepository->getById($object->getStoreId()); $currentDate = $this->getFormattedDate($store, $object->getCreatedAt()); $taxOverride = null; if ($object instanceof \Magento\Sales\Api\Data\InvoiceInterface) { $docType = DocumentType::$SalesInvoice; if ($this->areTimesDifferentDays($order->getCreatedAt(), $object->getCreatedAt(), $object->getStoreId())) { $taxCalculationDate = $this->getFormattedDate($store, $order->getCreatedAt()); // Set the tax date for calculation $taxOverride = $this->taxOverrideFactory->create(); $taxOverride->setTaxDate($taxCalculationDate); $taxOverride->setTaxOverrideType(\AvaTax\TaxOverrideType::$TaxDate); $taxOverride->setTaxAmount(0.0); $taxOverride->setReason(self::AVATAX_INVOICE_OVERRIDE_REASON); } } else { $docType = DocumentType::$ReturnInvoice; $invoice = $this->getInvoice($object->getInvoiceId()); // If a Creditmemo was generated for an invoice, use the created_at value from the invoice if ($invoice) { $taxCalculationDate = $this->getFormattedDate($store, $invoice->getCreatedAt()); } else { $taxCalculationDate = $this->getFormattedDate($store, $order->getCreatedAt()); } // Set the tax date for calculation $taxOverride = $this->taxOverrideFactory->create(); $taxOverride->setTaxDate($taxCalculationDate); $taxOverride->setTaxOverrideType(\AvaTax\TaxOverrideType::$TaxDate); $taxOverride->setTaxAmount(0.0); $taxOverride->setReason(self::AVATAX_CREDITMEMO_OVERRIDE_REASON); } $customer = $this->getCustomerById($order->getCustomerId()); $customerUsageType = $customer ? $this->taxClassHelper->getAvataxTaxCodeForCustomer($customer) : null; $data = ['StoreId' => $store->getId(), 'Commit' => $this->config->getCommitSubmittedTransactions($store), 'TaxOverride' => $taxOverride, 'CurrencyCode' => $order->getOrderCurrencyCode(), 'CustomerCode' => $this->getCustomerCode($order), 'CustomerUsageType' => $customerUsageType, 'DestinationAddress' => $avaTaxAddress, 'DocCode' => $object->getIncrementId() . '123-' . rand(10000000, 90000000000), 'DocDate' => $currentDate, 'DocType' => $docType, 'ExchangeRate' => $this->getExchangeRate($store, $order->getBaseCurrencyCode(), $order->getOrderCurrencyCode()), 'ExchangeRateEffDate' => $currentDate, 'Lines' => $lines, 'DetailLevel' => DetailLevel::$Document, 'PaymentDate' => $currentDate, 'PurchaseOrderNo' => $object->getIncrementId()]; $data = array_merge($this->retrieveGetTaxRequestFields($store, $address, $object), $data); try { $data = $this->metaDataObject->validateData($data); } catch (ValidationException $e) { $this->avaTaxLogger->error('Error validating data: ' . $e->getMessage(), ['data' => var_export($data, true)]); } /** @var $getTaxRequest GetTaxRequest */ $getTaxRequest = $this->getTaxRequestFactory->create(); $this->populateGetTaxRequest($data, $getTaxRequest); return $getTaxRequest; }