9 use Magento\Customer\Api\Data\AddressInterfaceFactory as CustomerAddressFactory;
11 use Magento\Customer\Api\Data\RegionInterfaceFactory as CustomerAddressRegionFactory;
17 use Magento\Tax\Api\Data\QuoteDetailsInterfaceFactory;
18 use Magento\Tax\Api\Data\TaxClassKeyInterfaceFactory;
154 $this->_config = $taxConfig;
172 $this->customerAddressRegionFactory->create()->setRegionId(
$address->getRegionId())
191 public function mapItem(
192 \
Magento\
Tax\Api\Data\QuoteDetailsItemInterfaceFactory $itemDataObjectFactory,
198 if (!
$item->getTaxCalculationItemId()) {
200 $item->setTaxCalculationItemId($sequence);
203 $itemDataObject = $itemDataObjectFactory->create();
204 $itemDataObject->setCode(
$item->getTaxCalculationItemId())
205 ->setQuantity(
$item->getQty())
207 $this->taxClassKeyDataObjectFactory->create()
209 ->setValue(
$item->getProduct()->getTaxClassId())
211 ->setIsTaxIncluded($priceIncludesTax)
212 ->setType(self::ITEM_TYPE_PRODUCT);
214 if ($useBaseCurrency) {
215 if (!
$item->getBaseTaxCalculationPrice()) {
216 $item->setBaseTaxCalculationPrice(
$item->getBaseCalculationPriceOriginal());
218 $itemDataObject->setUnitPrice(
$item->getBaseTaxCalculationPrice())
219 ->setDiscountAmount(
$item->getBaseDiscountAmount());
221 if (!
$item->getTaxCalculationPrice()) {
222 $item->setTaxCalculationPrice(
$item->getCalculationPriceOriginal());
224 $itemDataObject->setUnitPrice(
$item->getTaxCalculationPrice())
225 ->setDiscountAmount(
$item->getDiscountAmount());
228 $itemDataObject->setParentCode($parentCode);
230 return $itemDataObject;
242 public function mapItemExtraTaxables(
243 \
Magento\Tax\Api\Data\QuoteDetailsItemInterfaceFactory $itemDataObjectFactory,
248 $itemDataObjects = [];
249 $extraTaxables =
$item->getAssociatedTaxables();
250 if (!$extraTaxables) {
254 foreach ($extraTaxables as $extraTaxable) {
255 $extraTaxableIncludesTax =
256 isset($extraTaxable[
'price_includes_tax']) ? $extraTaxable[
'price_includes_tax'] : $priceIncludesTax;
258 if ($useBaseCurrency) {
264 $itemDataObject = $itemDataObjectFactory->create();
265 $itemDataObject->setCode($extraTaxable[self::KEY_ASSOCIATED_TAXABLE_CODE])
266 ->setType($extraTaxable[self::KEY_ASSOCIATED_TAXABLE_TYPE])
267 ->setQuantity($extraTaxable[self::KEY_ASSOCIATED_TAXABLE_QUANTITY])
269 $this->taxClassKeyDataObjectFactory->create()
271 ->setValue($extraTaxable[self::KEY_ASSOCIATED_TAXABLE_TAX_CLASS_ID])
273 ->setUnitPrice($unitPrice)
274 ->setIsTaxIncluded($extraTaxableIncludesTax)
275 ->setAssociatedItemCode(
$item->getTaxCalculationItemId());
276 $itemDataObjects[] = $itemDataObject;
279 return $itemDataObjects;
302 $itemDataObjects = [];
304 if (
$item->getParentItem()) {
308 if (
$item->getHasChildren() &&
$item->isChildrenCalculated()) {
309 $parentItemDataObject = $this->mapItem(
310 $itemDataObjectFactory,
315 $itemDataObjects[] = $parentItemDataObject;
316 foreach (
$item->getChildren() as $child) {
317 $childItemDataObject = $this->mapItem(
318 $itemDataObjectFactory,
322 $parentItemDataObject->getCode()
324 $itemDataObjects[] = $childItemDataObject;
325 $extraTaxableItems = $this->mapItemExtraTaxables(
326 $itemDataObjectFactory,
331 $itemDataObjects = array_merge($itemDataObjects, $extraTaxableItems);
334 $itemDataObject = $this->mapItem($itemDataObjectFactory,
$item, $priceIncludesTax, $useBaseCurrency);
335 $itemDataObjects[] = $itemDataObject;
336 $extraTaxableItems = $this->mapItemExtraTaxables(
337 $itemDataObjectFactory,
342 $itemDataObjects = array_merge($itemDataObjects, $extraTaxableItems);
346 return $itemDataObjects;
360 return $quoteDetails;
369 public function getShippingDataObject(
374 $store = $shippingAssignment->
getShipping()->getAddress()->getQuote()->getStore();
375 if (
$total->getShippingTaxCalculationAmount() ===
null) {
378 $total->setShippingTaxCalculationAmount(
$total->getShippingAmount());
379 $total->setBaseShippingTaxCalculationAmount(
$total->getBaseShippingAmount());
381 if (
$total->getShippingTaxCalculationAmount() !==
null) {
383 $itemDataObject = $this->quoteDetailsItemDataObjectFactory->create()
384 ->setType(self::ITEM_TYPE_SHIPPING)
385 ->setCode(self::ITEM_CODE_SHIPPING)
387 if ($useBaseCurrency) {
388 $itemDataObject->setUnitPrice(
$total->getBaseShippingTaxCalculationAmount());
390 $itemDataObject->setUnitPrice(
$total->getShippingTaxCalculationAmount());
392 if (
$total->getShippingDiscountAmount()) {
393 if ($useBaseCurrency) {
394 $itemDataObject->setDiscountAmount(
$total->getBaseShippingDiscountAmount());
396 $itemDataObject->setDiscountAmount(
$total->getShippingDiscountAmount());
399 $itemDataObject->setTaxClassKey(
400 $this->taxClassKeyDataObjectFactory->create()
402 ->setValue($this->_config->getShippingTaxClass(
$store))
404 $itemDataObject->setIsTaxIncluded(
405 $this->_config->shippingPriceIncludesTax(
$store)
407 return $itemDataObject;
425 return $this->quoteDetailsDataObjectFactory->create();
428 $quoteDetails = $this->quoteDetailsDataObjectFactory->create();
432 $quoteDetails->setCustomerTaxClassKey(
433 $this->taxClassKeyDataObjectFactory->create()
435 ->setValue(
$address->getQuote()->getCustomerTaxClassId())
437 $quoteDetails->setItems($itemDataObjects);
438 $quoteDetails->setCustomerId(
$address->getQuote()->getCustomerId());
440 return $quoteDetails;
450 protected function organizeItemTaxDetailsByType(
460 $baseKeyedItems = [];
467 $baseItem = $baseKeyedItems[
$code];
468 $itemType =
$item->getType();
469 $itemsByType[$itemType][
$code] = [self::KEY_ITEM =>
$item, self::KEY_BASE_ITEM => $baseItem];
485 protected function processProductItems(
486 ShippingAssignmentInterface $shippingAssignment,
487 array $itemTaxDetails,
490 $store = $shippingAssignment->getShipping()->getAddress()->getQuote()->getStore();
493 $keyedAddressItems = [];
494 foreach ($shippingAssignment->getItems() as $addressItem) {
495 $keyedAddressItems[$addressItem->getTaxCalculationItemId()] = $addressItem;
498 $subtotal = $baseSubtotal = 0;
499 $discountTaxCompensation = $baseDiscountTaxCompensation = 0;
501 $subtotalInclTax = $baseSubtotalInclTax = 0;
503 foreach ($itemTaxDetails as
$code => $itemTaxDetail) {
516 $subtotal += $taxDetail->getRowTotal();
517 $baseSubtotal += $baseTaxDetail->getRowTotal();
518 $discountTaxCompensation += $taxDetail->getDiscountTaxCompensationAmount();
519 $baseDiscountTaxCompensation += $baseTaxDetail->getDiscountTaxCompensationAmount();
520 $tax += $taxDetail->getRowTax();
521 $baseTax += $baseTaxDetail->getRowTax();
522 $subtotalInclTax += $taxDetail->getRowTotalInclTax();
523 $baseSubtotalInclTax += $baseTaxDetail->getRowTotalInclTax();
527 $total->setTotalAmount(
'subtotal', $subtotal);
528 $total->setBaseTotalAmount(
'subtotal', $baseSubtotal);
530 $total->setBaseTotalAmount(
'tax', $baseTax);
531 $total->setTotalAmount(
'discount_tax_compensation', $discountTaxCompensation);
532 $total->setBaseTotalAmount(
'discount_tax_compensation', $baseDiscountTaxCompensation);
534 $total->setSubtotalInclTax($subtotalInclTax);
535 $total->setBaseSubtotalTotalInclTax($baseSubtotalInclTax);
536 $total->setBaseSubtotalInclTax($baseSubtotalInclTax);
537 $shippingAssignment->getShipping()->getAddress()->setBaseSubtotalTotalInclTax($baseSubtotalInclTax);
549 protected function processAppliedTaxes(
551 ShippingAssignmentInterface $shippingAssignment,
554 $total->setAppliedTaxes([]);
555 $allAppliedTaxesArray = [];
558 $keyedAddressItems = [];
559 foreach ($shippingAssignment->getItems() as $addressItem) {
560 $keyedAddressItems[$addressItem->getTaxCalculationItemId()] = $addressItem;
563 foreach ($itemsByType as $itemType =>
$items) {
564 foreach (
$items as $itemTaxCalculationId => $itemTaxDetails) {
572 $itemType = $taxDetails->getType();
574 $associatedItemId =
null;
575 if ($itemType == self::ITEM_TYPE_PRODUCT) {
577 $itemId = $keyedAddressItems[$itemTaxCalculationId]->getId();
579 if ($taxDetails->getAssociatedItemCode()
582 $associatedItemId = $keyedAddressItems[$taxDetails->getAssociatedItemCode()]->getId();
589 'item_id' => $itemId,
590 'item_type' => $itemType,
591 'associated_item_id' => $associatedItemId,
594 $appliedTaxesArray = $this->
convertAppliedTaxes($appliedTaxes, $baseAppliedTaxes, $extraInfo);
596 if ($itemType == self::ITEM_TYPE_PRODUCT) {
597 $quoteItem = $keyedAddressItems[$itemTaxCalculationId];
598 $quoteItem->setAppliedTaxes($appliedTaxesArray);
601 $allAppliedTaxesArray[$itemTaxCalculationId] = $appliedTaxesArray;
603 foreach ($appliedTaxesArray as $appliedTaxArray) {
607 $appliedTaxArray[
'amount'],
608 $appliedTaxArray[
'base_amount'],
609 $appliedTaxArray[
'percent']
615 $total->setItemsAppliedTaxes($allAppliedTaxesArray);
632 $quoteItem->setPrice($baseItemTaxDetails->getPrice());
633 $quoteItem->setConvertedPrice($itemTaxDetails->getPrice());
634 $quoteItem->setPriceInclTax($itemTaxDetails->getPriceInclTax());
635 $quoteItem->setRowTotal($itemTaxDetails->getRowTotal());
636 $quoteItem->setRowTotalInclTax($itemTaxDetails->getRowTotalInclTax());
637 $quoteItem->setTaxAmount($itemTaxDetails->getRowTax());
638 $quoteItem->setTaxPercent($itemTaxDetails->getTaxPercent());
639 $quoteItem->setDiscountTaxCompensationAmount($itemTaxDetails->getDiscountTaxCompensationAmount());
641 $quoteItem->setBasePrice($baseItemTaxDetails->getPrice());
642 $quoteItem->setBasePriceInclTax($baseItemTaxDetails->getPriceInclTax());
643 $quoteItem->setBaseRowTotal($baseItemTaxDetails->getRowTotal());
644 $quoteItem->setBaseRowTotalInclTax($baseItemTaxDetails->getRowTotalInclTax());
645 $quoteItem->setBaseTaxAmount($baseItemTaxDetails->getRowTax());
646 $quoteItem->setTaxPercent($baseItemTaxDetails->getTaxPercent());
647 $quoteItem->setBaseDiscountTaxCompensationAmount($baseItemTaxDetails->getDiscountTaxCompensationAmount());
650 if ($this->_config->discountTax(
$store)) {
651 $quoteItem->setDiscountCalculationPrice($itemTaxDetails->getPriceInclTax());
652 $quoteItem->setBaseDiscountCalculationPrice($baseItemTaxDetails->getPriceInclTax());
654 $quoteItem->setDiscountCalculationPrice($itemTaxDetails->getPrice());
655 $quoteItem->setBaseDiscountCalculationPrice($baseItemTaxDetails->getPrice());
674 $baseShippingTaxDetails
676 $total->setTotalAmount(
'shipping', $shippingTaxDetails->getRowTotal());
677 $total->setBaseTotalAmount(
'shipping', $baseShippingTaxDetails->getRowTotal());
679 'shipping_discount_tax_compensation',
680 $shippingTaxDetails->getDiscountTaxCompensationAmount()
682 $total->setBaseTotalAmount(
683 'shipping_discount_tax_compensation',
684 $baseShippingTaxDetails->getDiscountTaxCompensationAmount()
687 $total->setShippingInclTax($shippingTaxDetails->getRowTotalInclTax());
688 $total->setBaseShippingInclTax($baseShippingTaxDetails->getRowTotalInclTax());
689 $total->setShippingTaxAmount($shippingTaxDetails->getRowTax());
690 $total->setBaseShippingTaxAmount($baseShippingTaxDetails->getRowTax());
693 $total->addTotalAmount(
'tax', $shippingTaxDetails->getRowTax());
694 $total->addBaseTotalAmount(
'tax', $baseShippingTaxDetails->getRowTax());
696 if ($this->_config->discountTax($shippingAssignment->
getShipping()->getAddress()->getQuote()->getStore())) {
697 $total->setShippingAmountForDiscount($shippingTaxDetails->getRowTotalInclTax());
698 $total->setBaseShippingAmountForDiscount($baseShippingTaxDetails->getRowTotalInclTax());
714 $appliedTaxesArray = [];
716 if (!$appliedTaxes || !$baseAppliedTaxes) {
717 return $appliedTaxesArray;
720 foreach ($appliedTaxes as $taxId => $appliedTax) {
721 $baseAppliedTax = $baseAppliedTaxes[$taxId];
722 $rateDataObjects = $appliedTax->getRates();
725 foreach ($rateDataObjects as $rateDataObject) {
727 'percent' => $rateDataObject->getPercent(),
728 'code' => $rateDataObject->getCode(),
729 'title' => $rateDataObject->getTitle(),
734 'amount' => $appliedTax->getAmount(),
735 'base_amount' => $baseAppliedTax->getAmount(),
736 'percent' => $appliedTax->getPercent(),
737 'id' => $appliedTax->getTaxRateKey(),
740 if (!empty($extraInfo)) {
741 $appliedTaxArray = array_merge($appliedTaxArray, $extraInfo);
744 $appliedTaxesArray[] = $appliedTaxArray;
747 return $appliedTaxesArray;
769 $previouslyAppliedTaxes =
$total->getAppliedTaxes();
770 $process = count($previouslyAppliedTaxes);
772 foreach ($applied as
$row) {
773 if (
$row[
'percent'] == 0) {
776 if (!isset($previouslyAppliedTaxes[
$row[
'id']])) {
777 $row[
'process'] = $process;
779 $row[
'base_amount'] = 0;
780 $previouslyAppliedTaxes[
$row[
'id']] =
$row;
783 if (
$row[
'percent'] !==
null) {
784 $row[
'percent'] =
$row[
'percent'] ?
$row[
'percent'] : 1;
791 $baseAppliedAmount = 0;
793 $appliedAmount +=
$rate[
'amount'];
794 $baseAppliedAmount +=
$rate[
'base_amount'];
798 if ($appliedAmount || $previouslyAppliedTaxes[
$row[
'id']][
'amount']) {
799 $previouslyAppliedTaxes[
$row[
'id']][
'amount'] += $appliedAmount;
800 $previouslyAppliedTaxes[
$row[
'id']][
'base_amount'] += $baseAppliedAmount;
802 unset($previouslyAppliedTaxes[
$row[
'id']]);
805 $total->setAppliedTaxes($previouslyAppliedTaxes);
setBillingAddress(\Magento\Customer\Api\Data\AddressInterface $billingAddress=null)
__construct(\Magento\Tax\Model\Config $taxConfig, \Magento\Tax\Api\TaxCalculationInterface $taxCalculationService, \Magento\Tax\Api\Data\QuoteDetailsInterfaceFactory $quoteDetailsDataObjectFactory, \Magento\Tax\Api\Data\QuoteDetailsItemInterfaceFactory $quoteDetailsItemDataObjectFactory, \Magento\Tax\Api\Data\TaxClassKeyInterfaceFactory $taxClassKeyDataObjectFactory, CustomerAddressFactory $customerAddressFactory, CustomerAddressRegionFactory $customerAddressRegionFactory)
const KEY_TAX_DETAILS_BASE_ROW_TAX
const KEY_ASSOCIATED_TAXABLE_CODE
mapAddress(QuoteAddress $address)
const KEY_TAX_DETAILS_CODE
const KEY_ASSOCIATED_TAXABLE_PRICE_INCLUDES_TAX
$taxClassKeyDataObjectFactory
const KEY_TAX_DETAILS_TYPE
const KEY_ASSOCIATED_TAXABLE_UNIT_PRICE
const KEY_ASSOCIATED_TAXABLE_BASE_UNIT_PRICE
const KEY_TAX_DETAILS_TAX_PERCENT
const KEY_TAX_DETAILS_BASE_PRICE_EXCL_TAX
const ASSOCIATION_ITEM_CODE_FOR_QUOTE
populateAddressData(QuoteDetailsInterface $quoteDetails, QuoteAddress $address)
$customerAddressRegionFactory
setShippingAddress(\Magento\Customer\Api\Data\AddressInterface $shippingAddress=null)
convertAppliedTaxes($appliedTaxes, $baseAppliedTaxes, $extraInfo=[])
const KEY_TAX_DETAILS_BASE_PRICE_INCL_TAX
const KEY_TAX_DETAILS_BASE_ROW_TOTAL
const KEY_TAX_DETAILS_PRICE_EXCL_TAX
updateItemTaxInfo($quoteItem, $itemTaxDetails, $baseItemTaxDetails, $store)
const KEY_ASSOCIATED_TAXABLE_TYPE
const KEY_TAX_DETAILS_ROW_TOTAL_INCL_TAX
mapItems(ShippingAssignmentInterface $shippingAssignment, $priceIncludesTax, $useBaseCurrency)
const KEY_TAX_DETAILS_ROW_TAX
const KEY_TAX_DETAILS_ROW_TOTAL
const KEY_ASSOCIATED_TAXABLE_QUANTITY
const KEY_TAX_DETAILS_BASE_ROW_TOTAL_INCL_TAX
prepareQuoteDetails(ShippingAssignmentInterface $shippingAssignment, $itemDataObjects)
$quoteDetailsItemDataObjectFactory
processShippingTaxInfo(ShippingAssignmentInterface $shippingAssignment, QuoteAddress\Total $total, $shippingTaxDetails, $baseShippingTaxDetails)
_saveAppliedTaxes(QuoteAddress\Total $total, $applied, $amount, $baseAmount, $rate)
const KEY_TAX_DETAILS_PRICE_INCL_TAX
const KEY_ASSOCIATED_TAXABLE_ASSOCIATION_ITEM_CODE
const KEY_TAX_DETAILS_APPLIED_TAXES
const KEY_ASSOCIATED_TAXABLE_TAX_CLASS_ID
$quoteDetailsDataObjectFactory