Skip to content

Commit 7024122

Browse files
authored
Merge pull request #5743 from magento-mpi/MC-32962
[MPI] MC-32962: [Magento Cloud] - Shopping Cart Rules not applying to children of Bundle
2 parents dc9b5a9 + 867fee7 commit 7024122

File tree

12 files changed

+555
-197
lines changed

12 files changed

+555
-197
lines changed

app/code/Magento/SalesRule/Model/Quote/Discount.php

Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,53 @@
66
namespace Magento\SalesRule\Model\Quote;
77

88
use Magento\Framework\App\ObjectManager;
9-
use Magento\SalesRule\Api\Data\RuleDiscountInterfaceFactory;
9+
use Magento\Framework\Event\ManagerInterface;
10+
use Magento\Framework\Pricing\PriceCurrencyInterface;
11+
use Magento\Quote\Api\Data\AddressInterface;
12+
use Magento\Quote\Api\Data\ShippingAssignmentInterface;
13+
use Magento\Quote\Model\Quote;
14+
use Magento\Quote\Model\Quote\Address\Total;
15+
use Magento\Quote\Model\Quote\Address\Total\AbstractTotal;
16+
use Magento\Quote\Model\Quote\Item;
17+
use Magento\Quote\Model\Quote\Item\AbstractItem;
18+
use Magento\SalesRule\Api\Data\DiscountDataInterface;
1019
use Magento\SalesRule\Api\Data\DiscountDataInterfaceFactory;
20+
use Magento\SalesRule\Api\Data\RuleDiscountInterfaceFactory;
21+
use Magento\SalesRule\Model\Data\RuleDiscount;
22+
use Magento\SalesRule\Model\Discount\PostProcessorFactory;
23+
use Magento\SalesRule\Model\Validator;
24+
use Magento\Store\Model\StoreManagerInterface;
1125

1226
/**
1327
* Discount totals calculation model.
28+
*
29+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1430
*/
15-
class Discount extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal
31+
class Discount extends AbstractTotal
1632
{
1733
const COLLECTOR_TYPE_CODE = 'discount';
1834

1935
/**
2036
* Discount calculation object
2137
*
22-
* @var \Magento\SalesRule\Model\Validator
38+
* @var Validator
2339
*/
2440
protected $calculator;
2541

2642
/**
2743
* Core event manager proxy
2844
*
29-
* @var \Magento\Framework\Event\ManagerInterface
45+
* @var ManagerInterface
3046
*/
3147
protected $eventManager = null;
3248

3349
/**
34-
* @var \Magento\Store\Model\StoreManagerInterface
50+
* @var StoreManagerInterface
3551
*/
3652
protected $storeManager;
3753

3854
/**
39-
* @var \Magento\Framework\Pricing\PriceCurrencyInterface
55+
* @var PriceCurrencyInterface
4056
*/
4157
protected $priceCurrency;
4258

@@ -51,18 +67,18 @@ class Discount extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal
5167
private $discountDataInterfaceFactory;
5268

5369
/**
54-
* @param \Magento\Framework\Event\ManagerInterface $eventManager
55-
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
56-
* @param \Magento\SalesRule\Model\Validator $validator
57-
* @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency
70+
* @param ManagerInterface $eventManager
71+
* @param StoreManagerInterface $storeManager
72+
* @param Validator $validator
73+
* @param PriceCurrencyInterface $priceCurrency
5874
* @param RuleDiscountInterfaceFactory|null $discountInterfaceFactory
5975
* @param DiscountDataInterfaceFactory|null $discountDataInterfaceFactory
6076
*/
6177
public function __construct(
62-
\Magento\Framework\Event\ManagerInterface $eventManager,
63-
\Magento\Store\Model\StoreManagerInterface $storeManager,
64-
\Magento\SalesRule\Model\Validator $validator,
65-
\Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency,
78+
ManagerInterface $eventManager,
79+
StoreManagerInterface $storeManager,
80+
Validator $validator,
81+
PriceCurrencyInterface $priceCurrency,
6682
RuleDiscountInterfaceFactory $discountInterfaceFactory = null,
6783
DiscountDataInterfaceFactory $discountDataInterfaceFactory = null
6884
) {
@@ -80,17 +96,17 @@ public function __construct(
8096
/**
8197
* Collect address discount amount
8298
*
83-
* @param \Magento\Quote\Model\Quote $quote
84-
* @param \Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment
85-
* @param \Magento\Quote\Model\Quote\Address\Total $total
99+
* @param Quote $quote
100+
* @param ShippingAssignmentInterface $shippingAssignment
101+
* @param Total $total
86102
* @return $this
87103
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
88104
* @SuppressWarnings(PHPMD.NPathComplexity)
89105
*/
90106
public function collect(
91-
\Magento\Quote\Model\Quote $quote,
92-
\Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment,
93-
\Magento\Quote\Model\Quote\Address\Total $total
107+
Quote $quote,
108+
ShippingAssignmentInterface $shippingAssignment,
109+
Total $total
94110
) {
95111
parent::collect($quote, $shippingAssignment, $total);
96112

@@ -122,7 +138,7 @@ public function collect(
122138
$address->getExtensionAttributes()->setDiscounts([]);
123139
$addressDiscountAggregator = [];
124140

125-
/** @var \Magento\Quote\Model\Quote\Item $item */
141+
/** @var Item $item */
126142
foreach ($items as $item) {
127143
if ($item->getNoDiscount() || !$this->calculator->canApplyDiscount($item)) {
128144
$item->setDiscountAmount(0);
@@ -147,7 +163,6 @@ public function collect(
147163

148164
if ($item->getHasChildren() && $item->isChildrenCalculated()) {
149165
$this->calculator->process($item);
150-
$this->distributeDiscount($item);
151166
foreach ($item->getChildren() as $child) {
152167
$eventArgs['item'] = $child;
153168
$this->eventManager->dispatch('sales_quote_address_discount_item', $eventArgs);
@@ -175,13 +190,13 @@ public function collect(
175190
/**
176191
* Aggregate item discount information to total data and related properties
177192
*
178-
* @param \Magento\Quote\Model\Quote\Item\AbstractItem $item
179-
* @param \Magento\Quote\Model\Quote\Address\Total $total
193+
* @param AbstractItem $item
194+
* @param Total $total
180195
* @return $this
181196
*/
182197
protected function aggregateItemDiscount(
183-
\Magento\Quote\Model\Quote\Item\AbstractItem $item,
184-
\Magento\Quote\Model\Quote\Address\Total $total
198+
AbstractItem $item,
199+
Total $total
185200
) {
186201
$total->addTotalAmount($this->getCode(), -$item->getDiscountAmount());
187202
$total->addBaseTotalAmount($this->getCode(), -$item->getBaseDiscountAmount());
@@ -191,10 +206,12 @@ protected function aggregateItemDiscount(
191206
/**
192207
* Distribute discount at parent item to children items
193208
*
194-
* @param \Magento\Quote\Model\Quote\Item\AbstractItem $item
209+
* @param AbstractItem $item
195210
* @return $this
211+
* @deprecated No longer used.
212+
* @see \Magento\SalesRule\Model\RulesApplier::applyRule()
196213
*/
197-
protected function distributeDiscount(\Magento\Quote\Model\Quote\Item\AbstractItem $item)
214+
protected function distributeDiscount(AbstractItem $item)
198215
{
199216
$parentBaseRowTotal = $item->getBaseRowTotal();
200217
$keys = [
@@ -230,12 +247,12 @@ protected function distributeDiscount(\Magento\Quote\Model\Quote\Item\AbstractIt
230247
/**
231248
* Add discount total information to address
232249
*
233-
* @param \Magento\Quote\Model\Quote $quote
234-
* @param \Magento\Quote\Model\Quote\Address\Total $total
250+
* @param Quote $quote
251+
* @param Total $total
235252
* @return array|null
236253
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
237254
*/
238-
public function fetch(\Magento\Quote\Model\Quote $quote, \Magento\Quote\Model\Quote\Address\Total $total)
255+
public function fetch(Quote $quote, Total $total)
239256
{
240257
$result = null;
241258
$amount = $total->getDiscountAmount();
@@ -254,25 +271,25 @@ public function fetch(\Magento\Quote\Model\Quote $quote, \Magento\Quote\Model\Qu
254271
/**
255272
* Aggregates discount per rule
256273
*
257-
* @param \Magento\Quote\Model\Quote\Item\AbstractItem $item
258-
* @param \Magento\Quote\Api\Data\AddressInterface $address
274+
* @param AbstractItem $item
275+
* @param AddressInterface $address
259276
* @param array $addressDiscountAggregator
260277
* @return void
261278
*/
262279
private function aggregateDiscountPerRule(
263-
\Magento\Quote\Model\Quote\Item\AbstractItem $item,
264-
\Magento\Quote\Api\Data\AddressInterface $address,
280+
AbstractItem $item,
281+
AddressInterface $address,
265282
array &$addressDiscountAggregator
266283
) {
267284
$discountBreakdown = $item->getExtensionAttributes()->getDiscounts();
268285
if ($discountBreakdown) {
269286
foreach ($discountBreakdown as $value) {
270-
/* @var \Magento\SalesRule\Api\Data\DiscountDataInterface $discount */
287+
/* @var DiscountDataInterface $discount */
271288
$discount = $value->getDiscountData();
272289
$ruleLabel = $value->getRuleLabel();
273290
$ruleID = $value->getRuleID();
274291
if (isset($addressDiscountAggregator[$ruleID])) {
275-
/** @var \Magento\SalesRule\Model\Data\RuleDiscount $cartDiscount */
292+
/** @var RuleDiscount $cartDiscount */
276293
$cartDiscount = $addressDiscountAggregator[$ruleID];
277294
$discountData = $cartDiscount->getDiscountData();
278295
$discountData->setBaseAmount($discountData->getBaseAmount()+$discount->getBaseAmount());
@@ -294,12 +311,12 @@ private function aggregateDiscountPerRule(
294311
'rule' => $ruleLabel,
295312
'rule_id' => $ruleID,
296313
];
297-
/** @var \Magento\SalesRule\Model\Data\RuleDiscount $cartDiscount */
314+
/** @var RuleDiscount $cartDiscount */
298315
$cartDiscount = $this->discountInterfaceFactory->create(['data' => $data]);
299316
$addressDiscountAggregator[$ruleID] = $cartDiscount;
300317
}
301318
}
302319
}
303-
$address->getExtensionAttributes()->setDiscounts(array_values($addressDiscountAggregator));
320+
$address->getExtensionAttributes()->setDiscounts(array_values($addressDiscountAggregator));
304321
}
305322
}

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

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@
1616
use Magento\SalesRule\Api\Data\DiscountDataInterfaceFactory;
1717

1818
/**
19-
* Class RulesApplier
20-
*
21-
* @package Magento\SalesRule\Model\Validator
19+
* Rule applier model
2220
*/
2321
class RulesApplier
2422
{
@@ -115,7 +113,6 @@ public function applyRules($item, $rules, $skipValidation, $couponCode)
115113
if (!$this->validatorUtility->canProcessRule($rule, $address)) {
116114
continue;
117115
}
118-
119116
if (!$skipValidation && !$rule->getActions()->validate($item)) {
120117
if (!$this->childrenValidationLocator->isChildrenValidationRequired($item)) {
121118
continue;
@@ -189,8 +186,22 @@ public function addDiscountDescription($address, $rule)
189186
*/
190187
protected function applyRule($item, $rule, $address, $couponCode)
191188
{
192-
$discountData = $this->getDiscountData($item, $rule, $address);
193-
$this->setDiscountData($discountData, $item);
189+
if ($item->getChildren() && $item->isChildrenCalculated()) {
190+
$cloneItem = clone $item;
191+
/**
192+
* validate without children
193+
*/
194+
$applyAll = $rule->getActions()->validate($cloneItem);
195+
foreach ($item->getChildren() as $childItem) {
196+
if ($applyAll || $rule->getActions()->validate($childItem)) {
197+
$discountData = $this->getDiscountData($childItem, $rule, $address);
198+
$this->setDiscountData($discountData, $childItem);
199+
}
200+
}
201+
} else {
202+
$discountData = $this->getDiscountData($item, $rule, $address);
203+
$this->setDiscountData($discountData, $item);
204+
}
194205

195206
$this->maintainAddressCouponCode($address, $rule, $couponCode);
196207
$this->addDiscountDescription($address, $rule);

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,13 @@ public function process(AbstractItem $item)
265265
$item->setDiscountAmount(0);
266266
$item->setBaseDiscountAmount(0);
267267
$item->setDiscountPercent(0);
268+
if ($item->getChildren() && $item->isChildrenCalculated()) {
269+
foreach ($item->getChildren() as $child) {
270+
$child->setDiscountAmount(0);
271+
$child->setBaseDiscountAmount(0);
272+
$child->setDiscountPercent(0);
273+
}
274+
}
268275

269276
$itemPrice = $this->getItemPrice($item);
270277
if ($itemPrice < 0) {

0 commit comments

Comments
 (0)