OrderSave.php 9.41 KB
Newer Older
Ketan's avatar
Ketan committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
<?php
/**
 *
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

namespace Magento\Tax\Model\Plugin;

use Magento\Tax\Api\Data\OrderTaxDetailsAppliedTaxExtension;

class OrderSave
{
    /**
     * @var \Magento\Tax\Model\Sales\Order\TaxFactory
     */
    protected $orderTaxFactory;

    /**
     * @var \Magento\Sales\Model\Order\Tax\ItemFactory
     */
    protected $taxItemFactory;

    /**
     * @param \Magento\Tax\Model\Sales\Order\TaxFactory $orderTaxFactory
     * @param \Magento\Sales\Model\Order\Tax\ItemFactory $taxItemFactory
     */
    public function __construct(
        \Magento\Tax\Model\Sales\Order\TaxFactory $orderTaxFactory,
        \Magento\Sales\Model\Order\Tax\ItemFactory $taxItemFactory
    ) {
        $this->orderTaxFactory = $orderTaxFactory;
        $this->taxItemFactory = $taxItemFactory;
    }

    /**
     * Save order tax
     *
     * @param \Magento\Sales\Api\OrderRepositoryInterface $subject
     * @param \Magento\Sales\Api\Data\OrderInterface $order
     * @return \Magento\Sales\Api\Data\OrderInterface
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function afterSave(
        \Magento\Sales\Api\OrderRepositoryInterface $subject,
        \Magento\Sales\Api\Data\OrderInterface $order
    ) {
        $this->saveOrderTax($order);
        return $order;
    }

    /**
     * @param \Magento\Sales\Api\Data\OrderInterface $order
     * @return $this
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     * @SuppressWarnings(PHPMD.NPathComplexity)
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
     */
    protected function saveOrderTax(\Magento\Sales\Api\Data\OrderInterface $order)
    {
        $extensionAttribute = $order->getExtensionAttributes();
        if (!$extensionAttribute ||
            !$extensionAttribute->getConvertingFromQuote() ||
            $order->getAppliedTaxIsSaved()) {
            return;
        }

        /** @var \Magento\Tax\Api\Data\OrderTaxDetailsAppliedTaxInterface[]|null $taxes */
        $taxes = $extensionAttribute->getAppliedTaxes();
        if ($taxes == null) {
            $taxes = [];
        }

        /** @var \Magento\Tax\Api\Data\OrderTaxDetailsItemInterface[]|null $taxesForItems */
        $taxesForItems = $extensionAttribute->getItemAppliedTaxes();
        if ($taxesForItems == null) {
            $taxesForItems = [];
        }

        $ratesIdQuoteItemId = [];
        foreach ($taxesForItems as $taxesArray) {
            foreach ($taxesArray['applied_taxes'] as $rates) {
                if (isset($rates['extension_attributes'])) {
                    $taxRates = $rates['extension_attributes'] instanceof OrderTaxDetailsAppliedTaxExtension
                        ? $rates['extension_attributes']->getRates()
                        : $rates['extension_attributes']['rates'];
                    if (is_array($taxRates)) {
                        if (count($taxRates) == 1) {
                            $ratesIdQuoteItemId[$rates['id']][] = [
                                'id' => $taxesArray['item_id'],
                                'percent' => $rates['percent'],
                                'code' => $taxRates[0]['code'],
                                'associated_item_id' => $taxesArray['associated_item_id'],
                                'item_type' => $taxesArray['type'],
                                'amount' => $rates['amount'],
                                'base_amount' => $rates['base_amount'],
                                'real_amount' => $rates['amount'],
                                'real_base_amount' => $rates['base_amount'],
                            ];
                        } else {
                            $percentSum = 0;
                            foreach ($taxRates as $rate) {
                                $percentSum += $rate['percent'];
                            }

                            foreach ($taxRates as $rate) {
                                $realAmount = $rates['amount'] * $rate['percent'] / $percentSum;
                                $realBaseAmount = $rates['base_amount'] * $rate['percent'] / $percentSum;
                                $ratesIdQuoteItemId[$rates['id']][] = [
                                    'id' => $taxesArray['item_id'],
                                    'percent' => $rate['percent'],
                                    'code' => $rate['code'],
                                    'associated_item_id' => $taxesArray['associated_item_id'],
                                    'item_type' => $taxesArray['type'],
                                    'amount' => $rates['amount'],
                                    'base_amount' => $rates['base_amount'],
                                    'real_amount' => $realAmount,
                                    'real_base_amount' => $realBaseAmount,
                                ];
                            }
                        }
                    }
                }
            }
        }

        foreach ($taxes as $row) {
            $id = $row['id'];
            if (isset($row['extension_attributes'])) {
                $taxRates = $row['extension_attributes'] instanceof OrderTaxDetailsAppliedTaxExtension
                    ? $row['extension_attributes']->getRates()
                    : $row['extension_attributes']['rates'];
                if (is_array($taxRates)) {
                    foreach ($taxRates as $tax) {
                        if ($row['percent'] == null) {
                            $baseRealAmount = $row['base_amount'];
                        } else {
                            if ($row['percent'] == 0 || $tax['percent'] == 0) {
                                continue;
                            }
                            $baseRealAmount = $row['base_amount'] / $row['percent'] * $tax['percent'];
                        }
                        $hidden = isset($row['hidden']) ? $row['hidden'] : 0;
                        $priority = isset($tax['priority']) ? $tax['priority'] : 0;
                        $position = isset($tax['position']) ? $tax['position'] : 0;
                        $process = isset($row['process']) ? $row['process'] : 0;
                        $data = [
                            'order_id' => $order->getEntityId(),
                            'code' => $tax['code'],
                            'title' => $tax['title'],
                            'hidden' => $hidden,
                            'percent' => $tax['percent'],
                            'priority' => $priority,
                            'position' => $position,
                            'amount' => $row['amount'],
                            'base_amount' => $row['base_amount'],
                            'process' => $process,
                            'base_real_amount' => $baseRealAmount,
                        ];

                        /** @var $orderTax \Magento\Tax\Model\Sales\Order\Tax */
                        $orderTax = $this->orderTaxFactory->create();
                        $result = $orderTax->setData($data)->save();

                        if (isset($ratesIdQuoteItemId[$id])) {
                            foreach ($ratesIdQuoteItemId[$id] as $quoteItemId) {
                                if ($quoteItemId['code'] === $tax['code']) {
                                    $itemId = null;
                                    $associatedItemId = null;
                                    if (isset($quoteItemId['id'])) {
                                        //This is a product item
                                        $item = $order->getItemByQuoteItemId($quoteItemId['id']);
                                        if ($item !== null && $item->getId()) {
                                            $itemId = $item->getId();
                                        }
                                    } elseif (isset($quoteItemId['associated_item_id'])) {
                                        //This item is associated with a product item
                                        $item = $order->getItemByQuoteItemId($quoteItemId['associated_item_id']);
                                        $associatedItemId = $item->getId();
                                    }

                                    $data = [
                                        'item_id' => $itemId,
                                        'tax_id' => $result->getTaxId(),
                                        'tax_percent' => $quoteItemId['percent'],
                                        'associated_item_id' => $associatedItemId,
                                        'amount' => $quoteItemId['amount'],
                                        'base_amount' => $quoteItemId['base_amount'],
                                        'real_amount' => $quoteItemId['real_amount'],
                                        'real_base_amount' => $quoteItemId['real_base_amount'],
                                        'taxable_item_type' => $quoteItemId['item_type'],
                                    ];
                                    /** @var $taxItem \Magento\Sales\Model\Order\Tax\Item */
                                    $taxItem = $this->taxItemFactory->create();
                                    $taxItem->setData($data)->save();
                                }
                            }
                        }
                    }
                }
            }
        }

        $order->setAppliedTaxIsSaved(true);
        return $this;
    }
}