Skip to content

Commit 44d643a

Browse files
committed
Merge remote-tracking branch 'l3/MC-41343' into L3-PR-20210324
2 parents 9bb84b4 + 3e8e036 commit 44d643a

File tree

6 files changed

+646
-62
lines changed

6 files changed

+646
-62
lines changed

app/code/Magento/Quote/Model/Quote/Address/Total/Shipping.php

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,14 @@ public function collect(
7171
$address->setItemQty($data['addressQty']);
7272
$address->setWeight($data['addressWeight']);
7373
$address->setFreeMethodWeight($data['freeMethodWeight']);
74-
$addressFreeShipping = (bool)$address->getFreeShipping();
74+
7575
$isFreeShipping = $this->freeShipping->isFreeShipping($quote, $shippingAssignment->getItems());
7676
$address->setFreeShipping($isFreeShipping);
77-
if (!$addressFreeShipping && $isFreeShipping) {
78-
$data = $this->getAssignmentWeightData($address, $shippingAssignment->getItems());
79-
$address->setItemQty($data['addressQty']);
80-
$address->setWeight($data['addressWeight']);
81-
$address->setFreeMethodWeight($data['freeMethodWeight']);
82-
}
77+
// recalculate weights
78+
$data = $this->getAssignmentWeightData($address, $shippingAssignment->getItems());
79+
$address->setItemQty($data['addressQty']);
80+
$address->setWeight($data['addressWeight']);
81+
$address->setFreeMethodWeight($data['freeMethodWeight']);
8382

8483
$address->collectShippingRates();
8584

app/code/Magento/Shipping/Model/Carrier/AbstractCarrier.php

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,23 @@ public function getSortOrder()
404404
return $this->getConfigData('sort_order');
405405
}
406406

407+
/**
408+
* Check if the request has free shipping weight
409+
*
410+
* @param \Magento\Quote\Model\Quote\Address\RateRequest $request
411+
* @return bool
412+
*/
413+
private function hasFreeMethodWeight($request): bool
414+
{
415+
return (
416+
$request->getFreeShipping()
417+
|| (
418+
$request->hasFreeMethodWeight()
419+
&& ((float) $request->getFreeMethodWeight()) !== ((float) $request->getPackageWeight())
420+
)
421+
);
422+
}
423+
407424
/**
408425
* Allows free shipping when all product items have free shipping.
409426
*
@@ -414,10 +431,7 @@ public function getSortOrder()
414431
*/
415432
protected function _updateFreeMethodQuote($request)
416433
{
417-
if (!$request->getFreeShipping()) {
418-
return;
419-
}
420-
if ($request->getFreeMethodWeight() == $request->getPackageWeight() || !$request->hasFreeMethodWeight()) {
434+
if (!$this->hasFreeMethodWeight($request)) {
421435
return;
422436
}
423437

app/code/Magento/Usps/Test/Unit/Model/CarrierTest.php

Lines changed: 189 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Magento\Framework\HTTP\ZendClient;
1414
use Magento\Framework\HTTP\ZendClientFactory;
1515
use Magento\Framework\Locale\ResolverInterface;
16+
use Magento\Framework\Pricing\PriceCurrencyInterface;
1617
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
1718
use Magento\Framework\Xml\Security;
1819
use Magento\Quote\Model\Quote\Address\RateRequest;
@@ -22,6 +23,7 @@
2223
use Magento\Quote\Model\Quote\Address\RateResult\MethodFactory;
2324
use Magento\Shipping\Helper\Carrier as CarrierHelper;
2425
use Magento\Shipping\Model\Rate\Result;
26+
use Magento\Shipping\Model\Rate\Result\ProxyDeferredFactory;
2527
use Magento\Shipping\Model\Rate\ResultFactory;
2628
use Magento\Shipping\Model\Shipment\ReturnShipment;
2729
use Magento\Shipping\Model\Simplexml\Element;
@@ -76,6 +78,24 @@ class CarrierTest extends TestCase
7678
*/
7779
private $httpClient;
7880

81+
/**
82+
* @var MockObject
83+
*/
84+
private $proxyDeferredFactory;
85+
86+
/**
87+
* @var array
88+
*/
89+
private $config = [
90+
'carriers/usps/allowed_methods' => '0_FCLE,0_FCL,0_FCP,1,2,3,4,6,7,13,16,17,22,23,25,27,28,33,' .
91+
'34,35,36,37,42,43,53,55,56,57,61,INT_1,INT_2,INT_4,INT_6,INT_7,INT_8,INT_9,INT_10,INT_11,' .
92+
'INT_12,INT_13,INT_14,INT_15,INT_16,INT_20,INT_26',
93+
'carriers/usps/showmethod' => 1,
94+
'carriers/usps/debug' => 1,
95+
'carriers/usps/userid' => 'test',
96+
'carriers/usps/mode' => 0,
97+
];
98+
7999
/**
80100
* @inheritdoc
81101
*/
@@ -88,7 +108,10 @@ protected function setUp(): void
88108
->getMockForAbstractClass();
89109

90110
$this->scope->method('getValue')
91-
->willReturnCallback([$this, 'scopeConfiggetValue']);
111+
->willReturnCallback([$this, 'scopeConfigGetValue']);
112+
113+
$this->scope->method('isSetFlag')
114+
->willReturnCallback([$this, 'scopeIsSetFlag']);
92115

93116
$xmlElFactory = $this->getXmlFactory();
94117
$rateFactory = $this->getRateFactory();
@@ -110,7 +133,7 @@ protected function setUp(): void
110133

111134
$carrierHelper = $this->getCarrierHelper();
112135
$productCollectionFactory = $this->getProductCollectionFactory();
113-
136+
$this->proxyDeferredFactory = $this->createMock(ProxyDeferredFactory::class);
114137
$arguments = [
115138
'scopeConfig' => $this->scope,
116139
'xmlSecurity' => new Security(),
@@ -123,6 +146,7 @@ protected function setUp(): void
123146
'carrierHelper' => $carrierHelper,
124147
'productCollectionFactory' => $productCollectionFactory,
125148
'dataHelper' => $this->dataHelper,
149+
'proxyDeferredFactory' => $this->proxyDeferredFactory
126150
];
127151

128152
$this->dataHelper = $this->getMockBuilder(DataHelper::class)
@@ -197,17 +221,16 @@ public function testFormattingFloatValuesForIntlShipmentRequest()
197221
*/
198222
public function scopeConfigGetValue($path)
199223
{
200-
$pathMap = [
201-
'carriers/usps/allowed_methods' => '0_FCLE,0_FCL,0_FCP,1,2,3,4,6,7,13,16,17,22,23,25,27,28,33,' .
202-
'34,35,36,37,42,43,53,55,56,57,61,INT_1,INT_2,INT_4,INT_6,INT_7,INT_8,INT_9,INT_10,INT_11,' .
203-
'INT_12,INT_13,INT_14,INT_15,INT_16,INT_20,INT_26',
204-
'carriers/usps/showmethod' => 1,
205-
'carriers/usps/debug' => 1,
206-
'carriers/usps/userid' => 'test',
207-
'carriers/usps/mode' => 0,
208-
];
224+
return $this->config[$path] ?? null;
225+
}
209226

210-
return $pathMap[$path] ?? null;
227+
/**
228+
* @param $path
229+
* @return bool
230+
*/
231+
public function scopeIsSetFlag($path): bool
232+
{
233+
return !!$this->scopeConfigGetValue($path);
211234
}
212235

213236
/**
@@ -307,6 +330,160 @@ public function isGirthAllowedDataProvider()
307330
];
308331
}
309332

333+
/**
334+
* @param array $requestData
335+
* @param array $result1
336+
* @param array $result2
337+
* @param array $expected
338+
* @throws \ReflectionException
339+
* @dataProvider updateFreeMethodQuoteDataProvider
340+
*/
341+
public function testUpdateFreeMethodQuote(array $requestData, array $result1, array $result2, array $expected)
342+
{
343+
$this->config = array_merge(
344+
$this->config,
345+
[
346+
'carriers/usps/free_method' => 3
347+
]
348+
);
349+
$requestData = array_merge(
350+
[
351+
'orig_country_id' => 'US',
352+
'dest_country_id' => 'US'
353+
],
354+
$requestData
355+
);
356+
$this->proxyDeferredFactory
357+
->method('create')
358+
->willReturnOnConsecutiveCalls(
359+
$this->createResultMock($result1),
360+
$this->createResultMock($result2),
361+
);
362+
363+
$request = new RateRequest($requestData);
364+
$this->carrier->setRequest($request);
365+
$result = $this->invokeModelMethod('_getQuotes', [$request]);
366+
$this->setModelProperty('_result', $result);
367+
$this->invokeModelMethod('_updateFreeMethodQuote', [$request]);
368+
$rates = [];
369+
foreach ($this->carrier->getResult()->getAllRates() as $rate) {
370+
$rates[$rate->getMethod()] = $rate->getPrice();
371+
}
372+
$this->assertEquals($expected, $rates);
373+
}
374+
375+
public function updateFreeMethodQuoteDataProvider(): array
376+
{
377+
$result1 = [
378+
['method' => '1', 'method_title' => 'Priority Mail 3-Day', 'cost' => 70, 'price' => 70],
379+
['method' => '2', 'method_title' => 'Priority Mail 5-Day', 'cost' => 50, 'price' => 50],
380+
['method' => '3', 'method_title' => 'Priority Mail 7-Day', 'cost' => 30, 'price' => 30],
381+
];
382+
$result2 = [
383+
['method' => '1', 'method_title' => 'Priority Mail 3-Day', 'cost' => 70, 'price' => 35],
384+
['method' => '2', 'method_title' => 'Priority Mail 5-Day', 'cost' => 50, 'price' => 25],
385+
['method' => '3', 'method_title' => 'Priority Mail 7-Day', 'cost' => 30, 'price' => 15],
386+
];
387+
388+
return [
389+
[
390+
[
391+
'free_method_weight' => 10,
392+
'package_weight' => 10,
393+
'free_shipping' => false,
394+
],
395+
$result1,
396+
$result2,
397+
[
398+
'1' => 70,
399+
'2' => 50,
400+
'3' => 30,
401+
]
402+
],
403+
[
404+
[
405+
'free_method_weight' => 10,
406+
'package_weight' => 20,
407+
'free_shipping' => false,
408+
],
409+
$result1,
410+
$result2,
411+
[
412+
'1' => 70,
413+
'2' => 50,
414+
'3' => 15,
415+
]
416+
],
417+
[
418+
[
419+
'free_method_weight' => 0,
420+
'package_weight' => 10,
421+
'free_shipping' => true,
422+
],
423+
$result1,
424+
$result2,
425+
[
426+
'1' => 70,
427+
'2' => 50,
428+
'3' => 0,
429+
]
430+
]
431+
];
432+
}
433+
434+
/**
435+
* @param string $method
436+
* @param array $parameters
437+
* @return mixed
438+
* @throws \ReflectionException
439+
*/
440+
private function invokeModelMethod(string $method, array $parameters = [])
441+
{
442+
$reflection = new \ReflectionClass($this->carrier);
443+
$method = $reflection->getMethod($method);
444+
$method->setAccessible(true);
445+
446+
return $method->invokeArgs($this->carrier, $parameters);
447+
}
448+
449+
/**
450+
* @param string $property
451+
* @param mixed $value
452+
* @return void
453+
* @throws \ReflectionException
454+
*/
455+
private function setModelProperty(string $property, $value): void
456+
{
457+
$reflection = new \ReflectionClass($this->carrier);
458+
$property = $reflection->getProperty($property);
459+
$property->setAccessible(true);
460+
$property->setValue($this->carrier, $value);
461+
}
462+
463+
/**
464+
* @param array $rates
465+
* @return Result
466+
*/
467+
private function createResultMock(array $rates): Result
468+
{
469+
$result = $this->getMockBuilder(Result::class)
470+
->disableOriginalConstructor()
471+
->getMockForAbstractClass();
472+
473+
foreach ($rates as $rateData) {
474+
$price = $this->createMock(PriceCurrencyInterface::class);
475+
$price->method('round')
476+
->willReturnArgument(0);
477+
$rate = new Method(
478+
$price,
479+
$rateData + ['carrier' => 'usps', 'carrier_title' => 'USPS']
480+
);
481+
$result->append($rate);
482+
}
483+
484+
return $result;
485+
}
486+
310487
/**
311488
* @return MockObject
312489
*/

dev/tests/integration/framework/Magento/TestFramework/HTTP/AsyncClientInterfaceMock.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,10 @@ public function clearRequests()
9797
/**
9898
* Next responses will be as given.
9999
*
100-
* @param HttpResponseDeferredInterface $mockDeferredResponse
100+
* @param HttpResponseDeferredInterface|null $mockDeferredResponse
101101
* @return self
102102
*/
103-
public function setDeferredResponseMock(HttpResponseDeferredInterface $mockDeferredResponse): self
103+
public function setDeferredResponseMock(?HttpResponseDeferredInterface $mockDeferredResponse): self
104104
{
105105
$this->mockDeferredResponse = $mockDeferredResponse;
106106

0 commit comments

Comments
 (0)