Skip to content

Commit a79bf77

Browse files
committed
Merge remote-tracking branch 'magento-l3/MC-43223' into L3_PR_21-10-19
2 parents 1f1d4e4 + c32b0fe commit a79bf77

File tree

2 files changed

+182
-8
lines changed

2 files changed

+182
-8
lines changed

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

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77

88
use Magento\Quote\Model\Quote\Address;
99
use Magento\Quote\Model\Quote\Item\AbstractItem;
10+
use Magento\SalesRule\Model\Data\RuleDiscount;
1011
use Magento\SalesRule\Model\Quote\ChildrenValidationLocator;
1112
use Magento\Framework\App\ObjectManager;
1213
use Magento\SalesRule\Model\ResourceModel\Rule\Collection;
1314
use Magento\SalesRule\Model\Rule\Action\Discount\CalculatorFactory;
15+
use Magento\SalesRule\Model\Rule\Action\Discount\Data;
1416
use Magento\SalesRule\Model\Rule\Action\Discount\DataFactory;
1517
use Magento\SalesRule\Api\Data\RuleDiscountInterfaceFactory;
1618
use Magento\SalesRule\Api\Data\DiscountDataInterfaceFactory;
@@ -108,6 +110,9 @@ public function applyRules($item, $rules, $skipValidation, $couponCode)
108110
$address = $item->getAddress();
109111
$appliedRuleIds = [];
110112
$this->discountAggregator = [];
113+
if ($item->getExtensionAttributes()) {
114+
$item->getExtensionAttributes()->setDiscounts(null);
115+
}
111116
/* @var $rule Rule */
112117
foreach ($rules as $rule) {
113118
if (!$this->validatorUtility->canProcessRule($rule, $address)) {
@@ -215,7 +220,7 @@ protected function applyRule($item, $rule, $address, $couponCode)
215220
* @param AbstractItem $item
216221
* @param \Magento\SalesRule\Model\Rule $rule
217222
* @param \Magento\Quote\Model\Quote\Address $address
218-
* @return \Magento\SalesRule\Model\Rule\Action\Discount\Data
223+
* @return Data
219224
*/
220225
protected function getDiscountData($item, $rule, $address)
221226
{
@@ -241,7 +246,7 @@ protected function getDiscountData($item, $rule, $address)
241246
/**
242247
* Set Discount Breakdown
243248
*
244-
* @param \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData
249+
* @param Data $discountData
245250
* @param \Magento\Quote\Model\Quote\Item\AbstractItem $item
246251
* @param \Magento\SalesRule\Model\Rule $rule
247252
* @param \Magento\Quote\Model\Quote\Address $address
@@ -263,18 +268,72 @@ private function setDiscountBreakdown($discountData, $item, $rule, $address)
263268
'rule' => $ruleLabel,
264269
'rule_id' => $rule->getId(),
265270
];
266-
/** @var \Magento\SalesRule\Model\Data\RuleDiscount $itemDiscount */
271+
/** @var RuleDiscount $itemDiscount */
267272
$ruleDiscount = $this->discountInterfaceFactory->create(['data' => $data]);
268273
$this->discountAggregator[] = $ruleDiscount;
269274
$item->getExtensionAttributes()->setDiscounts($this->discountAggregator);
275+
$parentItem = $item->getParentItem();
276+
277+
if ($parentItem && $parentItem->getExtensionAttributes()) {
278+
$this->aggregateDiscountBreakdown($discountData, $parentItem, $rule, $address);
279+
}
270280
}
271281
return $this;
272282
}
273283

284+
/**
285+
* Add Discount Breakdown to existing discount data
286+
*
287+
* @param Data $discountData
288+
* @param AbstractItem $item
289+
* @param Rule $rule
290+
* @param Address $address
291+
*/
292+
private function aggregateDiscountBreakdown(
293+
Data $discountData,
294+
AbstractItem $item,
295+
Rule $rule,
296+
Address $address
297+
): void {
298+
$ruleLabel = $rule->getStoreLabel($address->getQuote()->getStore()) ?: __('Discount');
299+
/** @var RuleDiscount[] $discounts */
300+
$discounts = [];
301+
foreach ((array) $item->getExtensionAttributes()->getDiscounts() as $discount) {
302+
$discounts[$discount->getRuleID()] = $discount;
303+
}
304+
305+
$data = [
306+
'amount' => $discountData->getAmount(),
307+
'base_amount' => $discountData->getBaseAmount(),
308+
'original_amount' => $discountData->getOriginalAmount(),
309+
'base_original_amount' => $discountData->getBaseOriginalAmount()
310+
];
311+
312+
$discount = $discounts[$rule->getId()] ?? null;
313+
314+
if (isset($discount)) {
315+
$data['amount'] += $discount->getDiscountData()->getAmount();
316+
$data['base_amount'] += $discount->getDiscountData()->getBaseAmount();
317+
$data['original_amount'] += $discount->getDiscountData()->getOriginalAmount();
318+
$data['base_original_amount'] += $discount->getDiscountData()->getBaseOriginalAmount();
319+
}
320+
321+
$discounts[$rule->getId()] = $this->discountInterfaceFactory->create(
322+
[
323+
'data' => [
324+
'discount' => $this->discountDataInterfaceFactory->create(['data' => $data]),
325+
'rule' => $ruleLabel,
326+
'rule_id' => $rule->getId(),
327+
]
328+
]
329+
);
330+
$item->getExtensionAttributes()->setDiscounts(array_values($discounts));
331+
}
332+
274333
/**
275334
* Set Discount data
276335
*
277-
* @param \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData
336+
* @param Data $discountData
278337
* @param AbstractItem $item
279338
* @return $this
280339
*/
@@ -312,14 +371,14 @@ public function maintainAddressCouponCode($address, $rule, $couponCode)
312371
/**
313372
* Fire event to allow overwriting of discount amounts
314373
*
315-
* @param \Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData
374+
* @param Data $discountData
316375
* @param AbstractItem $item
317376
* @param Rule $rule
318377
* @param float $qty
319378
* @return $this
320379
*/
321380
protected function eventFix(
322-
\Magento\SalesRule\Model\Rule\Action\Discount\Data $discountData,
381+
Data $discountData,
323382
AbstractItem $item,
324383
Rule $rule,
325384
$qty

dev/tests/api-functional/testsuite/Magento/GraphQl/Bundle/AddBundleProductToCartSingleMutationTest.php

Lines changed: 117 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
namespace Magento\GraphQl\Bundle;
99

1010
use Magento\Catalog\Api\ProductRepositoryInterface;
11+
use Magento\Framework\DataObject;
1112
use Magento\Quote\Model\Quote;
1213
use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface;
1314
use Magento\Quote\Model\ResourceModel\Quote as QuoteResource;
@@ -240,8 +241,7 @@ public function testAddBundleItemWithCustomOptionQuantity(
240241
string $optionQty1,
241242
string $expectedOptionQty0,
242243
string $expectedOptionQty1
243-
): void
244-
{
244+
): void {
245245
$this->quoteResource->load(
246246
$this->quote,
247247
'test_order_1',
@@ -263,6 +263,58 @@ public function testAddBundleItemWithCustomOptionQuantity(
263263
$this->assertEquals($expectedOptionQty1, $bundleOptions[1]['values'][0]['quantity']);
264264
}
265265

266+
/**
267+
* @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php
268+
* @magentoApiDataFixture Magento/Bundle/_files/bundle_product_with_dynamic_price.php
269+
* @magentoApiDataFixture Magento/Checkout/_files/active_quote.php
270+
* @return void
271+
*/
272+
public function testAddBundleProductToCartWithDiscount(): void
273+
{
274+
$this->quoteResource->load(
275+
$this->quote,
276+
'test_order_1',
277+
'reserved_order_id'
278+
);
279+
$maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId());
280+
$response = $this->graphQlQuery($this->getProductQuery('bundle_product_with_dynamic_price'));
281+
$bundleItem = $response['products']['items'][0];
282+
$sku = $bundleItem['sku'];
283+
$bundleOptions = $bundleItem['items'];
284+
285+
$uId0 = $bundleOptions[0]['options'][0]['uid'];
286+
$uId1 = $bundleOptions[1]['options'][0]['uid'];
287+
$response = $this->graphQlMutation(
288+
$this->getMutationsQuery($maskedQuoteId, $uId0, $uId1, $sku, '1', '1')
289+
);
290+
$responseDataObject = new DataObject($response);
291+
$cartItems = $responseDataObject->getData('addProductsToCart/cart/items');
292+
self::assertIsArray($cartItems);
293+
self::assertCount(1, $cartItems);
294+
self::assertEquals($sku, $cartItems[0]['product']['sku']);
295+
296+
$couponCode = '2?ds5!2d';
297+
$query = $this->getCouponMutationsQuery($maskedQuoteId, $couponCode);
298+
$response = $this->graphQlMutation($query);
299+
$responseDataObject = new DataObject($response);
300+
$appliedCouponCode = $responseDataObject->getData('applyCouponToCart/cart/applied_coupon/code');
301+
self::assertEquals($couponCode, $appliedCouponCode);
302+
303+
$query = $this->getCartQueryWithDiscounts($maskedQuoteId);
304+
$response = $this->graphQlMutation($query);
305+
$responseDataObject = new DataObject($response);
306+
$discounts = $responseDataObject->getData('cart/prices/discounts');
307+
self::assertIsArray($discounts);
308+
self::assertCount(1, $discounts);
309+
self::assertEquals(5, $discounts[0]['amount']['value']);
310+
$cartItems = $responseDataObject->getData('cart/items');
311+
self::assertIsArray($cartItems);
312+
self::assertCount(1, $cartItems);
313+
self::assertEquals($sku, $cartItems[0]['product']['sku']);
314+
self::assertIsArray($cartItems[0]['prices']['discounts']);
315+
self::assertEquals(5, $cartItems[0]['prices']['discounts'][0]['amount']['value']);
316+
}
317+
266318
/**
267319
* Data provider for testAddBundleItemWithCustomOptionQuantity
268320
*
@@ -396,6 +448,69 @@ private function getMutationsQuery(
396448
}
397449
}
398450
}
451+
QUERY;
452+
}
453+
454+
/**
455+
* @param string $maskedQuoteId
456+
* @param string $couponCode
457+
* @return string
458+
*/
459+
private function getCouponMutationsQuery(string $maskedQuoteId, string $couponCode): string
460+
{
461+
return <<<QUERY
462+
mutation {
463+
applyCouponToCart(input: {cart_id: "$maskedQuoteId", coupon_code: "$couponCode"}) {
464+
cart {
465+
id
466+
applied_coupon {
467+
code
468+
}
469+
}
470+
}
471+
}
472+
QUERY;
473+
}
474+
475+
/**
476+
* @param string $maskedQuoteId
477+
* @return string
478+
*/
479+
private function getCartQueryWithDiscounts(string $maskedQuoteId): string
480+
{
481+
return <<<QUERY
482+
{
483+
cart(cart_id: "$maskedQuoteId") {
484+
email
485+
items {
486+
uid
487+
prices {
488+
discounts {
489+
amount {
490+
value
491+
}
492+
}
493+
}
494+
product {
495+
sku
496+
}
497+
}
498+
applied_coupons {
499+
code
500+
}
501+
prices {
502+
discounts {
503+
amount {
504+
value
505+
}
506+
label
507+
}
508+
grand_total {
509+
value
510+
}
511+
}
512+
}
513+
}
399514
QUERY;
400515
}
401516
}

0 commit comments

Comments
 (0)