Skip to content

Commit d2ac3de

Browse files
committed
ACP2E-2646: [Cloud] Sales Rule not applied to first order of Multi Shipping
1 parent c12e0d9 commit d2ac3de

File tree

3 files changed

+159
-4
lines changed

3 files changed

+159
-4
lines changed

app/code/Magento/SalesRule/Test/Unit/Model/Quote/DiscountTest.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,9 @@ function ($argument) {
130130

131131
$this->addressMock = $this->getMockBuilder(Address::class)
132132
->addMethods(['getShippingAmount'])
133-
->onlyMethods(['getQuote', 'getAllItems', 'getExtensionAttributes', 'getCustomAttributesCodes'])
133+
->onlyMethods(
134+
['getQuote', 'getAllItems', 'getExtensionAttributes', 'getCustomAttributesCodes', 'setBaseDiscountAmount']
135+
)
134136
->disableOriginalConstructor()
135137
->getMock();
136138
$addressExtension = $this->getMockBuilder(
@@ -178,7 +180,7 @@ public function testCollectItemNoDiscount()
178180
{
179181
$itemNoDiscount = $this->getMockBuilder(Item::class)
180182
->addMethods(['getNoDiscount'])
181-
->onlyMethods(['getExtensionAttributes', 'getParentItem', 'getId'])
183+
->onlyMethods(['getExtensionAttributes', 'getParentItem', 'getId', 'getAddress'])
182184
->disableOriginalConstructor()
183185
->getMock();
184186
$itemExtension = $this->getMockBuilder(
@@ -191,6 +193,7 @@ public function testCollectItemNoDiscount()
191193
$itemNoDiscount->expects($this->any())->method('getExtensionAttributes')->willReturn($itemExtension);
192194
$itemNoDiscount->expects($this->any())->method('getId')->willReturn(1);
193195
$itemNoDiscount->expects($this->once())->method('getNoDiscount')->willReturn(true);
196+
$itemNoDiscount->expects($this->once())->method('getAddress')->willReturn($this->addressMock);
194197
$this->validatorMock->expects($this->once())->method('sortItemsByPriority')
195198
->with([$itemNoDiscount], $this->addressMock)
196199
->willReturnArgument(0);
@@ -213,6 +216,7 @@ public function testCollectItemNoDiscount()
213216
$this->addressMock->expects($this->any())->method('getQuote')->willReturn($quoteMock);
214217
$this->shippingAssignmentMock->expects($this->any())->method('getItems')->willReturn([$itemNoDiscount]);
215218
$this->addressMock->expects($this->any())->method('getShippingAmount')->willReturn(true);
219+
$this->addressMock->expects($this->atLeastOnce())->method('setBaseDiscountAmount')->with(0)->willReturnSelf();
216220

217221
$totalMock = $this->getMockBuilder(Total::class)
218222
->addMethods(
@@ -234,13 +238,14 @@ public function testCollectItemHasParent()
234238
{
235239
$itemWithParentId = $this->getMockBuilder(Item::class)
236240
->addMethods(['getNoDiscount'])
237-
->onlyMethods(['getParentItem', 'getId', 'getExtensionAttributes'])
241+
->onlyMethods(['getParentItem', 'getId', 'getExtensionAttributes', 'getAddress'])
238242
->disableOriginalConstructor()
239243
->getMock();
240244
$itemWithParentId->expects($this->once())->method('getNoDiscount')->willReturn(false);
241245
$itemWithParentId->expects($this->any())->method('getId')->willReturn(1);
242246
$itemWithParentId->expects($this->any())->method('getParentItem')->willReturn(true);
243247
$itemWithParentId->expects($this->any())->method('getExtensionAttributes')->willReturn(false);
248+
$itemWithParentId->expects($this->once())->method('getAddress')->willReturn($this->addressMock);
244249

245250
$this->validatorMock->expects($this->any())->method('canApplyDiscount')->willReturn(true);
246251
$this->validatorMock->expects($this->any())->method('sortItemsByPriority')
@@ -267,6 +272,7 @@ public function testCollectItemHasParent()
267272

268273
$this->addressMock->expects($this->any())->method('getQuote')->willReturn($quoteMock);
269274
$this->addressMock->expects($this->any())->method('getShippingAmount')->willReturn(true);
275+
$this->addressMock->expects($this->atLeastOnce())->method('setBaseDiscountAmount')->with(0)->willReturnSelf();
270276
$this->shippingAssignmentMock->expects($this->any())->method('getItems')->willReturn([$itemWithParentId]);
271277
$totalMock = $this->getMockBuilder(Total::class)
272278
->addMethods(
@@ -295,6 +301,7 @@ public function testCollectItemHasNoChildren()
295301
'getChildren',
296302
'getExtensionAttributes',
297303
'getId',
304+
'getAddress',
298305
]
299306
)->addMethods(
300307
[
@@ -318,6 +325,7 @@ public function testCollectItemHasNoChildren()
318325
$itemWithChildren->expects($this->any())->method('getParentItem')->willReturn(false);
319326
$itemWithChildren->expects($this->once())->method('getHasChildren')->willReturn(false);
320327
$itemWithChildren->expects($this->any())->method('getId')->willReturn(2);
328+
$itemWithChildren->expects($this->once())->method('getAddress')->willReturn($this->addressMock);
321329

322330
$this->validatorMock->expects($this->any())->method('canApplyDiscount')->willReturn(true);
323331
$this->validatorMock->expects($this->once())->method('sortItemsByPriority')
@@ -343,6 +351,7 @@ public function testCollectItemHasNoChildren()
343351
$this->addressMock->expects($this->any())->method('getAllItems')->willReturn([$itemWithChildren]);
344352
$this->addressMock->expects($this->any())->method('getQuote')->willReturn($quoteMock);
345353
$this->addressMock->expects($this->any())->method('getShippingAmount')->willReturn(true);
354+
$this->addressMock->expects($this->atLeastOnce())->method('setBaseDiscountAmount')->with(0)->willReturnSelf();
346355
$this->shippingAssignmentMock->expects($this->any())->method('getItems')->willReturn([$itemWithChildren]);
347356

348357
$totalMock = $this->getMockBuilder(Total::class)
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
<?php
2+
/************************************************************************
3+
*
4+
* Copyright 2024 Adobe
5+
* All Rights Reserved.
6+
*
7+
* NOTICE: All information contained herein is, and remains
8+
* the property of Adobe and its suppliers, if any. The intellectual
9+
* and technical concepts contained herein are proprietary to Adobe
10+
* and its suppliers and are protected by all applicable intellectual
11+
* property laws, including trade secret and copyright laws.
12+
* Dissemination of this information or reproduction of this material
13+
* is strictly forbidden unless prior written permission is obtained
14+
* from Adobe.
15+
* **********************************************************************
16+
*/
17+
declare(strict_types=1);
18+
19+
namespace Magento\SalesRule\Model\Rule\Action\Discount;
20+
21+
use Magento\Checkout\Model\Session as CheckoutSession;
22+
use Magento\Framework\Api\SearchCriteriaBuilder;
23+
use Magento\Multishipping\Model\Checkout\Type\Multishipping;
24+
use Magento\Quote\Api\CartRepositoryInterface;
25+
use Magento\Quote\Model\Quote;
26+
use Magento\Sales\Api\OrderRepositoryInterface;
27+
use Magento\Sales\Model\Order;
28+
use Magento\SalesRule\Model\Rule;
29+
use Magento\SalesRule\Test\Fixture\Rule as RuleFixture;
30+
use Magento\TestFramework\Fixture\AppArea;
31+
use Magento\TestFramework\Fixture\DataFixture;
32+
use Magento\TestFramework\Helper\Bootstrap;
33+
use PHPUnit\Framework\TestCase;
34+
35+
#[
36+
AppArea('frontend'),
37+
]
38+
class ByPercentTest extends TestCase
39+
{
40+
/**
41+
* @var SearchCriteriaBuilder
42+
*/
43+
private $searchCriteriaBuilder;
44+
45+
/**
46+
* @var CartRepositoryInterface
47+
*/
48+
private $quoteRepository;
49+
50+
/**
51+
* @var OrderRepositoryInterface
52+
*/
53+
private $orderRepository;
54+
55+
protected function setUp(): void
56+
{
57+
$this->searchCriteriaBuilder = Bootstrap::getObjectManager()->get(SearchCriteriaBuilder::class);
58+
$this->quoteRepository = Bootstrap::getObjectManager()->get(CartRepositoryInterface::class);
59+
$this->orderRepository = Bootstrap::getObjectManager()->get(OrderRepositoryInterface::class);
60+
}
61+
62+
#[
63+
DataFixture(
64+
RuleFixture::class,
65+
['simple_action' => Rule::BY_PERCENT_ACTION, 'discount_amount' => 10, 'coupon_code' => 'COUPON10']
66+
),
67+
DataFixture('Magento/Multishipping/Fixtures/quote_with_split_items.php'),
68+
]
69+
public function testMultishipping(): void
70+
{
71+
$quote = $this->getQuote('multishipping_quote_id');
72+
$quote->setCouponCode('COUPON10');
73+
$quote->collectTotals();
74+
$this->quoteRepository->save($quote);
75+
76+
$session = Bootstrap::getObjectManager()->get(CheckoutSession::class);
77+
$session->replaceQuote($quote);
78+
$multishipping = Bootstrap::getObjectManager()->get(Multishipping::class);
79+
$multishipping->createOrders();
80+
$orderList = array_values($this->getOrderList((int) $quote->getId()));
81+
self::assertCount(3, $orderList);
82+
83+
foreach ($orderList as $order) {
84+
self::assertNotEmpty($order->getAppliedRuleIds());
85+
$discountAmount = $order->getSubtotal() * 0.1;
86+
self::assertEquals($discountAmount * -1, $order->getDiscountAmount());
87+
$grandTotal = $order->getSubtotal() + $order->getShippingAmount() - $discountAmount;
88+
self::assertEquals($grandTotal, $order->getGrandTotal());
89+
$orderItem = array_values($order->getItems())[0];
90+
self::assertNotEmpty($orderItem->getAppliedRuleIds());
91+
self::assertEquals($discountAmount, $orderItem->getDiscountAmount());
92+
}
93+
}
94+
95+
/**
96+
* Load cart from fixture.
97+
*
98+
* @param string $reservedOrderId
99+
* @return Quote
100+
*/
101+
private function getQuote(string $reservedOrderId): Quote
102+
{
103+
$searchCriteria = $this->searchCriteriaBuilder->addFilter('reserved_order_id', $reservedOrderId)
104+
->create();
105+
$quoteList = $this->quoteRepository->getList($searchCriteria);
106+
107+
return array_values($quoteList->getItems())[0];
108+
}
109+
110+
/**
111+
* Get list of orders by quote id.
112+
*
113+
* @param int $quoteId
114+
* @return Order[]
115+
*/
116+
private function getOrderList(int $quoteId): array
117+
{
118+
$searchCriteria = $this->searchCriteriaBuilder->addFilter('quote_id', $quoteId)->create();
119+
$orderList = $this->orderRepository->getList($searchCriteria);
120+
121+
return $orderList->getItems();
122+
}
123+
}

dev/tests/integration/testsuite/Magento/SalesRule/Model/Rule/Action/Discount/CartFixedTest.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,12 +370,13 @@ public function testMultishipping(
370370
$model->createOrders();
371371
$orderList = $this->getOrderList((int)$quote->getId());
372372
$this->assertCount(3, $orderList);
373+
373374
/**
374375
* The order with $10 simple product
375376
* @var Order $firstOrder
376377
*/
377378
$firstOrder = array_shift($orderList);
378-
379+
$this->assertNotEmpty($firstOrder->getAppliedRuleIds());
379380
$this->assertEquals(
380381
$firstOrderTotals['subtotal'],
381382
$firstOrder->getSubtotal()
@@ -392,11 +393,19 @@ public function testMultishipping(
392393
$firstOrderTotals['grand_total'],
393394
$firstOrder->getGrandTotal()
394395
);
396+
$firstOrderItem = array_values($firstOrder->getItems())[0];
397+
$this->assertNotEmpty($firstOrderItem->getAppliedRuleIds());
398+
$this->assertEquals(
399+
$firstOrderTotals['discount_amount'] * -1,
400+
$firstOrderItem->getDiscountAmount()
401+
);
402+
395403
/**
396404
* The order with $20 simple product
397405
* @var Order $secondOrder
398406
*/
399407
$secondOrder = array_shift($orderList);
408+
$this->assertNotEmpty($secondOrder->getAppliedRuleIds());
400409
$this->assertEquals(
401410
$secondOrderTotals['subtotal'],
402411
$secondOrder->getSubtotal()
@@ -413,11 +422,19 @@ public function testMultishipping(
413422
$secondOrderTotals['grand_total'],
414423
$secondOrder->getGrandTotal()
415424
);
425+
$secondOrderItem = array_values($secondOrder->getItems())[0];
426+
$this->assertNotEmpty($secondOrderItem->getAppliedRuleIds());
427+
$this->assertEquals(
428+
$secondOrderTotals['discount_amount'] * -1,
429+
$secondOrderItem->getDiscountAmount()
430+
);
431+
416432
/**
417433
* The order with $5 virtual product and billing address as shipping
418434
* @var Order $thirdOrder
419435
*/
420436
$thirdOrder = array_shift($orderList);
437+
$this->assertNotEmpty($thirdOrder->getAppliedRuleIds());
421438
$this->assertEquals(
422439
$thirdOrderTotals['subtotal'],
423440
$thirdOrder->getSubtotal()
@@ -434,6 +451,12 @@ public function testMultishipping(
434451
$thirdOrderTotals['grand_total'],
435452
$thirdOrder->getGrandTotal()
436453
);
454+
$thirdOrderItem = array_values($thirdOrder->getItems())[0];
455+
$this->assertNotEmpty($thirdOrderItem->getAppliedRuleIds());
456+
$this->assertEquals(
457+
$thirdOrderTotals['discount_amount'] * -1,
458+
$thirdOrderItem->getDiscountAmount()
459+
);
437460
}
438461

439462
/**

0 commit comments

Comments
 (0)