/**
  * If module is enabled, don't run collect totals for shipping
  *
  * Tax calculation for shipping is handled in this class
  * @see \ClassyLlama\AvaTax\Model\Tax\Sales\Total\Quote\Tax::collect()
  * Since this extension doesn't support applying discounts *after* tax, we don't need to run a separate collect
  * process.
  *
  * @param \Magento\Tax\Model\Sales\Total\Quote\Shipping $subject
  * @param \Closure $proceed
  * @param \Magento\Quote\Model\Quote $quote
  * @param \Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment
  * @param \Magento\Quote\Model\Quote\Address\Total $total
  * @return mixed
  */
 public function aroundCollect(\Magento\Tax\Model\Sales\Total\Quote\Shipping $subject, \Closure $proceed, \Magento\Quote\Model\Quote $quote, \Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment, \Magento\Quote\Model\Quote\Address\Total $total)
 {
     $storeId = $quote->getStoreId();
     // If quote is virtual, getShipping will return billing address, so no need to check if quote is virtual
     $address = $shippingAssignment->getShipping()->getAddress();
     if (!$this->config->isModuleEnabled($storeId) || $this->config->getTaxMode($storeId) == Config::TAX_MODE_NO_ESTIMATE_OR_SUBMIT || !$this->config->isAddressTaxable($address, $storeId)) {
         return $proceed($quote, $shippingAssignment, $total);
     }
 }
 /**
  * If AvaTax GetTaxRequest failed and if configuration is set to prevent checkout, throw exception
  *
  * @param \Magento\Framework\Event\Observer $observer
  * @return $this
  * @throws LocalizedException
  */
 public function execute(\Magento\Framework\Event\Observer $observer)
 {
     /** @var \Magento\Sales\Api\Data\OrderInterface $order */
     $order = $observer->getOrder();
     if ($this->coreRegistry->registry(Tax::AVATAX_GET_TAX_REQUEST_ERROR)) {
         $errorMessage = $this->config->getErrorActionDisableCheckoutMessage($order->getStoreId());
         throw new LocalizedException($errorMessage);
     }
     return $this;
 }
 /**
  * Writes the log to the database by utilizing the Log model
  *
  * @param $record array
  * @return void
  */
 public function write(array $record)
 {
     # Log to database
     /** @var \ClassyLlama\AvaTax\Model\Log $log */
     $log = $this->logFactory->create();
     $log->setData('level', isset($record['level_name']) ? $record['level_name'] : null);
     $log->setData('message', isset($record['message']) ? $record['message'] : null);
     if (isset($record['extra']['store_id'])) {
         $log->setData('store_id', $record['extra']['store_id']);
         unset($record['extra']['store_id']);
     }
     if (isset($record['extra']['class']) && isset($record['extra']['line'])) {
         $log->setData('source', $record['extra']['class'] . " [line:" . $record['extra']['line'] . "]");
     }
     if ($this->avaTaxConfig->getLogDbDetail() == LogDetail::MINIMAL && $record['level'] >= Logger::WARNING) {
         $log->setData('request', $this->getRequest($record));
         $log->setData('result', $this->getResult($record));
     } elseif ($this->avaTaxConfig->getLogDbDetail() == LogDetail::NORMAL) {
         $log->setData('request', $this->getRequest($record));
         $log->setData('result', $this->getResult($record));
         $log->setData('additional', $this->getContextVarExport($record));
     } elseif ($this->avaTaxConfig->getLogDbDetail() == LogDetail::EXTRA) {
         $log->setData('request', $this->getRequest($record));
         $log->setData('result', $this->getResult($record));
         $log->setData('additional', $this->getExtraVarExport($record) . (strlen($this->getExtraVarExport($record)) > 0 ? "\n" : '') . $this->getContextVarExport($record));
     }
     $log->save();
 }
 /**
  * @return void
  */
 public function prepare()
 {
     $config = $this->getData('config');
     if (isset($config['options'])) {
         $options = [];
         foreach ($config['options'] as $option) {
             $option['url'] = $this->urlBuilder->getUrl($option['url']);
             $options[] = $option;
         }
         $config['options'] = $options;
     }
     $store = $this->storeManager->getStore();
     $config['validationEnabled'] = $this->config->isAddressValidationEnabled($store);
     $hasChoice = $this->config->allowUserToChooseAddress($store);
     if ($hasChoice) {
         $instructions = $this->config->getAddressValidationInstructionsWithChoice($store);
     } else {
         $instructions = $this->config->getAddressValidationInstructionsWithOutChoice($store);
     }
     $config['instructions'] = $instructions;
     $config['errorInstructions'] = $this->config->getAddressValidationErrorInstructions($store);
     $config['countriesEnabled'] = $this->config->getAddressValidationCountriesEnabled($store);
     $config['baseUrl'] = $this->urlBuilder->getUrl(self::VALIDATE_ADDRESS_PATH);
     $this->setData('config', $config);
     parent::prepare();
 }
 /**
  * Ping AvaTax using configured live/production mode
  *
  * @param $scopeId
  * @param $scopeType
  * @return array
  */
 protected function sendPing($scopeId, $scopeType)
 {
     $errors = [];
     if (!$this->config->isModuleEnabled($scopeId, $scopeType)) {
         return $errors;
     }
     $message = '';
     $type = $this->config->getLiveMode() ? Config::API_PROFILE_NAME_PROD : Config::API_PROFILE_NAME_DEV;
     try {
         $result = $this->interactionTax->getTaxService($type, $scopeId, $scopeType)->ping();
         if (is_object($result) && $result->getResultCode() != \AvaTax\SeverityLevel::$Success) {
             foreach ($result->getMessages() as $messages) {
                 $message .= $messages->getName() . ': ' . $messages->getSummary() . "\n";
             }
         } elseif (is_object($result) && $result->getResultCode() == \AvaTax\SeverityLevel::$Success) {
             $this->messageManager->addSuccess(__('Successfully connected to AvaTax using the ' . '<a href="#row_tax_avatax_connection_settings_header">%1 credentials</a>', $type));
         }
     } catch (\Exception $exception) {
         $message = $exception->getMessage();
     }
     if ($message) {
         $errors[] = __('Error connecting to AvaTax using the ' . '<a href="#row_tax_avatax_connection_settings_header">%1 credentials</a>: %2', $type, $message);
     }
     return $errors;
 }
 /**
  * Get Ref2 code for product
  *
  * @param \Magento\Catalog\Model\Product $product
  * @return mixed|null
  */
 public function getRef2ForProduct(\Magento\Catalog\Model\Product $product)
 {
     if ($this->config->getRef2Attribute() && $product->getData($this->config->getRef2Attribute())) {
         return $product->getData($this->config->getRef2Attribute());
     }
     return null;
 }
 /**
  * @param \Magento\Sales\Model\Spi\InvoiceResourceInterface $subject
  * @param \Closure $proceed
  *
  *        Include both the extended AbstractModel and implemented Interface here for the IDE's benefit
  * @param \Magento\Framework\Model\AbstractModel|\Magento\Sales\Api\Data\InvoiceInterface $entity
  * @param mixed $value
  * @param string $field field to load by (defaults to model id)
  * @return \Magento\Framework\Model\ResourceModel\Db\AbstractDb
  * @throws \Magento\Framework\Exception\NoSuchEntityException
  */
 public function aroundLoad(InvoiceResourceInterface $subject, \Closure $proceed, AbstractModel $entity, $value, $field = null)
 {
     /** @var \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resultEntity */
     $resultEntity = $proceed($entity, $value, $field);
     // Load AvaTax extension attributes
     if ($this->avaTaxConfig->isModuleEnabled($entity->getStoreId())) {
         // Get the AvaTax Attributes from the AbstractModel
         $avataxIsUnbalanced = $entity->getData('avatax_is_unbalanced');
         $baseAvataxTaxAmount = $entity->getData('base_avatax_tax_amount');
         // Check the AvaTax Entity to see if we need to add extension attributes
         if ($avataxIsUnbalanced !== null || $baseAvataxTaxAmount !== null) {
             // Get any existing extension attributes or create a new one
             $entityExtension = $entity->getExtensionAttributes();
             if (!$entityExtension) {
                 $entityExtension = $this->invoiceExtensionFactory->create();
             }
             // Set the attributes
             if ($avataxIsUnbalanced !== null) {
                 $entityExtension->setAvataxIsUnbalanced($avataxIsUnbalanced);
             }
             if ($baseAvataxTaxAmount !== null) {
                 $entityExtension->setBaseAvataxTaxAmount($baseAvataxTaxAmount);
             }
             // save the ExtensionAttributes on the entity object
             $entity->setExtensionAttributes($entityExtension);
         }
     }
     return $resultEntity;
 }
 /**
  * Check to see if there was an error during tax calculation, and if so, throw exception to prevent further progress
  *
  * @param $storeId
  * @return void
  * @throws LocalizedException
  */
 protected function ensureTaxCalculationSuccess($storeId)
 {
     if ($this->coreRegistry->registry(Tax::AVATAX_GET_TAX_REQUEST_ERROR)) {
         $errorMessage = $this->config->getErrorActionDisableCheckoutMessage($storeId);
         throw new LocalizedException($errorMessage);
     }
 }
Esempio n. 9
0
 /**
  * @param $store
  * @param $address
  * @param \Magento\Customer\Api\Data\CustomerInterface|null $customer
  * @return null
  */
 protected function getBusinessIdentificationNumber($store, $address, $customer)
 {
     if ($customer && $customer->getTaxvat()) {
         return $customer->getTaxvat();
     }
     if ($this->config->getUseBusinessIdentificationNumber($store)) {
         return $address->getVatId();
     }
     return null;
 }
 /**
  * Check to see if there are any native tax rules created that may affect AvaTax
  *
  * @return array
  */
 public function checkNativeTaxRules()
 {
     $errors = [];
     if ($this->avaTaxConfig->isModuleEnabled() && $this->avaTaxConfig->getTaxMode($this->storeManager->getDefaultStoreView()) != Config::TAX_MODE_NO_ESTIMATE_OR_SUBMIT && !$this->avaTaxConfig->isNativeTaxRulesIgnored()) {
         $taxRules = $this->taxRuleRepository->getList($this->searchCriteriaBuilder->create());
         if (count($taxRules->getItems())) {
             $errors[] = __('You have %1 native Magento Tax Rule(s) configured. ' . 'Please <a href="%2">review the tax rule(s)</a> and delete any that you do not specifically want enabled. ' . 'You should only have rules setup if you want to use them as backup rules in case of AvaTax ' . 'errors (see <a href="#row_tax_avatax_error_handling_header">Error Action setting</a>) ' . 'or if you need to support VAT tax. ' . '<a href="%3">Ignore this notification</a>.', count($taxRules->getItems()), $this->backendUrl->getUrl('tax/rule'), $this->backendUrl->getUrl('avatax/tax/ignoreTaxRuleNotification'));
         }
     }
     return $errors;
 }
Esempio n. 11
0
 /**
  * Get address service by type and cache instances by type to avoid duplicate instantiation
  *
  * @param string $type
  * @param $storeId
  * @return AddressServiceSoap
  */
 public function getAddressService($type = null, $storeId = null)
 {
     if (is_null($type)) {
         $type = $this->config->getLiveMode() ? Config::API_PROFILE_NAME_PROD : Config::API_PROFILE_NAME_DEV;
     }
     if (!isset($this->addressServiceSoap[$type])) {
         $this->config->createAvaTaxProfile($storeId);
         $this->addressServiceSoap[$type] = $this->addressServiceSoapFactory->create(['configurationName' => $type]);
     }
     return $this->addressServiceSoap[$type];
 }
Esempio n. 12
0
 /**
  * Clear the queue of complete and failed records
  */
 public function clearLogs()
 {
     $this->avaTaxLogger->debug(__('Starting queue clearing'));
     /** @var $collection \ClassyLlama\AvaTax\Model\ResourceModel\Log\Collection */
     $collection = $this->logCollectionFactory->create();
     // Get configuration for record lifetime
     $lifetimeDays = $this->avaTaxConfig->getLogDbLifetime();
     // Calculate the number of seconds to adjust the filter
     // 86400 seconds == 60 seconds * 60 minutes * 24 hours == 1 day
     $secondsBeforeNow = $lifetimeDays * 60 * 60 * 24;
     // Add filters
     $collection->addCreatedAtBeforeFilter($secondsBeforeNow);
     // Process each queued entity
     /** @var $log Log */
     foreach ($collection as $log) {
         // Remove the queue record
         $log->delete();
         $this->deleteCount++;
     }
     $this->avaTaxLogger->debug(__('Finished clearing log entries'), ['delete_count' => $this->deleteCount]);
 }
Esempio n. 13
0
 /**
  * Append attributes to the list of attributes loaded on the quote_items collection
  *
  * @param QuoteConfig $config
  * @param $attributes
  * @return array
  */
 public function afterGetProductAttributes(QuoteConfig $config, $attributes)
 {
     if ($this->config->getRef1Attribute()) {
         $attributes[] = $this->config->getRef1Attribute();
     }
     if ($this->config->getRef2Attribute()) {
         $attributes[] = $this->config->getRef2Attribute();
     }
     if ($this->config->getUpcAttribute()) {
         $attributes[] = $this->config->getUpcAttribute();
     }
     return array_unique($attributes);
 }
 /**
  * Check whether notification is displayed
  *
  * @return bool
  */
 public function isDisplayed()
 {
     // Check configuration to see if this should be evaluated further
     if ($this->avaTaxConfig->isModuleEnabled() == false || $this->avaTaxConfig->getTaxMode($this->storeManager->getDefaultStoreView()) != Config::TAX_MODE_ESTIMATE_AND_SUBMIT || $this->avaTaxConfig->getQueueAdminNotificationEnabled() == false) {
         return false;
     }
     // Query the database to get some stats about the queue
     $this->loadQueueStats();
     // Determine if we need to notify the admin user
     if ($this->authorization->isAllowed('ClassyLlama_AvaTax::manage_avatax') && $this->statQueueCount > 0) {
         return true;
     } else {
         return false;
     }
 }
 /**
  * Get country list
  *
  * @return array
  */
 protected function getCountryList()
 {
     // It seems odd to check the parameters directly, but it's the same pattern being used in Magento_Backend
     if ($this->request->getParam('store')) {
         $scopeId = $this->request->getParam('store');
         $scopeType = \Magento\Store\Model\ScopeInterface::SCOPE_STORE;
     } elseif ($this->request->getParam('website')) {
         $scopeId = $this->request->getParam('website');
         $scopeType = \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE;
     } elseif ($this->request->getParam('group')) {
         $scopeId = $this->request->getParam('website');
         $scopeType = \Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE;
     } else {
         $scopeId = $this->storeManager->getDefaultStoreView();
         $scopeType = \Magento\Store\Model\ScopeInterface::SCOPE_STORE;
     }
     return explode(',', $this->config->getTaxCalculationCountriesEnabled($scopeId, $scopeType));
 }
 /**
  * Overrides payment component and adds config variable to be used in the component and template
  *
  * This class takes the place of a layout config change to checkout_index_index.xml. Making the changes to the
  * layout this way is necessary because in the process of merging the layout files, layout overrides are
  * applied over existing nodes in alphabetical order by Namespace_ModuleName. So Magento_Checkout overrides
  * ClassyLlama_AvaTax because Magento_Checkout layout files are merged after ClassyLlama_AvaTax layout files. The
  * solution is to set the value of the converted object after the layout files have been merged. Additionally,
  * because the config fields must be accessed from PHP, the most efficient method of setting the config node values
  * is with PHP as the following code does.
  *
  * @param array $jsLayout
  * @return array
  */
 public function process($jsLayout)
 {
     if ($this->config->isModuleEnabled()) {
         if ($this->config->isAddressValidationEnabled($this->storeManager->getStore())) {
             $userHasChoice = $this->config->allowUserToChooseAddress($this->storeManager->getStore());
             if ($userHasChoice) {
                 $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']['payment']['config']['instructions'] = $this->config->getAddressValidationInstructionsWithChoice($this->storeManager->getStore());
             } else {
                 $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']['payment']['config']['instructions'] = $this->config->getAddressValidationInstructionsWithoutChoice($this->storeManager->getStore());
             }
             $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']['payment']['config']['errorInstructions'] = $this->config->getAddressValidationErrorInstructions($this->storeManager->getStore());
             $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']['payment']['config']['choice'] = $userHasChoice;
             $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']['payment']['component'] = self::COMPONENT_PATH;
         }
     }
     return $jsLayout;
 }
Esempio n. 17
0
 /**
  * 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;
 }
 /**
  * @param Queue $queue
  * @param string $message
  * @param \Magento\Sales\Api\Data\InvoiceInterface|\Magento\Sales\Api\Data\CreditmemoInterface $entity
  */
 protected function resetQueueingForProcessing(Queue $queue, $message, $entity)
 {
     // Check retry attempts and determine if we need to fail processing
     // Add a comment to the order indicating what has been done
     if ($queue->getAttempts() >= $this->avaTaxConfig->getQueueMaxRetryAttempts()) {
         $message .= __(' The processing has failed due to reaching the maximum number of attempts to retry. ' . 'Any corrective measures will need to be initiated manually');
         // fail processing later by setting queue status to pending
         $this->failQueueProcessing($queue, $message);
         // Add comment to order
         $this->addOrderComment($entity->getOrderId(), $message);
     } else {
         $message .= __(' The processing is set to automatically retry on the next processing attempt.');
         // retry processing later by setting queue status to pending
         $queue->setMessage($message);
         $queue->setQueueStatus(Queue::QUEUE_STATUS_PENDING);
         $queue->save();
         // Add comment to order
         $this->addOrderComment($entity->getOrderId(), $message);
     }
 }
Esempio n. 19
0
 /**
  * Clear the queue of failed records based on config lifetime
  */
 protected function clearFailedQueue()
 {
     // Initialize the queue collection
     /** @var $queueCollection \ClassyLlama\AvaTax\Model\ResourceModel\Queue\Collection */
     $queueCollection = $this->queueCollectionFactory->create();
     $queueCollection->addQueueStatusFilter(Queue::QUEUE_STATUS_FAILED);
     // Get configuration for record lifetime
     $completeDays = $this->avaTaxConfig->getQueueFailedLifetime();
     // Calculate the number of seconds to adjust the filter
     // 86400 seconds == 60 seconds * 60 minutes * 24 hours == 1 day
     $secondsBeforeNow = $completeDays * 60 * 60 * 24;
     // Add filters
     $queueCollection->addCreatedAtBeforeFilter($secondsBeforeNow);
     $queueCollection->addUpdatedAtBeforeFilter($secondsBeforeNow);
     // Process each queued entity
     /** @var $queue Queue */
     foreach ($queueCollection as $queue) {
         // Remove the queue record
         $queue->delete();
         $this->deleteFailedCount++;
     }
 }
 /**
  * Writes the log record to a file based on admin configuration settings
  *
  * @param $record array
  * @return void
  */
 public function write(array $record)
 {
     // Filter the log details
     if ($this->avaTaxConfig->getLogFileDetail() == LogDetail::MINIMAL && $record['level'] >= Logger::WARNING) {
         if (isset($record['context']['extra'])) {
             unset($record['context']['extra']);
         }
     } elseif ($this->avaTaxConfig->getLogFileDetail() == LogDetail::NORMAL) {
         if (isset($record['context']['extra'])) {
             unset($record['context']['extra']);
         }
     } elseif ($this->avaTaxConfig->getLogFileDetail() == LogDetail::EXTRA) {
         // do not remove any of the context data
     } else {
         if (isset($record['context']['request'])) {
             unset($record['context']['request']);
         }
         if (isset($record['context']['result'])) {
             unset($record['context']['result']);
         }
         if (isset($record['context']['additional'])) {
             unset($record['context']['additional']);
         }
         if (isset($record['context']['extra'])) {
             unset($record['context']['extra']);
         }
     }
     // Write the log file
     if ($this->avaTaxConfig->getLogFileMode() == LogFileMode::COMBINED) {
         // forward the record to the default system handler for processing instead
         $this->systemHandler->handle($record);
     } elseif ($this->avaTaxConfig->getLogFileMode() == LogFileMode::SEPARATE && $this->avaTaxConfig->getLogFileBuiltinRotateEnabled()) {
         $this->writeWithRotation($record);
     } else {
         // write the log to the custom log file
         parent::write($record);
     }
 }
Esempio n. 21
0
 /**
  * Map extra taxables associated with quote. Add AvaTax details to extension objects.
  *
  * @param QuoteDetailsItemInterfaceFactory $itemDataObjectFactory
  * @param Address $address
  * @param bool $useBaseCurrency
  * @return \Magento\Tax\Api\Data\QuoteDetailsItemInterface[]
  */
 public function mapQuoteExtraTaxables(QuoteDetailsItemInterfaceFactory $itemDataObjectFactory, Address $address, $useBaseCurrency)
 {
     $itemDataObjects = parent::mapQuoteExtraTaxables($itemDataObjectFactory, $address, $useBaseCurrency);
     $storeId = $address->getQuote()->getStore()->getId();
     if (!$this->config->isModuleEnabled($storeId) || $this->config->getTaxMode($storeId) == Config::TAX_MODE_NO_ESTIMATE_OR_SUBMIT || !$this->config->isAddressTaxable($address, $storeId)) {
         return $itemDataObjects;
     }
     foreach ($itemDataObjects as $itemDataObject) {
         switch ($itemDataObject->getType()) {
             case Giftwrapping::QUOTE_TYPE:
                 $itemCode = $this->config->getSkuGiftWrapOrder($storeId);
                 $taxCode = $this->taxClassHelper->getAvataxTaxCodeForGiftOptions($storeId);
                 $this->addExtensionAttributesToTaxQuoteDetailsItem($itemDataObject, $itemCode, $taxCode, \ClassyLlama\AvaTax\Framework\Interaction\Line::GIFT_WRAP_ORDER_LINE_DESCRIPTION);
                 break;
             case Giftwrapping::PRINTED_CARD_TYPE:
                 $itemCode = $this->config->getSkuShippingGiftWrapCard($storeId);
                 $taxCode = $this->taxClassHelper->getAvataxTaxCodeForGiftOptions($storeId);
                 $this->addExtensionAttributesToTaxQuoteDetailsItem($itemDataObject, $itemCode, $taxCode, \ClassyLlama\AvaTax\Framework\Interaction\Line::GIFT_WRAP_ORDER_LINE_DESCRIPTION);
                 break;
         }
     }
     return $itemDataObjects;
 }
 /**
  * @return mixed
  */
 public function getCountriesEnabled()
 {
     return $this->config->getAddressValidationCountriesEnabled($this->_storeManager->getStore());
 }
 /**
  * Check whether notification is displayed
  *
  * @return bool
  */
 public function isDisplayed()
 {
     return $this->getText() && $this->isQueuePage() && $this->config->isModuleEnabled() && $this->config->getTaxMode($this->storeManager->getDefaultStoreView()) != Config::TAX_MODE_ESTIMATE_AND_SUBMIT;
 }
 /**
  * Check whether notification is displayed
  *
  * @return bool
  */
 public function isDisplayed()
 {
     return $this->getText() && $this->isTaxConfigPage() && $this->config->isModuleEnabled();
 }