Skip to content

Commit 69c8bc9

Browse files
Merge remote-tracking branch 'remotes/github/MC-4316' into EPAM-PR-40
2 parents c2500fa + 1ca3699 commit 69c8bc9

File tree

12 files changed

+262
-15
lines changed

12 files changed

+262
-15
lines changed

app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
<requiredEntity type="product_extension_attribute">EavStockItem</requiredEntity>
3636
<requiredEntity type="custom_attribute_array">CustomAttributeCategoryIds</requiredEntity>
3737
</entity>
38+
<entity name="ApiSimpleProductWithCustomPrice" type="product" extends="ApiSimpleProduct">
39+
<data key="price">100</data>
40+
</entity>
3841
<entity name="ApiSimpleProductUpdateDescription" type="product2">
3942
<requiredEntity type="custom_attribute">ApiProductDescription</requiredEntity>
4043
<requiredEntity type="custom_attribute">ApiProductShortDescription</requiredEntity>

app/code/Magento/Config/Test/Mftf/ActionGroup/ConfigSalesTaxClassActionGroup.xml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,32 @@
2828
<click selector="{{SalesConfigSection.TaxClassesTab}}" stepKey="collapseTaxClassesTab"/>
2929
<click selector="{{ContentManagementSection.Save}}" stepKey="saveConfiguration"/>
3030
</actionGroup>
31+
<actionGroup name="SetTaxApplyOnSetting">
32+
<arguments>
33+
<argument name="userInput" type="string"/>
34+
</arguments>
35+
<conditionalClick selector="{{AdminConfigureTaxSection.taxCalculationSettings}}" dependentSelector="{{AdminConfigureTaxSection.taxCalculationAlgorithm}}" visible="false" stepKey="openTaxCalcSettingsSection"/>
36+
<scrollTo selector="{{AdminConfigureTaxSection.taxCalculationApplyTaxOnInherit}}" stepKey="goToCheckbox"/>
37+
<uncheckOption selector="{{AdminConfigureTaxSection.taxCalculationApplyTaxOnInherit}}" stepKey="enableApplyTaxOnSetting"/>
38+
<selectOption selector="{{AdminConfigureTaxSection.taxCalculationApplyTaxOn}}" userInput="{{userInput}}" stepKey="setApplyTaxOn"/>
39+
<scrollTo selector="{{SalesConfigSection.TaxClassesTab}}" stepKey="scrollToTop"/>
40+
<click selector="{{AdminConfigureTaxSection.taxCalculationSettings}}" stepKey="collapseCalcSettingsTab"/>
41+
<click selector="{{AdminConfigureTaxSection.save}}" stepKey="saveConfig"/>
42+
<waitForPageLoad stepKey="waitForConfigSaved"/>
43+
<see userInput="You saved the configuration." stepKey="seeSuccessMessage"/>
44+
</actionGroup>
45+
<actionGroup name="DisableTaxApplyOnOriginalPrice">
46+
<arguments>
47+
<argument name="userInput" type="string"/>
48+
</arguments>
49+
<amOnPage url="{{AdminSalesTaxClassPage.url}}" stepKey="navigateToSalesTaxPage"/>
50+
<waitForPageLoad stepKey="waitForPageLoad"/>
51+
<conditionalClick selector="{{AdminConfigureTaxSection.taxCalculationSettings}}" dependentSelector="{{AdminConfigureTaxSection.taxCalculationAlgorithm}}" visible="false" stepKey="openTaxCalcSettingsSection"/>
52+
<scrollTo selector="{{AdminConfigureTaxSection.taxCalculationApplyTaxOnInherit}}" stepKey="goToCheckbox"/>
53+
<selectOption selector="{{AdminConfigureTaxSection.taxCalculationApplyTaxOn}}" userInput="{{userInput}}" stepKey="setApplyTaxOff"/>
54+
<checkOption selector="{{AdminConfigureTaxSection.taxCalculationApplyTaxOnInherit}}" stepKey="disableApplyTaxOnSetting"/>
55+
<click selector="{{AdminConfigureTaxSection.save}}" stepKey="saveConfig"/>
56+
<waitForPageLoad stepKey="waitForConfigSaved"/>
57+
<see userInput="You saved the configuration." stepKey="seeSuccessMessage"/>
58+
</actionGroup>
3159
</actionGroups>

app/code/Magento/Tax/Model/Calculation/AbstractAggregateCalculator.php

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77

88
use Magento\Tax\Api\Data\QuoteDetailsItemInterface;
99

10+
/**
11+
* Abstract aggregate calculator.
12+
*/
1013
abstract class AbstractAggregateCalculator extends AbstractCalculator
1114
{
1215
/**
@@ -106,11 +109,12 @@ protected function calculateWithTaxNotInPrice(QuoteDetailsItemInterface $item, $
106109
$rowTaxes = [];
107110
$rowTaxesBeforeDiscount = [];
108111
$appliedTaxes = [];
112+
$rowTotalForTaxCalculation = $this->getPriceForTaxCalculation($item, $price) * $quantity;
109113
//Apply each tax rate separately
110114
foreach ($appliedRates as $appliedRate) {
111115
$taxId = $appliedRate['id'];
112116
$taxRate = $appliedRate['percent'];
113-
$rowTaxPerRate = $this->calculationTool->calcTaxAmount($rowTotal, $taxRate, false, false);
117+
$rowTaxPerRate = $this->calculationTool->calcTaxAmount($rowTotalForTaxCalculation, $taxRate, false, false);
114118
$deltaRoundingType = self::KEY_REGULAR_DELTA_ROUNDING;
115119
if ($applyTaxAfterDiscount) {
116120
$deltaRoundingType = self::KEY_TAX_BEFORE_DISCOUNT_DELTA_ROUNDING;
@@ -121,7 +125,10 @@ protected function calculateWithTaxNotInPrice(QuoteDetailsItemInterface $item, $
121125
//Handle discount
122126
if ($applyTaxAfterDiscount) {
123127
//TODO: handle originalDiscountAmount
124-
$taxableAmount = max($rowTotal - $discountAmount, 0);
128+
$taxableAmount = max($rowTotalForTaxCalculation - $discountAmount, 0);
129+
if ($taxableAmount && !$applyTaxAfterDiscount) {
130+
$taxableAmount = $rowTotalForTaxCalculation;
131+
}
125132
$rowTaxAfterDiscount = $this->calculationTool->calcTaxAmount(
126133
$taxableAmount,
127134
$taxRate,
@@ -168,6 +175,26 @@ protected function calculateWithTaxNotInPrice(QuoteDetailsItemInterface $item, $
168175
->setAppliedTaxes($appliedTaxes);
169176
}
170177

178+
/**
179+
* Get price for tax calculation.
180+
*
181+
* @param QuoteDetailsItemInterface $item
182+
* @param float $price
183+
* @return float
184+
*/
185+
private function getPriceForTaxCalculation(QuoteDetailsItemInterface $item, float $price)
186+
{
187+
if ($item->getExtensionAttributes() && $item->getExtensionAttributes()->getPriceForTaxCalculation()) {
188+
$priceForTaxCalculation = $this->calculationTool->round(
189+
$item->getExtensionAttributes()->getPriceForTaxCalculation()
190+
);
191+
} else {
192+
$priceForTaxCalculation = $price;
193+
}
194+
195+
return $priceForTaxCalculation;
196+
}
197+
171198
/**
172199
* Round amount
173200
*

app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php

Lines changed: 71 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,17 @@
1515
use Magento\Quote\Model\Quote\Item\AbstractItem;
1616
use Magento\Store\Model\Store;
1717
use Magento\Tax\Api\Data\QuoteDetailsInterfaceFactory;
18+
use Magento\Tax\Api\Data\QuoteDetailsItemInterface;
1819
use Magento\Tax\Api\Data\TaxClassKeyInterfaceFactory;
1920
use Magento\Tax\Api\Data\TaxClassKeyInterface;
2021
use Magento\Tax\Api\Data\TaxDetailsInterface;
2122
use Magento\Tax\Api\Data\TaxDetailsItemInterface;
2223
use Magento\Tax\Api\Data\QuoteDetailsInterface;
2324
use Magento\Quote\Api\Data\ShippingAssignmentInterface;
25+
use Magento\Tax\Helper\Data as TaxHelper;
26+
use Magento\Framework\App\ObjectManager;
27+
use Magento\Tax\Api\Data\QuoteDetailsItemExtensionInterface;
28+
use Magento\Tax\Api\Data\QuoteDetailsItemExtensionInterfaceFactory;
2429

2530
/**
2631
* Tax totals calculation model
@@ -129,6 +134,16 @@ class CommonTaxCollector extends AbstractTotal
129134
*/
130135
protected $quoteDetailsItemDataObjectFactory;
131136

137+
/**
138+
* @var TaxHelper
139+
*/
140+
private $taxHelper;
141+
142+
/**
143+
* @var QuoteDetailsItemExtensionInterfaceFactory
144+
*/
145+
private $quoteDetailsItemExtensionFactory;
146+
132147
/**
133148
* Class constructor
134149
*
@@ -139,6 +154,8 @@ class CommonTaxCollector extends AbstractTotal
139154
* @param \Magento\Tax\Api\Data\TaxClassKeyInterfaceFactory $taxClassKeyDataObjectFactory
140155
* @param CustomerAddressFactory $customerAddressFactory
141156
* @param CustomerAddressRegionFactory $customerAddressRegionFactory
157+
* @param TaxHelper|null $taxHelper
158+
* @param QuoteDetailsItemExtensionInterfaceFactory|null $quoteDetailsItemExtensionInterfaceFactory
142159
*/
143160
public function __construct(
144161
\Magento\Tax\Model\Config $taxConfig,
@@ -147,7 +164,9 @@ public function __construct(
147164
\Magento\Tax\Api\Data\QuoteDetailsItemInterfaceFactory $quoteDetailsItemDataObjectFactory,
148165
\Magento\Tax\Api\Data\TaxClassKeyInterfaceFactory $taxClassKeyDataObjectFactory,
149166
CustomerAddressFactory $customerAddressFactory,
150-
CustomerAddressRegionFactory $customerAddressRegionFactory
167+
CustomerAddressRegionFactory $customerAddressRegionFactory,
168+
TaxHelper $taxHelper = null,
169+
QuoteDetailsItemExtensionInterfaceFactory $quoteDetailsItemExtensionInterfaceFactory = null
151170
) {
152171
$this->taxCalculationService = $taxCalculationService;
153172
$this->quoteDetailsDataObjectFactory = $quoteDetailsDataObjectFactory;
@@ -156,6 +175,9 @@ public function __construct(
156175
$this->quoteDetailsItemDataObjectFactory = $quoteDetailsItemDataObjectFactory;
157176
$this->customerAddressFactory = $customerAddressFactory;
158177
$this->customerAddressRegionFactory = $customerAddressRegionFactory;
178+
$this->taxHelper = $taxHelper ?: ObjectManager::getInstance()->get(TaxHelper::class);
179+
$this->quoteDetailsItemExtensionFactory = $quoteDetailsItemExtensionInterfaceFactory ?:
180+
ObjectManager::getInstance()->get(QuoteDetailsItemExtensionInterfaceFactory::class);
159181
}
160182

161183
/**
@@ -186,7 +208,7 @@ public function mapAddress(QuoteAddress $address)
186208
* @param bool $priceIncludesTax
187209
* @param bool $useBaseCurrency
188210
* @param string $parentCode
189-
* @return \Magento\Tax\Api\Data\QuoteDetailsItemInterface
211+
* @return QuoteDetailsItemInterface
190212
*/
191213
public function mapItem(
192214
\Magento\Tax\Api\Data\QuoteDetailsItemInterfaceFactory $itemDataObjectFactory,
@@ -199,7 +221,7 @@ public function mapItem(
199221
$sequence = 'sequence-' . $this->getNextIncrement();
200222
$item->setTaxCalculationItemId($sequence);
201223
}
202-
/** @var \Magento\Tax\Api\Data\QuoteDetailsItemInterface $itemDataObject */
224+
/** @var QuoteDetailsItemInterface $itemDataObject */
203225
$itemDataObject = $itemDataObjectFactory->create();
204226
$itemDataObject->setCode($item->getTaxCalculationItemId())
205227
->setQuantity($item->getQty())
@@ -215,12 +237,28 @@ public function mapItem(
215237
if (!$item->getBaseTaxCalculationPrice()) {
216238
$item->setBaseTaxCalculationPrice($item->getBaseCalculationPriceOriginal());
217239
}
240+
241+
if ($this->taxHelper->applyTaxOnOriginalPrice()) {
242+
$baseTaxCalculationPrice = $item->getBaseOriginalPrice();
243+
} else {
244+
$baseTaxCalculationPrice = $item->getBaseCalculationPriceOriginal();
245+
}
246+
$this->setPriceForTaxCalculation($itemDataObject, (float)$baseTaxCalculationPrice);
247+
218248
$itemDataObject->setUnitPrice($item->getBaseTaxCalculationPrice())
219249
->setDiscountAmount($item->getBaseDiscountAmount());
220250
} else {
221251
if (!$item->getTaxCalculationPrice()) {
222252
$item->setTaxCalculationPrice($item->getCalculationPriceOriginal());
223253
}
254+
255+
if ($this->taxHelper->applyTaxOnOriginalPrice()) {
256+
$taxCalculationPrice = $item->getOriginalPrice();
257+
} else {
258+
$taxCalculationPrice = $item->getCalculationPriceOriginal();
259+
}
260+
$this->setPriceForTaxCalculation($itemDataObject, (float)$taxCalculationPrice);
261+
224262
$itemDataObject->setUnitPrice($item->getTaxCalculationPrice())
225263
->setDiscountAmount($item->getDiscountAmount());
226264
}
@@ -230,14 +268,31 @@ public function mapItem(
230268
return $itemDataObject;
231269
}
232270

271+
/**
272+
* Set price for tax calculation.
273+
*
274+
* @param QuoteDetailsItemInterface $quoteDetailsItem
275+
* @param float $taxCalculationPrice
276+
* @return void
277+
*/
278+
private function setPriceForTaxCalculation(QuoteDetailsItemInterface $quoteDetailsItem, float $taxCalculationPrice)
279+
{
280+
$extensionAttributes = $quoteDetailsItem->getExtensionAttributes();
281+
if (!$extensionAttributes) {
282+
$extensionAttributes = $this->quoteDetailsItemExtensionFactory->create();
283+
}
284+
$extensionAttributes->setPriceForTaxCalculation($taxCalculationPrice);
285+
$quoteDetailsItem->setExtensionAttributes($extensionAttributes);
286+
}
287+
233288
/**
234289
* Map item extra taxables
235290
*
236291
* @param \Magento\Tax\Api\Data\QuoteDetailsItemInterfaceFactory $itemDataObjectFactory
237292
* @param AbstractItem $item
238293
* @param bool $priceIncludesTax
239294
* @param bool $useBaseCurrency
240-
* @return \Magento\Tax\Api\Data\QuoteDetailsItemInterface[]
295+
* @return QuoteDetailsItemInterface[]
241296
*/
242297
public function mapItemExtraTaxables(
243298
\Magento\Tax\Api\Data\QuoteDetailsItemInterfaceFactory $itemDataObjectFactory,
@@ -260,7 +315,7 @@ public function mapItemExtraTaxables(
260315
} else {
261316
$unitPrice = $extraTaxable[self::KEY_ASSOCIATED_TAXABLE_UNIT_PRICE];
262317
}
263-
/** @var \Magento\Tax\Api\Data\QuoteDetailsItemInterface $itemDataObject */
318+
/** @var QuoteDetailsItemInterface $itemDataObject */
264319
$itemDataObject = $itemDataObjectFactory->create();
265320
$itemDataObject->setCode($extraTaxable[self::KEY_ASSOCIATED_TAXABLE_CODE])
266321
->setType($extraTaxable[self::KEY_ASSOCIATED_TAXABLE_TYPE])
@@ -283,9 +338,9 @@ public function mapItemExtraTaxables(
283338
* Add quote items
284339
*
285340
* @param ShippingAssignmentInterface $shippingAssignment
286-
* @param bool $useBaseCurrency
287341
* @param bool $priceIncludesTax
288-
* @return \Magento\Tax\Api\Data\QuoteDetailsItemInterface[]
342+
* @param bool $useBaseCurrency
343+
* @return QuoteDetailsItemInterface[]
289344
*/
290345
public function mapItems(
291346
ShippingAssignmentInterface $shippingAssignment,
@@ -361,10 +416,12 @@ public function populateAddressData(QuoteDetailsInterface $quoteDetails, QuoteAd
361416
}
362417

363418
/**
419+
* Get shipping data object.
420+
*
364421
* @param ShippingAssignmentInterface $shippingAssignment
365422
* @param QuoteAddress\Total $total
366423
* @param bool $useBaseCurrency
367-
* @return \Magento\Tax\Api\Data\QuoteDetailsItemInterface
424+
* @return QuoteDetailsItemInterface
368425
*/
369426
public function getShippingDataObject(
370427
ShippingAssignmentInterface $shippingAssignment,
@@ -379,7 +436,7 @@ public function getShippingDataObject(
379436
$total->setBaseShippingTaxCalculationAmount($total->getBaseShippingAmount());
380437
}
381438
if ($total->getShippingTaxCalculationAmount() !== null) {
382-
/** @var \Magento\Tax\Api\Data\QuoteDetailsItemInterface $itemDataObject */
439+
/** @var QuoteDetailsItemInterface $itemDataObject */
383440
$itemDataObject = $this->quoteDetailsItemDataObjectFactory->create()
384441
->setType(self::ITEM_TYPE_SHIPPING)
385442
->setCode(self::ITEM_CODE_SHIPPING)
@@ -414,7 +471,7 @@ public function getShippingDataObject(
414471
* Populate QuoteDetails object from quote address object
415472
*
416473
* @param ShippingAssignmentInterface $shippingAssignment
417-
* @param \Magento\Tax\Api\Data\QuoteDetailsItemInterface[] $itemDataObjects
474+
* @param QuoteDetailsItemInterface[] $itemDataObjects
418475
* @return \Magento\Tax\Api\Data\QuoteDetailsInterface
419476
*/
420477
protected function prepareQuoteDetails(ShippingAssignmentInterface $shippingAssignment, $itemDataObjects)
@@ -543,6 +600,7 @@ protected function processProductItems(
543600
* Process applied taxes for items and quote
544601
*
545602
* @param QuoteAddress\Total $total
603+
* @param ShippingAssignmentInterface $shippingAssignment
546604
* @param array $itemsByType
547605
* @return $this
548606
*/
@@ -846,8 +904,9 @@ protected function saveAppliedTaxes()
846904
}
847905

848906
/**
849-
* Increment and return counter. This function is intended to be used to generate temporary
850-
* id for an item.
907+
* Increment and return counter.
908+
*
909+
* This function is intended to be used to generate temporary id for an item.
851910
*
852911
* @return int
853912
*/

app/code/Magento/Tax/Test/Mftf/Data/TaxRateData.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,8 @@
106106
<data key="zip_is_range">0</data>
107107
<data key="rate">0.1</data>
108108
</entity>
109+
<entity name="taxRateForPensylvannia" extends="defaultTaxRate">
110+
<data key="tax_region_id">51</data>
111+
<data key="rate">6</data>
112+
</entity>
109113
</entities>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd">
11+
<page name="AdminEditTaxRatePage" url="tax/rate/edit/rate/{{var1}}/" module="Magento_Tax" area="admin" parameterized="true">
12+
<section name="AdminTaxRateFormSection"/>
13+
</page>
14+
</pages>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd">
11+
<page name="AdminEditTaxRulePage" url="tax/rule/edit/rule/{{var}}/" module="Magento_Tax" area="admin" parameterized="true">
12+
<section name="AdminTaxRulesSection"/>
13+
</page>
14+
</pages>

app/code/Magento/Tax/Test/Mftf/Section/AdminConfigureTaxSection.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
<element name="taxCalculationPrices" type="select" selector="#tax_calculation_price_includes_tax"/>
2929
<element name="taxCalculationPricesDisabled" type="select" selector="#tax_calculation_price_includes_tax[disabled='disabled']"/>
3030
<element name="taxCalculationPricesInherit" type="checkbox" selector="#tax_calculation_price_includes_tax_inherit"/>
31+
<element name="taxCalculationApplyTaxOn" type="select" selector="#tax_calculation_apply_tax_on"/>
32+
<element name="taxCalculationApplyTaxOnInherit" type="checkbox" selector="#tax_calculation_apply_tax_on_inherit"/>
3133

3234
<element name="defaultDestination" type="block" selector="#tax_defaults-head" timeout="30"/>
3335
<element name="systemValueDefaultState" type="checkbox" selector="#row_tax_defaults_region input[type='checkbox']"/>

app/code/Magento/Tax/Test/Mftf/Section/AdminTaxRulesSection.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,6 @@
3333
<element name="deleteTaxClass" type="button" selector="//span[contains(text(),'{{var1}}')]/../..//*[@class='mselect-delete']" parameterized="true"/>
3434
<element name="popUpDialogOK" type="button" selector="//*[@class='modal-footer']//*[contains(text(),'OK')]"/>
3535
<element name="taxRateMultiSelectItems" type="block" selector=".mselect-list-item"/>
36+
<element name="taxRateNumber" type="button" selector="//div[@data-ui-id='tax-rate-form-fieldset-element-form-field-tax-rate']//div[@class='mselect-items-wrapper']//label[{{var}}]" parameterized="true"/>
3637
</section>
3738
</sections>

0 commit comments

Comments
 (0)