Skip to content

Commit 9147bf1

Browse files
committed
Merge remote-tracking branches 'local/ACP2E-780', 'local/ACP2E-785' and 'local/ACP2E-793' into PR_19_May_2022_Odubovyk
4 parents 08a39d5 + 613ab57 + c928f95 + b745d1d commit 9147bf1

File tree

6 files changed

+315
-4
lines changed

6 files changed

+315
-4
lines changed

app/code/Magento/Customer/Model/Validator/Name.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
class Name extends AbstractValidator
1717
{
18-
private const PATTERN_NAME = '/(?:[\p{L}\p{M}\,\-\_\.\'’\s\d]){1,255}+/u';
18+
private const PATTERN_NAME = '/(?:[\p{L}\p{M}\,\-\_\.\'`\s\d]){1,255}+/u';
1919

2020
/**
2121
* Validate name fields.

app/code/Magento/Customer/Test/Unit/Model/Validator/NameTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ public function expectedPunctuationInNamesDataProvider(): array
8181
'middleName' => '',
8282
'lastNameName' => 'O\'Doe',
8383
'message' => 'Legacy straight apostrophe must be allowed in names'
84+
],
85+
[
86+
'firstName' => 'John',
87+
'middleName' => '',
88+
'lastNameName' => 'O`Doe',
89+
'message' => 'Grave accent back quote character must be allowed in names'
8490
]
8591
];
8692
}

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ public function calculate($rule, $item, $qty)
2222

2323
$baseDiscountAmount = (float) $rule->getDiscountAmount();
2424
$discountAmount = $this->priceCurrency->convert($baseDiscountAmount, $item->getQuote()->getStore());
25+
$itemDiscountAmount = $item->getDiscountAmount();
26+
$itemBaseDiscountAmount = $item->getBaseDiscountAmount();
2527
$itemPrice = $this->validator->getItemPrice($item);
2628
$baseItemPrice = $this->validator->getItemBasePrice($item);
2729

28-
$discountAmountMin = min($itemPrice * $qty, $discountAmount * $qty);
29-
$baseDiscountAmountMin = min($baseItemPrice * $qty, $baseDiscountAmount * $qty);
30+
$discountAmountMin = min(($itemPrice * $qty) - $itemDiscountAmount, $discountAmount * $qty);
31+
$baseDiscountAmountMin = min(($baseItemPrice * $qty) - $itemBaseDiscountAmount, $baseDiscountAmount * $qty);
3032

3133
$discountData->setAmount($discountAmountMin);
3234
$discountData->setBaseAmount($baseDiscountAmountMin);

app/code/Magento/SalesRule/Model/Rule/Condition/Product/Subselect.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
*/
66
namespace Magento\SalesRule\Model\Rule\Condition\Product;
77

8+
use Magento\Quote\Api\Data\TotalsItemInterface;
9+
810
/**
911
* Subselect conditions for product.
1012
*/
@@ -163,9 +165,12 @@ public function validate(\Magento\Framework\Model\AbstractModel $model)
163165
}
164166
}
165167
}
168+
if ($attr !== TotalsItemInterface::KEY_BASE_ROW_TOTAL) {
169+
$childrenAttrTotal *= $item->getQty();
170+
}
166171
if ($hasValidChild || parent::validate($item)) {
167172
$total += ($hasValidChild && $useChildrenTotal && $childrenAttrTotal > 0)
168-
? $childrenAttrTotal * $item->getQty()
173+
? $childrenAttrTotal
169174
: $item->getData($attr);
170175
}
171176
}
Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
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+
namespace Magento\SalesRule\Test\Unit\Model\Rule\Action\Discount;
9+
10+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
11+
use Magento\Quote\Model\Quote;
12+
use Magento\Quote\Model\Quote\Item\AbstractItem;
13+
use Magento\SalesRule\Model\Rule;
14+
use Magento\SalesRule\Model\Rule\Action\Discount\ByFixed;
15+
use Magento\SalesRule\Model\Rule\Action\Discount\Data;
16+
use Magento\SalesRule\Model\Rule\Action\Discount\DataFactory;
17+
use Magento\SalesRule\Model\Validator;
18+
use Magento\Framework\Pricing\PriceCurrencyInterface;
19+
use Magento\Store\Model\Store;
20+
use PHPUnit\Framework\MockObject\MockObject;
21+
use PHPUnit\Framework\TestCase;
22+
23+
class ByFixedTest extends TestCase
24+
{
25+
/**
26+
* @var ByFixed
27+
*/
28+
protected $model;
29+
30+
/**
31+
* @var Validator|MockObject
32+
*/
33+
protected $validator;
34+
35+
/**
36+
* @var PriceCurrencyInterface|MockObject
37+
*/
38+
protected $priceCurrency;
39+
40+
/**
41+
* @var DataFactory|MockObject
42+
*/
43+
protected $discountDataFactory;
44+
45+
protected function setUp(): void
46+
{
47+
$helper = new ObjectManager($this);
48+
49+
$this->validator = $this->getMockBuilder(
50+
Validator::class
51+
)->disableOriginalConstructor()
52+
->setMethods(
53+
['getItemPrice', 'getItemBasePrice', 'getItemOriginalPrice', 'getItemBaseOriginalPrice']
54+
)->getMock();
55+
56+
$this->priceCurrency = $this->getMockBuilder(PriceCurrencyInterface::class)
57+
->getMockForAbstractClass();
58+
59+
$this->discountDataFactory = $this->getMockBuilder(
60+
DataFactory::class
61+
)->disableOriginalConstructor()
62+
->setMethods(
63+
['create']
64+
)->getMock();
65+
66+
$this->model = $helper->getObject(
67+
ByFixed::class,
68+
[
69+
'discountDataFactory' => $this->discountDataFactory,
70+
'validator' => $this->validator,
71+
'priceCurrency' => $this->priceCurrency
72+
]
73+
);
74+
}
75+
76+
/**
77+
* Test fixed discount cannot be higher than products price
78+
*
79+
* @param $qty
80+
* @param $ruleData
81+
* @param $itemData
82+
* @param $validItemData
83+
* @param $expectedDiscountData
84+
* @dataProvider calculateDataProvider
85+
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
86+
*/
87+
public function testCalculate(
88+
$qty,
89+
$ruleData,
90+
$itemData,
91+
$validItemData,
92+
$expectedDiscountData
93+
) {
94+
$discountData = $this->getMockBuilder(
95+
Data::class
96+
)->disableOriginalConstructor()
97+
->setMethods(
98+
['setAmount', 'setBaseAmount', 'setOriginalAmount', 'setBaseOriginalAmount']
99+
)->getMock();
100+
101+
$this->discountDataFactory->expects($this->once())->method('create')->willReturn($discountData);
102+
103+
$rule = $this->getMockBuilder(
104+
Rule::class
105+
)->disableOriginalConstructor()
106+
->setMethods(
107+
['getDiscountAmount']
108+
)->getMock();
109+
110+
$quote = $this->getMockBuilder(Quote::class)
111+
->onlyMethods(['getStore'])
112+
->disableOriginalConstructor()
113+
->getMock();
114+
$store = $this->createMock(Store::class);
115+
$quote->expects($this->any())->method('getStore')->will($this->returnValue($store));
116+
117+
$item = $this->getMockBuilder(
118+
AbstractItem::class
119+
)->disableOriginalConstructor()
120+
->setMethods(
121+
[
122+
'getDiscountAmount',
123+
'getBaseDiscountAmount',
124+
'getQuote',
125+
'getAddress',
126+
'getOptionByCode',
127+
]
128+
)->getMock();
129+
130+
$this->validator->expects(
131+
$this->atLeastOnce()
132+
)->method(
133+
'getItemPrice'
134+
)->with(
135+
$item
136+
)->willReturn(
137+
$validItemData['price']
138+
);
139+
$this->validator->expects(
140+
$this->any()
141+
)->method(
142+
'getItemBasePrice'
143+
)->with(
144+
$item
145+
)->willReturn(
146+
$validItemData['basePrice']
147+
);
148+
$this->validator->expects(
149+
$this->any()
150+
)->method(
151+
'getItemOriginalPrice'
152+
)->with(
153+
$item
154+
)->willReturn(
155+
$validItemData['originalPrice']
156+
);
157+
$this->validator->expects(
158+
$this->any()
159+
)->method(
160+
'getItemBaseOriginalPrice'
161+
)->with(
162+
$item
163+
)->willReturn(
164+
$validItemData['baseOriginalPrice']
165+
);
166+
167+
$this->priceCurrency->expects(
168+
$this->any()
169+
)->method(
170+
'convert'
171+
)->with(
172+
$ruleData['discountAmount'],
173+
$store
174+
)->willReturn(
175+
$validItemData['baseOriginalPrice']
176+
);
177+
178+
$rule->expects(
179+
$this->atLeastOnce()
180+
)->method(
181+
'getDiscountAmount'
182+
)->willReturn(
183+
$ruleData['discountAmount']
184+
);
185+
186+
$item->expects(
187+
$this->atLeastOnce()
188+
)->method(
189+
'getDiscountAmount'
190+
)->willReturn(
191+
$itemData['discountAmount']
192+
);
193+
$item->expects(
194+
$this->atLeastOnce()
195+
)->method(
196+
'getBaseDiscountAmount'
197+
)->willReturn(
198+
$itemData['baseDiscountAmount']
199+
);
200+
$item->expects($this->atLeastOnce())->method('getQuote')->willReturn($quote);
201+
202+
$discountData->expects($this->once())->method('setAmount')->with($expectedDiscountData['amount']);
203+
$discountData->expects($this->once())->method('setBaseAmount')->with($expectedDiscountData['baseAmount']);
204+
$discountData->expects(
205+
$this->any()
206+
)->method(
207+
'setOriginalAmount'
208+
)->with(
209+
$expectedDiscountData['originalAmount']
210+
);
211+
$discountData->expects(
212+
$this->any()
213+
)->method(
214+
'setBaseOriginalAmount'
215+
)->with(
216+
$expectedDiscountData['baseOriginalAmount']
217+
);
218+
219+
$this->assertEquals($discountData, $this->model->calculate($rule, $item, $qty));
220+
}
221+
222+
/**
223+
* @return array
224+
*/
225+
public function calculateDataProvider()
226+
{
227+
return [
228+
[
229+
'qty' => 2,
230+
'ruleData' => ['discountAmount' => 100],
231+
'itemData' => ['discountAmount' => 139, 'baseDiscountAmount' => 139],
232+
'validItemData' => [
233+
'price' => 139,
234+
'basePrice' => 139,
235+
'originalPrice' => 139,
236+
'baseOriginalPrice' => 139,
237+
],
238+
'expectedDiscountData' => [
239+
'amount' => 139,
240+
'baseAmount' => 139,
241+
'originalAmount' => 0,
242+
'baseOriginalAmount' => 0,
243+
],
244+
]
245+
];
246+
}
247+
248+
/**
249+
* Test Fixing quantity depending on discount step
250+
*
251+
* @param int $step
252+
* @param int|float $qty
253+
* @param int $expected
254+
* @dataProvider fixQuantityDataProvider
255+
*/
256+
public function testFixQuantity($step, $qty, $expected)
257+
{
258+
$rule = $this->getMockBuilder(Rule::class)
259+
->addMethods(['getDiscountStep'])
260+
->disableOriginalConstructor()
261+
->getMock();
262+
$rule->expects($this->once())->method('getDiscountStep')->willReturn($step);
263+
264+
$this->assertEquals($expected, $this->model->fixQuantity($qty, $rule));
265+
}
266+
267+
/**
268+
* @return array
269+
*/
270+
public function fixQuantityDataProvider()
271+
{
272+
return [
273+
['step' => 0, 'qty' => 23, 'expected' => 23],
274+
['step' => 10, 'qty' => 23.5, 'expected' => 20],
275+
['step' => 20, 'qty' => 33, 'expected' => 20],
276+
['step' => 25, 'qty' => 23, 'expected' => 0]
277+
];
278+
}
279+
}

app/code/Magento/SalesRule/Test/Unit/Model/Rule/Condition/Product/SubselectTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,25 @@ public function dataProviderForFixedBundleProduct(): array
249249
],
250250
false
251251
],
252+
'validate true for bundle product data with conditions for attribute base_row_total' =>
253+
[
254+
[
255+
'id' => 'attribute_set_id',
256+
'name' => 'base_row_total',
257+
'attributeScope' => 'frontend',
258+
'attributeOperator' => '=='
259+
],
260+
[
261+
'id'=> 1,
262+
'type' => ProductType::TYPE_BUNDLE,
263+
'qty' => 2,
264+
'price' => 100,
265+
'hasChildren' => true,
266+
'baseRowTotal' => 200,
267+
'valueParsed' => 200
268+
],
269+
false
270+
],
252271
'validate true for simple product data with conditions' =>
253272
[
254273
[

0 commit comments

Comments
 (0)