Skip to content

Commit 233d683

Browse files
committed
ACP2E-3536: Cart Rule with shipping condition not applying when placing order from admin
- With test
1 parent 3f12d15 commit 233d683

File tree

5 files changed

+266
-8
lines changed

5 files changed

+266
-8
lines changed

app/code/Magento/Sales/Controller/Adminhtml/Order/Create.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
/**
3-
* Copyright © Magento, Inc. All rights reserved.
4-
* See COPYING.txt for license details.
3+
* Copyright 2011 Adobe
4+
* All Rights Reserved.
55
*/
66
declare(strict_types=1);
77

@@ -191,12 +191,13 @@ protected function _processActionData($action = null)
191191
*/
192192
$this->_getOrderCreateModel()->getBillingAddress();
193193

194+
$shippingMethod = $this->_getOrderCreateModel()->getShippingAddress()?->getShippingMethod();
195+
194196
/**
195197
* Flag for using billing address for shipping
196198
*/
197199
if (!$this->_getOrderCreateModel()->getQuote()->isVirtual()) {
198200
$syncFlag = $this->getRequest()->getPost('shipping_as_billing');
199-
$shippingMethod = $this->_getOrderCreateModel()->getShippingAddress()->getShippingMethod();
200201
if ($syncFlag === null
201202
&& $this->_getOrderCreateModel()->getShippingAddress()->getSameAsBilling() && empty($shippingMethod)
202203
) {
@@ -289,6 +290,7 @@ protected function _processActionData($action = null)
289290
$eventData = [
290291
'order_create_model' => $this->_getOrderCreateModel(),
291292
'request' => $this->getRequest()->getPostValue(),
293+
'shipping_method' => $shippingMethod
292294
];
293295

294296
$this->_eventManager->dispatch('adminhtml_sales_order_create_process_data', $eventData);

app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@
440440
*/
441441
setShippingAsBilling: function (flag) {
442442
var data,
443-
areasToLoad = ['billing_method', 'shipping_address', 'shipping_method', 'totals', 'giftmessage'];
443+
areasToLoad = ['items', 'billing_method', 'shipping_address', 'shipping_method', 'totals', 'giftmessage'];
444444

445445
this.disableShippingAddress(flag);
446446
data = this.serializeData(flag ? this.billingAddressContainer : this.shippingAddressContainer);
@@ -507,7 +507,7 @@
507507
loadPaymentMethods: function () {
508508
var data = this.serializeData(this.billingAddressContainer).toObject();
509509

510-
this.loadArea(['billing_method', 'totals'], true, data);
510+
this.loadArea(['items', 'billing_method', 'totals'], true, data);
511511

512512
return false;
513513
},
@@ -524,7 +524,7 @@
524524
this.setPaymentMethod(method);
525525
var data = {};
526526
data['order[payment_method]'] = method;
527-
this.loadArea(['card_validation'], true, data);
527+
this.loadArea(['items', 'card_validation'], true, data);
528528
},
529529

530530
setPaymentMethod: function (method) {
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
/**
3+
* Copyright 2024 Adobe
4+
* All Rights Reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\SalesRule\Observer;
9+
10+
use Magento\Framework\Event\Observer;
11+
use Magento\Framework\Event\ObserverInterface;
12+
use Magento\Multicoupon\Model\Config\Config;
13+
14+
/**
15+
* Class for process order for resetting shipping flag.
16+
*/
17+
class ProcessOrderCreationDataObserver implements ObserverInterface
18+
{
19+
/**
20+
* @param Config $multiCouponConfig
21+
*/
22+
public function __construct(private Config $multiCouponConfig)
23+
{
24+
}
25+
26+
/**
27+
* Checking shipping method and resetting it if needed.
28+
*
29+
* @param Observer $observer
30+
* @return $this
31+
*/
32+
public function execute(Observer $observer)
33+
{
34+
$order = $observer->getEvent()->getOrderCreateModel();
35+
$request = $observer->getEvent()->getRequest();
36+
if (array_key_exists('order', $request)) {
37+
$quote = $order->getQuote();
38+
$isVirtualQuote = $quote->isVirtual();
39+
$quoteShippingMethod = $observer->getEvent()->getShippingMethod();
40+
$checkIfCouponExists = array_key_exists('coupon', $request['order']);
41+
$noOfCouponsAvailable = $this->multiCouponConfig->getMaximumNumberOfCoupons();
42+
if (!$isVirtualQuote && !empty($quoteShippingMethod) && $checkIfCouponExists && $noOfCouponsAvailable <= 1) {
43+
$shippingAddress = $quote->getShippingAddress();
44+
$shippingAddress->setShippingMethod($quoteShippingMethod);
45+
}
46+
}
47+
return $this;
48+
}
49+
}
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
<?php
2+
/**
3+
* Copyright 2024 Adobe
4+
* All Rights Reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\SalesRule\Test\Unit\Observer;
9+
10+
use Magento\Framework\App\RequestInterface;
11+
use Magento\Framework\Event;
12+
use Magento\Framework\Event\Observer;
13+
use Magento\Multicoupon\Model\Config\Config;
14+
use Magento\Quote\Model\Quote;
15+
use Magento\Quote\Model\Quote\Address;
16+
use Magento\Sales\Model\AdminOrder\Create;
17+
use Magento\SalesRule\Observer\ProcessOrderCreationDataObserver;
18+
use PHPUnit\Framework\MockObject\MockObject;
19+
use PHPUnit\Framework\TestCase;
20+
21+
/**
22+
* Test case for process order for resetting shipping flag.
23+
*/
24+
class ProcessOrderCreationDataObserverTest extends TestCase
25+
{
26+
/**
27+
* @var MockObject|Observer
28+
*/
29+
private $observerMock;
30+
31+
/**
32+
* @var MockObject|Config
33+
*/
34+
private $multiCouponConfigMock;
35+
36+
/**
37+
* @var Event|MockObject
38+
*/
39+
private $eventMock;
40+
41+
/**
42+
* @var MockObject
43+
*/
44+
private $requestMock;
45+
46+
/**
47+
* @var MockObject
48+
*/
49+
private $quoteMock;
50+
51+
/**
52+
* @var Address|MockObject
53+
*/
54+
private $shippingAddressMock;
55+
56+
/**
57+
* @var Create|MockObject
58+
*/
59+
private $orderCreateModelMock;
60+
61+
/**
62+
* @var ProcessOrderCreationDataObserver|MockObject
63+
*/
64+
private $model;
65+
66+
/**
67+
* @inheritdoc
68+
*/
69+
protected function setUp(): void
70+
{
71+
$this->observerMock = $this->createMock(Observer::class);
72+
$this->quoteMock = $this->getMockBuilder(Quote::class)
73+
->onlyMethods(['isVirtual', 'getShippingAddress'])
74+
->disableOriginalConstructor()
75+
->getMock();
76+
$this->multiCouponConfigMock = $this->getMockBuilder(Config::class)
77+
->onlyMethods(['getMaximumNumberOfCoupons'])
78+
->disableOriginalConstructor()
79+
->getMock();
80+
$this->eventMock = $this->getMockBuilder(Event::class)
81+
->disableOriginalConstructor()
82+
->addMethods(['getRequest', 'getOrderCreateModel', 'getShippingMethod'])
83+
->getMock();
84+
$this->shippingAddressMock = $this->getMockBuilder(Address::class)
85+
->addMethods(['setShippingMethod'])
86+
->disableOriginalConstructor()
87+
->getMock();
88+
$this->orderCreateModelMock = $this->getMockBuilder(Create::class)
89+
->onlyMethods(['getQuote'])
90+
->disableOriginalConstructor()
91+
->getMock();
92+
$this->requestMock = $this->getMockForAbstractClass(RequestInterface::class);
93+
$this->model = new ProcessOrderCreationDataObserver($this->multiCouponConfigMock);
94+
}
95+
96+
/**
97+
* Test case for processOrderCreationDataObserver::execute
98+
*
99+
* @param bool $isVirtualQuote
100+
* @param int $maximumNumberOfCoupons
101+
* @param array $requestArr
102+
* @param string|null $quoteShippingMethod
103+
* @return void
104+
* @dataProvider executeDataProvider
105+
*/
106+
public function testExecute(
107+
bool $isVirtualQuote,
108+
int $maximumNumberOfCoupons,
109+
array $requestArr,
110+
?string $quoteShippingMethod = null,
111+
): void {
112+
$this->observerMock
113+
->expects($this->any())
114+
->method('getEvent')
115+
->willReturn($this->eventMock);
116+
$this->eventMock
117+
->expects($this->any())
118+
->method('getRequest')
119+
->willReturn($requestArr);
120+
$this->eventMock
121+
->expects($this->any())
122+
->method('getOrderCreateModel')
123+
->willReturn($this->orderCreateModelMock);
124+
$this->eventMock
125+
->expects($this->any())
126+
->method('getShippingMethod')
127+
->willReturn($quoteShippingMethod);
128+
$this->orderCreateModelMock
129+
->expects($this->any())
130+
->method('getQuote')
131+
->willReturn($this->quoteMock);
132+
$this->quoteMock
133+
->expects($this->any())
134+
->method('isVirtual')
135+
->willReturn($isVirtualQuote);
136+
$this->quoteMock
137+
->expects($this->any())
138+
->method('getShippingAddress')
139+
->willReturn($this->shippingAddressMock);
140+
$this->multiCouponConfigMock
141+
->expects($this->any())
142+
->method('getMaximumNumberOfCoupons')
143+
->willReturn($maximumNumberOfCoupons);
144+
$this->shippingAddressMock
145+
->expects($this->any())
146+
->method('setShippingMethod')
147+
->with($quoteShippingMethod)
148+
->willReturn(true);
149+
$this->model->execute($this->observerMock);
150+
}
151+
152+
/**
153+
* Data provider for testExecute
154+
*
155+
* @return array[]
156+
*/
157+
public static function executeDataProvider(): array
158+
{
159+
return [
160+
[
161+
'isVirtualQuote' => false,
162+
'maximumNumberOfCoupons' => 1,
163+
'requestArr' =>
164+
[
165+
'order' => ['coupon' => 'coupon_code'],
166+
'reset_shipping' => true,
167+
'collect_shipping_rates' => true
168+
],
169+
'quoteShippingMethod' => 'flatrate_flatrate',
170+
],
171+
[
172+
'isVirtualQuote' => true,
173+
'maximumNumberOfCoupons' => 1,
174+
'requestArr' =>
175+
[
176+
'order' => ['coupon' => 'coupon_code'],
177+
'reset_shipping' => false
178+
],
179+
'quoteShippingMethod' => 'freeshipping_freeshipping',
180+
],
181+
[
182+
'isVirtualQuote' => false,
183+
'maximumNumberOfCoupons' => 1,
184+
'requestArr' =>
185+
[
186+
'order' => ['coupon' => ''],
187+
'collect_shipping_rates' => true
188+
],
189+
'quoteShippingMethod' => null,
190+
],
191+
[
192+
'isVirtualQuote' => false,
193+
'maximumNumberOfCoupons' => 10,
194+
'requestArr' =>
195+
[
196+
'order' => ['coupon' => 'coupon_code'],
197+
'reset_shipping' => false,
198+
'collect_shipping_rates' => true
199+
],
200+
'quoteShippingMethod' => 'flatrate_flatrate'
201+
]
202+
];
203+
}
204+
}
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<?xml version="1.0"?>
22
<!--
33
/**
4-
* Copyright © Magento, Inc. All rights reserved.
5-
* See COPYING.txt for license details.
4+
* Copyright 2011 Adobe
5+
* All rights reserved.
66
*/
77
-->
88
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
@@ -12,4 +12,7 @@
1212
<event name="catalog_entity_attribute_save_after">
1313
<observer name="salesrule" instance="Magento\SalesRule\Observer\CatalogAttributeSaveAfterObserver" />
1414
</event>
15+
<event name="adminhtml_sales_order_create_process_data">
16+
<observer name="magento_salesrule" instance="Magento\SalesRule\Observer\ProcessOrderCreationDataObserver"/>
17+
</event>
1518
</config>

0 commit comments

Comments
 (0)