/**
  * Convert a quote/order/invoice/credit memo item to a tax details item objects
  *
  * This includes tax for the item as well as any additional line item tax information like Gift Wrapping
  *
  * @param QuoteDetailsItemInterface $item
  * @param GetTaxResult $getTaxResult
  * @param bool $useBaseCurrency
  * @param \Magento\Framework\App\ScopeInterface $scope
  * @return \Magento\Tax\Api\Data\TaxDetailsItemInterface
  */
 protected function getTaxDetailsItem(QuoteDetailsItemInterface $item, GetTaxResult $getTaxResult, $useBaseCurrency, $scope)
 {
     $price = $item->getUnitPrice();
     /* @var $taxLine \AvaTax\TaxLine  */
     $taxLine = $getTaxResult->getTaxLine($item->getCode());
     // Items that are children of other items won't have lines in the response
     if (!$taxLine instanceof \AvaTax\TaxLine) {
         return false;
     }
     $rate = (double) ($taxLine->getRate() * Tax::RATE_MULTIPLIER);
     $tax = (double) $taxLine->getTax();
     /**
      * Magento uses base rates for determining what to charge a customer, not the currency rate (i.e., the non-base
      * rate). Because of this, the base amounts are what is being sent to AvaTax for rate calculation. When we get
      * the base tax amounts back from AvaTax, we have to convert those to the current store's currency using the
      * \Magento\Framework\Pricing\PriceCurrencyInterface::convert() method. However if we simply convert the AvaTax
      * base tax amount * currency multiplier, we may run into issues due to rounding.
      *
      * For example, a $9.90 USD base price * a 6% tax rate equals a tax amount of $0.59 (.594 rounded). Assume the
      * current currency has a conversion rate of 2x. The price will display to the user as $19.80. There are two
      * ways we can calculate the tax amount:
      * 1. Multiply the tax amount received back from AvaTax, which would be $1.18 ($0.59 * 2).
      * 2. Multiply using this formula (base price * currency rate) * tax rate) ((9.99 * 2) * .06)
      *    which would be $1.19 (1.188 rounded)
      *
      * The second approach is more accurate and is what we are doing here.
      */
     if (!$useBaseCurrency) {
         /**
          * We could recalculate the amount using the same logic found in this class:
          * @see \ClassyLlama\AvaTax\Framework\Interaction\Line::convertTaxQuoteDetailsItemToData,
          * but using the taxable amount returned back from AvaTax is the only way to get an accurate amount as
          * some items sent to AvaTax may be tax exempt
          */
         $taxableAmount = (double) $taxLine->getTaxable();
         $amount = $this->priceCurrency->convert($taxableAmount, $scope);
         $tax = $amount * $taxLine->getRate();
         $tax = $this->calculationTool->round($tax);
     }
     $rowTax = $tax;
     /**
      * In native Magento, the "row_total_incl_tax" and "base_row_total_incl_tax" fields contain the tax before
      * discount. The AvaTax 15 API doesn't have the concept of before/after discount tax, so in order to determine
      * the "before discount tax amount", we need to multiply the discount by the rate returned by AvaTax.
      * @see \Magento\Tax\Model\Calculation\AbstractAggregateCalculator::calculateWithTaxNotInPrice
      *
      * If the rate is 0, then this product doesn't have taxes applied and tax on discount shouldn't be calculated.
      * If tax is 0, then item was tax-exempt for some reason and tax on discount shouldn't be calculated
      */
     if ($taxLine->getRate() > 0 && $tax > 0) {
         /**
          * Accurately calculating what AvaTax would have charged before discount requires checking to see if any
          * of the tax amount is tax exempt. If so, we need to find out what percentage of the total amount AvaTax
          * deemed as taxable and then use that percentage when calculating the discount amount. This partially
          * taxable scenario can arise in a situation like this:
          * @see https://help.avalara.com/kb/001/Why_is_freight_taxed_partially_on_my_sale
          *
          * To test this functionality, you can create a "Base Override" Tax Rule in the AvaTax admin to mark certain
          * jurisdictions as partially taxable.
          */
         $taxableAmountPercentage = 1;
         if ($taxLine->getExemption() > 0) {
             // This value is the total amount sent to AvaTax for tax calculation, before AvaTax determined what
             // portion of the amount is taxable
             $totalAmount = $taxLine->getTaxable() + $taxLine->getExemption();
             // Avoid division by 0
             if ($totalAmount != 0) {
                 $taxableAmountPercentage = $taxLine->getTaxable() / $totalAmount;
             }
         }
         $effectiveDiscountAmount = $taxableAmountPercentage * $item->getDiscountAmount();
         $taxOnDiscountAmount = $effectiveDiscountAmount * $taxLine->getRate();
         $taxOnDiscountAmount = $this->calculationTool->round($taxOnDiscountAmount);
         $rowTaxBeforeDiscount = $rowTax + $taxOnDiscountAmount;
     } else {
         $rowTaxBeforeDiscount = 0;
     }
     $extensionAttributes = $item->getExtensionAttributes();
     if ($extensionAttributes) {
         $quantity = $extensionAttributes->getTotalQuantity() !== null ? $extensionAttributes->getTotalQuantity() : $item->getQuantity();
     } else {
         $quantity = $item->getQuantity();
     }
     $rowTotal = $price * $quantity;
     $rowTotalInclTax = $rowTotal + $rowTaxBeforeDiscount;
     $priceInclTax = $rowTotalInclTax / $quantity;
     /**
      * Since the AvaTax extension does not support merchants adding products with tax already factored into the
      * price, we don't need to do any calculations for this number. The only time this value would be something
      * other than 0 is when this method runs:
      * @see \Magento\Tax\Model\Calculation\AbstractAggregateCalculator::calculateWithTaxInPrice
      */
     $discountTaxCompensationAmount = 0;
     /**
      * The \Magento\Tax\Model\Calculation\AbstractAggregateCalculator::calculateWithTaxNotInPrice method that this
      * method is patterned off of has $round as a variable, but any time that method is used in the context of a
      * collect totals on a quote, rounding is always used.
      */
     $round = true;
     if ($round) {
         $priceInclTax = $this->calculationTool->round($priceInclTax);
     }
     $appliedTax = $this->getAppliedTax($getTaxResult, $rowTax);
     $appliedTaxes = [$appliedTax->getTaxRateKey() => $appliedTax];
     return $this->taxDetailsItemDataObjectFactory->create()->setCode($item->getCode())->setType($item->getType())->setRowTax($rowTax)->setPrice($price)->setPriceInclTax($priceInclTax)->setRowTotal($rowTotal)->setRowTotalInclTax($rowTotalInclTax)->setDiscountTaxCompensationAmount($discountTaxCompensationAmount)->setAssociatedItemCode($item->getAssociatedItemCode())->setTaxPercent($rate)->setAppliedTaxes($appliedTaxes);
 }