Skip to content

Commit 94a25ee

Browse files
committed
Merge branch 'ACP2E-3498' of https://github.com/adobe-commerce-tier-4/magento2ce into PR-VK-2024-12-17-CE
2 parents 7b651ed + 236e9ec commit 94a25ee

File tree

7 files changed

+269
-18
lines changed

7 files changed

+269
-18
lines changed

app/code/Magento/SalesRule/Model/Rule/Action/Discount/CartFixed.php

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Magento\SalesRule\Model\DeltaPriceRound;
1414
use Magento\SalesRule\Model\Rule;
1515
use Magento\SalesRule\Model\Validator;
16+
use Magento\Quote\Model\Quote\Item;
1617

1718
/**
1819
* Calculates discount for cart item if fixed discount applied on whole cart.
@@ -29,33 +30,41 @@ class CartFixed extends AbstractDiscount
2930
/**
3031
* @var DeltaPriceRound
3132
*/
32-
private $deltaPriceRound;
33+
private DeltaPriceRound $deltaPriceRound;
3334

3435
/**
3536
* @var CartFixedDiscount
3637
*/
37-
private $cartFixedDiscountHelper;
38+
private CartFixedDiscount $cartFixedDiscountHelper;
3839

3940
/**
4041
* @var string
4142
*/
4243
private static $discountType = 'CartFixed';
4344

45+
/**
46+
* @var ExistingDiscountRuleCollector
47+
*/
48+
private ExistingDiscountRuleCollector $existingDiscountRuleCollector;
49+
4450
/**
4551
* @param Validator $validator
4652
* @param DataFactory $discountDataFactory
4753
* @param PriceCurrencyInterface $priceCurrency
4854
* @param DeltaPriceRound $deltaPriceRound
55+
* @param ExistingDiscountRuleCollector $existingDiscountRuleCollector
4956
* @param CartFixedDiscount|null $cartFixedDiscount
5057
*/
5158
public function __construct(
5259
Validator $validator,
5360
DataFactory $discountDataFactory,
5461
PriceCurrencyInterface $priceCurrency,
5562
DeltaPriceRound $deltaPriceRound,
63+
ExistingDiscountRuleCollector $existingDiscountRuleCollector,
5664
?CartFixedDiscount $cartFixedDiscount = null
5765
) {
5866
$this->deltaPriceRound = $deltaPriceRound;
67+
$this->existingDiscountRuleCollector = $existingDiscountRuleCollector;
5968
$this->cartFixedDiscountHelper = $cartFixedDiscount ?:
6069
ObjectManager::getInstance()->get(CartFixedDiscount::class);
6170
parent::__construct($validator, $discountDataFactory, $priceCurrency);
@@ -75,9 +84,6 @@ public function __construct(
7584
*/
7685
public function calculate($rule, $item, $qty)
7786
{
78-
/** @var Data $discountData */
79-
$discountData = $this->discountFactory->create();
80-
8187
$ruleTotals = $this->validator->getRuleItemTotalsInfo($rule->getId());
8288
$baseRuleTotals = $ruleTotals['base_items_price'] ?? 0.0;
8389
$ruleItemsCount = $ruleTotals['items_count'] ?? 0;
@@ -102,6 +108,8 @@ public function calculate($rule, $item, $qty)
102108
$availableDiscountAmount = (float) $cartRules[$rule->getId()];
103109
$discountType = self::$discountType . $rule->getId();
104110

111+
/** @var Data $discountData */
112+
$discountData = $this->discountFactory->create();
105113
if ($availableDiscountAmount > 0) {
106114
$store = $quote->getStore();
107115
$shippingPrice = $this->cartFixedDiscountHelper->applyDiscountOnPricesIncludedTax()
@@ -133,9 +141,11 @@ public function calculate($rule, $item, $qty)
133141
$qty,
134142
$baseItemPrice,
135143
$baseItemDiscountAmount,
136-
$baseRuleTotals - $address->getBaseDiscountAmount(),
144+
$baseRuleTotals -
145+
$this->getItemsTotalDiscount($rule->getId(), $ruleTotals['affected_items']),
137146
$discountType
138147
);
148+
139149
}
140150
$discountAmount = $this->priceCurrency->convert($baseDiscountAmount, $store);
141151
$baseDiscountAmount = min($baseItemPrice * $qty, $baseDiscountAmount);
@@ -190,6 +200,27 @@ public function calculate($rule, $item, $qty)
190200
return $discountData;
191201
}
192202

203+
/**
204+
* Get existing discount applied to affected items
205+
*
206+
* @param int $ruleId
207+
* @param array $affectedItems
208+
* @return float
209+
*/
210+
private function getItemsTotalDiscount(int $ruleId, array $affectedItems): float
211+
{
212+
if ($this->existingDiscountRuleCollector->getExistingRuleDiscount($ruleId) === null) {
213+
$existingRuleDiscount = 0;
214+
/** @var Item $ruleItem */
215+
foreach ($affectedItems as $ruleItem) {
216+
$existingRuleDiscount += $ruleItem->getBaseDiscountAmount();
217+
}
218+
$this->existingDiscountRuleCollector->setExistingRuleDiscount($ruleId, $existingRuleDiscount);
219+
}
220+
221+
return $this->existingDiscountRuleCollector->getExistingRuleDiscount($ruleId);
222+
}
223+
193224
/**
194225
* Set information about usage cart fixed rule by quote address
195226
*
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\Model\Rule\Action\Discount;
9+
10+
use Magento\Framework\ObjectManager\ResetAfterRequestInterface;
11+
12+
class ExistingDiscountRuleCollector implements ResetAfterRequestInterface
13+
{
14+
/**
15+
* @var array
16+
*/
17+
private array $ruleDiscounts = [];
18+
19+
/**
20+
* Store discounts that are applied to affected items by previous rules
21+
*
22+
* @param int $ruleId
23+
* @param float $discountAmount
24+
* @return void
25+
*/
26+
public function setExistingRuleDiscount(int $ruleId, float $discountAmount): void
27+
{
28+
$this->ruleDiscounts[$ruleId] = $discountAmount;
29+
}
30+
31+
/**
32+
* Retrieve discount that was applied to affected items by previous rule
33+
*
34+
* @param int $ruleId
35+
* @return float|null
36+
*/
37+
public function getExistingRuleDiscount(int $ruleId): ?float
38+
{
39+
return $this->ruleDiscounts[$ruleId] ?? null;
40+
}
41+
42+
/**
43+
* @inheritDoc
44+
*/
45+
public function _resetState(): void
46+
{
47+
$this->ruleDiscounts = [];
48+
}
49+
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,7 @@ public function initTotals($items, Address $address)
576576
$ruleTotalBaseItemsDiscountAmount = 0;
577577
$validItemsCount = 0;
578578

579+
$affectedItems = [];
579580
/** @var Quote\Item $item */
580581
foreach ($items as $item) {
581582
if (!$this->isValidItemForRule($item, $rule)) {
@@ -587,6 +588,7 @@ public function initTotals($items, Address $address)
587588
$ruleTotalItemsDiscountAmount += $item->getDiscountAmount();
588589
$ruleTotalBaseItemsDiscountAmount += $item->getBaseDiscountAmount();
589590
$validItemsCount++;
591+
$affectedItems[] = $item;
590592
}
591593

592594
$this->_rulesItemTotals[$rule->getId()] = [
@@ -595,6 +597,7 @@ public function initTotals($items, Address $address)
595597
'base_items_price' => $ruleTotalBaseItemsPrice,
596598
'base_items_discount_amount' => $ruleTotalBaseItemsDiscountAmount,
597599
'items_count' => $validItemsCount,
600+
'affected_items' => $affectedItems
598601
];
599602
}
600603

app/code/Magento/SalesRule/Test/Unit/Model/Rule/Action/Discount/CartFixedTest.php

Lines changed: 20 additions & 6 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 2014 Adobe
4+
* All Rights Reserved.
55
*/
66
declare(strict_types=1);
77

@@ -19,6 +19,7 @@
1919
use Magento\SalesRule\Model\Rule\Action\Discount\CartFixed;
2020
use Magento\SalesRule\Model\Rule\Action\Discount\Data;
2121
use Magento\SalesRule\Model\Rule\Action\Discount\DataFactory;
22+
use Magento\SalesRule\Model\Rule\Action\Discount\ExistingDiscountRuleCollector;
2223
use Magento\SalesRule\Model\Validator;
2324
use Magento\Store\Model\Store;
2425
use PHPUnit\Framework\MockObject\MockObject;
@@ -81,6 +82,11 @@ class CartFixedTest extends TestCase
8182
*/
8283
protected $cartFixedDiscountHelper;
8384

85+
/**
86+
* @var ExistingDiscountRuleCollector|MockObject
87+
*/
88+
private ExistingDiscountRuleCollector $existingDiscountRuleCollector;
89+
8490
/**
8591
* @inheritdoc
8692
*/
@@ -136,11 +142,16 @@ protected function setUp(): void
136142
->disableOriginalConstructor()
137143
->getMock();
138144

145+
$this->existingDiscountRuleCollector = $this->createMock(ExistingDiscountRuleCollector::class);
146+
$this->existingDiscountRuleCollector->expects($this->any())
147+
->method('getExistingRuleDiscount')
148+
->willReturn(0.00);
139149
$this->model = new CartFixed(
140150
$this->validator,
141151
$dataFactory,
142152
$this->priceCurrency,
143153
$this->deltaPriceRound,
154+
$this->existingDiscountRuleCollector,
144155
$this->cartFixedDiscountHelper
145156
);
146157
}
@@ -150,7 +161,7 @@ protected function setUp(): void
150161
* @dataProvider dataProviderActions
151162
* @param array $shipping
152163
* @param array $ruleDetails
153-
* @throws LocalizedException
164+
* @throws LocalizedException|\PHPUnit\Framework\MockObject\Exception
154165
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
155166
*/
156167
public function testCalculate(array $shipping, array $ruleDetails): void
@@ -279,7 +290,8 @@ public static function dataProviderActions()
279290
'items_count' => 1,
280291
'rounded_amount' => 0.0,
281292
'discounted_amount' => 10.0,
282-
'cart_rules' => 0.0
293+
'cart_rules' => 0.0,
294+
'affected_items' => []
283295
]
284296
],
285297
'regular shipping with two items and single shipping' => [
@@ -294,7 +306,8 @@ public static function dataProviderActions()
294306
'items_count' => 2,
295307
'rounded_amount' => 0.0,
296308
'discounted_amount' => 10.0,
297-
'cart_rules' => 0.0
309+
'cart_rules' => 0.0,
310+
'affected_items' => []
298311
]
299312
],
300313
'regular shipping with two items and multiple shipping' => [
@@ -309,7 +322,8 @@ public static function dataProviderActions()
309322
'items_count' => 2,
310323
'rounded_amount' => 0.0,
311324
'discounted_amount' => 10.0,
312-
'cart_rules' => 0.0
325+
'cart_rules' => 0.0,
326+
'affected_items' => []
313327
]
314328
]
315329

app/code/Magento/SalesRule/Test/Unit/Model/ValidatorTest.php

Lines changed: 3 additions & 2 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 2012 Adobe
4+
* All Rights Reserved.
55
*/
66
declare(strict_types=1);
77

@@ -461,6 +461,7 @@ public function testInitTotalsCanApplyDiscount(): void
461461
$this->assertArrayHasKey('items_price', $this->model->getRuleItemTotalsInfo($rule->getId()));
462462
$this->assertArrayHasKey('base_items_price', $this->model->getRuleItemTotalsInfo($rule->getId()));
463463
$this->assertArrayHasKey('items_count', $this->model->getRuleItemTotalsInfo($rule->getId()));
464+
$this->assertArrayHasKey('affected_items', $this->model->getRuleItemTotalsInfo($rule->getId()));
464465
$this->assertEquals(1, $this->model->getRuleItemTotalsInfo($rule->getId())['items_count']);
465466
}
466467

app/code/Magento/SalesRule/etc/di.xml

Lines changed: 3 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 2013 Adobe
5+
* All Rights Reserved.
66
*/
77
-->
88
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
@@ -211,4 +211,5 @@
211211
<argument name="scopeConfig" xsi:type="object">Magento\Framework\App\Config\ScopeConfigInterface\Proxy</argument>
212212
</arguments>
213213
</type>
214+
<type name="Magento\SalesRule\Model\Rule\Action\Discount\ExistingDiscountRuleCollector" shared="true" />
214215
</config>

0 commit comments

Comments
 (0)