Skip to content

Commit 10cfb26

Browse files
MC-19260: Coupon code removed during tax/shipping calculation on checkout
1 parent db85184 commit 10cfb26

File tree

4 files changed

+195
-2
lines changed

4 files changed

+195
-2
lines changed

app/code/Magento/SalesRule/Model/Validator.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,9 +243,9 @@ public function canApplyRules(AbstractItem $item)
243243
public function reset(Address $address)
244244
{
245245
$this->validatorUtility->resetRoundingDeltas();
246+
$address->setBaseSubtotalWithDiscount($address->getBaseSubtotal());
247+
$address->setSubtotalWithDiscount($address->getSubtotal());
246248
if ($this->_isFirstTimeResetRun) {
247-
$address->setBaseSubtotalWithDiscount($address->getBaseSubtotal());
248-
$address->setSubtotalWithDiscount($address->getSubtotal());
249249
$address->setAppliedRuleIds('');
250250
$address->getQuote()->setAppliedRuleIds('');
251251
$this->_isFirstTimeResetRun = false;

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

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,20 @@
1010
use Magento\Catalog\Api\Data\ProductInterface;
1111
use Magento\Catalog\Model\Product;
1212
use Magento\Catalog\Model\ProductRepository;
13+
use Magento\Framework\Api\SearchCriteriaBuilder;
1314
use Magento\Quote\Api\Data\CartItemInterface;
1415
use Magento\Quote\Api\GuestCartItemRepositoryInterface;
1516
use Magento\Quote\Api\GuestCartManagementInterface;
1617
use Magento\Quote\Api\GuestCartTotalRepositoryInterface;
1718
use Magento\Quote\Api\GuestCouponManagementInterface;
19+
use Magento\Sales\Api\Data\OrderInterface;
20+
use Magento\Sales\Api\OrderRepositoryInterface;
1821
use Magento\TestFramework\Helper\Bootstrap;
1922

2023
/**
2124
* Tests for Magento\SalesRule\Model\Rule\Action\Discount\CartFixed.
25+
*
26+
* @magentoAppArea frontend
2227
*/
2328
class CartFixedTest extends \PHPUnit\Framework\TestCase
2429
{
@@ -37,11 +42,17 @@ class CartFixedTest extends \PHPUnit\Framework\TestCase
3742
*/
3843
private $couponManagement;
3944

45+
/**
46+
* @var \Magento\Framework\ObjectManagerInterface
47+
*/
48+
private $objectManager;
49+
4050
/**
4151
* @inheritdoc
4252
*/
4353
protected function setUp()
4454
{
55+
$this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
4556
$this->cartManagement = Bootstrap::getObjectManager()->create(GuestCartManagementInterface::class);
4657
$this->couponManagement = Bootstrap::getObjectManager()->create(GuestCouponManagementInterface::class);
4758
$this->cartItemRepository = Bootstrap::getObjectManager()->create(GuestCartItemRepositoryInterface::class);
@@ -82,6 +93,30 @@ public function testApplyFixedDiscount(array $productPrices): void
8293
$this->assertEquals($expectedDiscount, $total->getBaseDiscountAmount());
8394
}
8495

96+
/**
97+
* Applies fixed discount amount on whole cart and created order with it
98+
*
99+
* @return void
100+
* @magentoDataFixture Magento/SalesRule/_files/coupon_cart_fixed_discount_subtotal_with_discount.php
101+
* @magentoDataFixture Magento/SalesRule/_files/quote_with_coupon.php
102+
*
103+
*/
104+
public function testOrderWithFixedDiscount(): void
105+
{
106+
/** @var $quote \Magento\Quote\Model\Quote */
107+
$quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class);
108+
/** @var \Magento\Quote\Model\QuoteIdMask $quoteIdMask */
109+
$quoteIdMask = $this->objectManager->create(\Magento\Quote\Model\QuoteIdMask::class);
110+
$quote->load('test01', 'reserved_order_id');
111+
$quoteIdMask->load($quote->getId(), 'quote_id');
112+
Bootstrap::getInstance()->reinitialize();
113+
114+
$cartManagement = Bootstrap::getObjectManager()->create(GuestCartManagementInterface::class);
115+
$cartManagement->placeOrder($quoteIdMask->getMaskedId());
116+
$order = $this->getOrder('test01');
117+
$this->assertEquals($quote->getGrandTotal(), $order->getGrandTotal());
118+
}
119+
85120
/**
86121
* @return array
87122
*/
@@ -150,4 +185,25 @@ private function createProduct(float $price): ProductInterface
150185

151186
return $productRepository->save($product);
152187
}
188+
189+
/**
190+
* Gets order entity by increment id.
191+
*
192+
* @param string $incrementId
193+
* @return OrderInterface
194+
*/
195+
private function getOrder(string $incrementId): OrderInterface
196+
{
197+
/** @var SearchCriteriaBuilder $searchCriteriaBuilder */
198+
$searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class);
199+
$searchCriteria = $searchCriteriaBuilder->addFilter('increment_id', $incrementId)
200+
->create();
201+
202+
/** @var OrderRepositoryInterface $repository */
203+
$repository = $this->objectManager->get(OrderRepositoryInterface::class);
204+
$items = $repository->getList($searchCriteria)
205+
->getItems();
206+
207+
return array_pop($items);
208+
}
153209
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
use Magento\Customer\Model\GroupManagement;
9+
use Magento\SalesRule\Api\CouponRepositoryInterface;
10+
use Magento\SalesRule\Model\Coupon;
11+
use Magento\SalesRule\Model\Rule;
12+
use Magento\Store\Model\StoreManagerInterface;
13+
use Magento\TestFramework\Helper\Bootstrap;
14+
15+
$objectManager = Bootstrap::getObjectManager();
16+
$salesRule = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\SalesRule\Model\Rule::class);
17+
$salesRule->setData(
18+
[
19+
'name' => '5$ fixed discount on whole cart',
20+
'is_active' => 1,
21+
'customer_group_ids' => [GroupManagement::NOT_LOGGED_IN_ID],
22+
'coupon_type' => Rule::COUPON_TYPE_SPECIFIC,
23+
'simple_action' => Rule::CART_FIXED_ACTION,
24+
'discount_amount' => 8,
25+
'discount_step' => 0,
26+
'stop_rules_processing' => 0,
27+
'website_ids' => [
28+
$objectManager->get(StoreManagerInterface::class)->getWebsite()->getId(),
29+
],
30+
]
31+
);
32+
$salesRule->getConditions()->loadArray([
33+
'type' => \Magento\SalesRule\Model\Rule\Condition\Combine::class,
34+
'attribute' => null,
35+
'operator' => null,
36+
'value' => '1',
37+
'is_value_processed' => null,
38+
'aggregator' => 'any',
39+
'conditions' =>
40+
[
41+
[
42+
'type' => \Magento\SalesRule\Model\Rule\Condition\Address::class,
43+
'attribute' => 'base_subtotal_with_discount',
44+
'operator' => '>=',
45+
'value' => 9,
46+
'is_value_processed' => false
47+
],
48+
],
49+
]);
50+
51+
$salesRule->save();
52+
53+
// Create coupon and assign "5$ fixed discount" rule to this coupon.
54+
$coupon = $objectManager->create(Coupon::class);
55+
$coupon->setRuleId($salesRule->getId())
56+
->setCode('CART_FIXED_DISCOUNT_5')
57+
->setType(0);
58+
$objectManager->get(CouponRepositoryInterface::class)->save($coupon);
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
use Magento\Quote\Api\GuestCouponManagementInterface;
8+
use Magento\TestFramework\Helper\Bootstrap;
9+
10+
\Magento\TestFramework\Helper\Bootstrap::getInstance()->loadArea('frontend');
11+
$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Catalog\Model\Product::class);
12+
$product->setTypeId('simple')
13+
->setId(1)
14+
->setAttributeSetId(4)
15+
->setName('Simple Product')
16+
->setSku('simple')
17+
->setPrice(10)
18+
->setTaxClassId(0)
19+
->setMetaTitle('meta title')
20+
->setMetaKeyword('meta keyword')
21+
->setMetaDescription('meta description')
22+
->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH)
23+
->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED)
24+
->setStockData(
25+
[
26+
'qty' => 100,
27+
'is_in_stock' => 1,
28+
'manage_stock' => 1,
29+
]
30+
)->save();
31+
32+
$productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
33+
->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
34+
$product = $productRepository->get('simple');
35+
36+
$addressData = include __DIR__ . '/../../../Magento/Sales/_files/address_data.php';
37+
$billingAddress = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
38+
\Magento\Quote\Model\Quote\Address::class,
39+
['data' => $addressData]
40+
);
41+
$billingAddress->setAddressType('billing');
42+
43+
$shippingAddress = clone $billingAddress;
44+
$shippingAddress->setId(null)->setAddressType('shipping');
45+
46+
$store = Magento\TestFramework\Helper\Bootstrap::getObjectManager()
47+
->get(\Magento\Store\Model\StoreManagerInterface::class)
48+
->getStore();
49+
50+
/** @var \Magento\Quote\Model\Quote $quote */
51+
$quote = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Quote\Model\Quote::class);
52+
$quote->setCustomerIsGuest(true)
53+
->setStoreId($store->getId())
54+
->setReservedOrderId('test01')
55+
->setBillingAddress($billingAddress)
56+
->setShippingAddress($shippingAddress)
57+
->addProduct($product);
58+
$quote->getPayment()->setMethod('checkmo');
59+
$quote->getShippingAddress()->setShippingMethod('flatrate_flatrate')->setCollectShippingRates(true);
60+
$quote->setIsMultiShipping('1');
61+
$quote->collectTotals();
62+
63+
$quoteRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
64+
->get(\Magento\Quote\Api\CartRepositoryInterface::class);
65+
$quoteRepository->save($quote);
66+
67+
/** @var \Magento\Quote\Model\QuoteIdMask $quoteIdMask */
68+
$quoteIdMask = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
69+
->create(\Magento\Quote\Model\QuoteIdMaskFactory::class)
70+
->create();
71+
$quoteIdMask->setQuoteId($quote->getId());
72+
$quoteIdMask->setDataChanges(true);
73+
$quoteIdMask->save();
74+
75+
$couponCode = 'CART_FIXED_DISCOUNT_5';
76+
$couponManagement = Bootstrap::getObjectManager()->create(GuestCouponManagementInterface::class);
77+
$couponManagement->set($quoteIdMask->getMaskedId(), $couponCode);
78+
79+

0 commit comments

Comments
 (0)