Skip to content

Commit a90721c

Browse files
committed
Merge remote-tracking branch 'origin/MC-37761' into 2.4-develop-pr42
2 parents 8baa37a + 40542aa commit a90721c

File tree

2 files changed

+286
-27
lines changed

2 files changed

+286
-27
lines changed

app/code/Magento/Tax/Model/Plugin/OrderSave.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,14 @@ public function afterSave(
5050
}
5151

5252
/**
53+
* Save order tax
54+
*
5355
* @param \Magento\Sales\Api\Data\OrderInterface $order
5456
* @return $this
5557
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
5658
* @SuppressWarnings(PHPMD.NPathComplexity)
5759
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
60+
* phpcs:disable Generic.Metrics.NestingLevel.TooHigh
5861
*/
5962
protected function saveOrderTax(\Magento\Sales\Api\Data\OrderInterface $order)
6063
{
@@ -176,7 +179,9 @@ protected function saveOrderTax(\Magento\Sales\Api\Data\OrderInterface $order)
176179
} elseif (isset($quoteItemId['associated_item_id'])) {
177180
//This item is associated with a product item
178181
$item = $order->getItemByQuoteItemId($quoteItemId['associated_item_id']);
179-
$associatedItemId = $item->getId();
182+
if ($item !== null && $item->getId()) {
183+
$associatedItemId = $item->getId();
184+
}
180185
}
181186

182187
$data = [

app/code/Magento/Tax/Test/Unit/Model/Plugin/OrderSaveTest.php

Lines changed: 280 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -175,50 +175,51 @@ public function verifyItemTaxes($expectedItemTaxes)
175175
}
176176

177177
/**
178+
* Test for order afterSave
179+
*
178180
* @dataProvider afterSaveDataProvider
181+
* @param array $appliedTaxes
182+
* @param array $itemAppliedTaxes
183+
* @param array $expectedTaxes
184+
* @param array $expectedItemTaxes
185+
* @param int|null $itemId
186+
* @return void
179187
*/
180188
public function testAfterSave(
181-
$appliedTaxes,
182-
$itemAppliedTaxes,
183-
$expectedTaxes,
184-
$expectedItemTaxes
185-
) {
189+
array $appliedTaxes,
190+
array $itemAppliedTaxes,
191+
array $expectedTaxes,
192+
array $expectedItemTaxes,
193+
?int $itemId
194+
): void {
186195
$orderMock = $this->setupOrderMock();
187196

188197
$extensionAttributeMock = $this->setupExtensionAttributeMock();
189-
$extensionAttributeMock->expects($this->any())
190-
->method('getConvertingFromQuote')
198+
$extensionAttributeMock->method('getConvertingFromQuote')
191199
->willReturn(true);
192-
$extensionAttributeMock->expects($this->any())
193-
->method('getAppliedTaxes')
200+
$extensionAttributeMock->method('getAppliedTaxes')
194201
->willReturn($appliedTaxes);
195-
$extensionAttributeMock->expects($this->any())
196-
->method('getItemAppliedTaxes')
202+
$extensionAttributeMock->method('getItemAppliedTaxes')
197203
->willReturn($itemAppliedTaxes);
198204

199205
$orderItemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class)
200206
->disableOriginalConstructor()
201207
->setMethods(['getId'])
202208
->getMock();
203-
$orderItemMock->expects($this->atLeastOnce())
204-
->method('getId')
205-
->willReturn(self::ORDER_ITEM_ID);
206-
$orderMock->expects($this->once())
207-
->method('getAppliedTaxIsSaved')
209+
$orderItemMock->method('getId')
210+
->willReturn($itemId);
211+
$orderMock->method('getAppliedTaxIsSaved')
208212
->willReturn(false);
209-
$orderMock->expects($this->once())
210-
->method('getExtensionAttributes')
213+
$orderMock->method('getExtensionAttributes')
211214
->willReturn($extensionAttributeMock);
212-
$orderMock->expects($this->atLeastOnce())
213-
->method('getItemByQuoteItemId')
215+
$itemByQuoteId = $itemId ? $orderItemMock : $itemId;
216+
$orderMock->method('getItemByQuoteItemId')
214217
->with(self::ITEMID)
215-
->willReturn($orderItemMock);
216-
$orderMock->expects($this->atLeastOnce())
217-
->method('getEntityId')
218+
->willReturn($itemByQuoteId);
219+
$orderMock->method('getEntityId')
218220
->willReturn(self::ORDERID);
219221

220-
$orderMock->expects($this->once())
221-
->method('setAppliedTaxIsSaved')
222+
$orderMock->method('setAppliedTaxIsSaved')
222223
->with(true);
223224

224225
$this->verifyOrderTaxes($expectedTaxes);
@@ -228,10 +229,12 @@ public function testAfterSave(
228229
}
229230

230231
/**
232+
* After save data provider
233+
*
231234
* @return array
232235
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
233236
*/
234-
public function afterSaveDataProvider()
237+
public function afterSaveDataProvider(): array
235238
{
236239
return [
237240
//one item with shipping
@@ -485,6 +488,257 @@ public function afterSaveDataProvider()
485488
'taxable_item_type' => 'shipping',
486489
],
487490
],
491+
'item_id' => self::ORDER_ITEM_ID,
492+
],
493+
'associated_item_with_empty_order_quote_item' => [
494+
'applied_taxes' => [
495+
[
496+
'amount' => 0.66,
497+
'base_amount' => 0.66,
498+
'percent' => 11,
499+
'id' => 'ILUS',
500+
'extension_attributes' => [
501+
'rates' => [
502+
[
503+
'percent' => 6,
504+
'code' => 'IL',
505+
'title' => 'IL',
506+
],
507+
[
508+
'percent' => 5,
509+
'code' => 'US',
510+
'title' => 'US',
511+
],
512+
]
513+
],
514+
],
515+
[
516+
'amount' => 0.2,
517+
'base_amount' => 0.2,
518+
'percent' => 3.33,
519+
'id' => 'CityTax',
520+
'extension_attributes' => [
521+
'rates' => [
522+
[
523+
'percent' => 3,
524+
'code' => 'CityTax',
525+
'title' => 'CityTax',
526+
],
527+
]
528+
],
529+
],
530+
],
531+
'item_applied_taxes' => [
532+
//item tax, three tax rates
533+
[
534+
//first two taxes are combined
535+
'item_id' => null,
536+
'type' => 'product',
537+
'associated_item_id' => self::ITEMID,
538+
'applied_taxes' => [
539+
[
540+
'amount' => 0.11,
541+
'base_amount' => 0.11,
542+
'percent' => 11,
543+
'id' => 'ILUS',
544+
'extension_attributes' => [
545+
'rates' => [
546+
[
547+
'percent' => 6,
548+
'code' => 'IL',
549+
'title' => 'IL',
550+
],
551+
[
552+
'percent' => 5,
553+
'code' => 'US',
554+
'title' => 'US',
555+
],
556+
]
557+
],
558+
],
559+
//city tax
560+
[
561+
'amount' => 0.03,
562+
'base_amount' => 0.03,
563+
'percent' => 3.33,
564+
'id' => 'CityTax',
565+
'extension_attributes' => [
566+
'rates' => [
567+
[
568+
'percent' => 3,
569+
'code' => 'CityTax',
570+
'title' => 'CityTax',
571+
],
572+
]
573+
],
574+
],
575+
],
576+
],
577+
//shipping tax
578+
[
579+
//first two taxes are combined
580+
'item_id' => null,
581+
'type' => 'shipping',
582+
'associated_item_id' => null,
583+
'applied_taxes' => [
584+
[
585+
'amount' => 0.55,
586+
'base_amount' => 0.55,
587+
'percent' => 11,
588+
'id' => 'ILUS',
589+
'extension_attributes' => [
590+
'rates' => [
591+
[
592+
'percent' => 6,
593+
'code' => 'IL',
594+
'title' => 'IL',
595+
],
596+
[
597+
'percent' => 5,
598+
'code' => 'US',
599+
'title' => 'US',
600+
],
601+
]
602+
],
603+
],
604+
//city tax
605+
[
606+
'amount' => 0.17,
607+
'base_amount' => 0.17,
608+
'percent' => 3.33,
609+
'id' => 'CityTax',
610+
'extension_attributes' => [
611+
'rates' => [
612+
[
613+
'percent' => 3,
614+
'code' => 'CityTax',
615+
'title' => 'CityTax',
616+
],
617+
]
618+
],
619+
],
620+
],
621+
],
622+
],
623+
'expected_order_taxes' => [
624+
//state tax
625+
'35' => [
626+
'order_id' => self::ORDERID,
627+
'code' => 'IL',
628+
'title' => 'IL',
629+
'hidden' => 0,
630+
'percent' => 6,
631+
'priority' => 0,
632+
'position' => 0,
633+
'amount' => 0.66,
634+
'base_amount' => 0.66,
635+
'process' => 0,
636+
'base_real_amount' => 0.36,
637+
],
638+
//federal tax
639+
'36' => [
640+
'order_id' => self::ORDERID,
641+
'code' => 'US',
642+
'title' => 'US',
643+
'hidden' => 0,
644+
'percent' => 5,
645+
'priority' => 0,
646+
'position' => 0,
647+
'amount' => 0.66, //combined amount
648+
'base_amount' => 0.66,
649+
'process' => 0,
650+
'base_real_amount' => 0.3, //portion for specific rate
651+
],
652+
//city tax
653+
'37' => [
654+
'order_id' => self::ORDERID,
655+
'code' => 'CityTax',
656+
'title' => 'CityTax',
657+
'hidden' => 0,
658+
'percent' => 3,
659+
'priority' => 0,
660+
'position' => 0,
661+
'amount' => 0.2, //combined amount
662+
'base_amount' => 0.2,
663+
'process' => 0,
664+
'base_real_amount' => 0.18018018018018, //this number is meaningless since this is single rate
665+
],
666+
],
667+
'expected_item_taxes' => [
668+
[
669+
//state tax for item
670+
'item_id' => null,
671+
'tax_id' => '35',
672+
'tax_percent' => 6,
673+
'associated_item_id' => null,
674+
'amount' => 0.11,
675+
'base_amount' => 0.11,
676+
'real_amount' => 0.06,
677+
'real_base_amount' => 0.06,
678+
'taxable_item_type' => 'product',
679+
],
680+
[
681+
//state tax for shipping
682+
'item_id' => null,
683+
'tax_id' => '35',
684+
'tax_percent' => 6,
685+
'associated_item_id' => null,
686+
'amount' => 0.55,
687+
'base_amount' => 0.55,
688+
'real_amount' => 0.3,
689+
'real_base_amount' => 0.3,
690+
'taxable_item_type' => 'shipping',
691+
],
692+
[
693+
//federal tax for item
694+
'item_id' => null,
695+
'tax_id' => '36',
696+
'tax_percent' => 5,
697+
'associated_item_id' => null,
698+
'amount' => 0.11,
699+
'base_amount' => 0.11,
700+
'real_amount' => 0.05,
701+
'real_base_amount' => 0.05,
702+
'taxable_item_type' => 'product',
703+
],
704+
[
705+
//federal tax for shipping
706+
'item_id' => null,
707+
'tax_id' => '36',
708+
'tax_percent' => 5,
709+
'associated_item_id' => null,
710+
'amount' => 0.55,
711+
'base_amount' => 0.55,
712+
'real_amount' => 0.25,
713+
'real_base_amount' => 0.25,
714+
'taxable_item_type' => 'shipping',
715+
],
716+
[
717+
//city tax for item
718+
'item_id' => null,
719+
'tax_id' => '37',
720+
'tax_percent' => 3.33,
721+
'associated_item_id' => null,
722+
'amount' => 0.03,
723+
'base_amount' => 0.03,
724+
'real_amount' => 0.03,
725+
'real_base_amount' => 0.03,
726+
'taxable_item_type' => 'product',
727+
],
728+
[
729+
//city tax for shipping
730+
'item_id' => null,
731+
'tax_id' => '37',
732+
'tax_percent' => 3.33,
733+
'associated_item_id' => null,
734+
'amount' => 0.17,
735+
'base_amount' => 0.17,
736+
'real_amount' => 0.17,
737+
'real_base_amount' => 0.17,
738+
'taxable_item_type' => 'shipping',
739+
],
740+
],
741+
'item_id' => null,
488742
],
489743
];
490744
}

0 commit comments

Comments
 (0)