Skip to content

Commit 39ce0e1

Browse files
MC-33737: Fedex response shows wrong "IntoCurrency"
1 parent e42ed8d commit 39ce0e1

File tree

3 files changed

+116
-24
lines changed

3 files changed

+116
-24
lines changed

app/code/Magento/Fedex/Model/Carrier.php

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
use Magento\Framework\App\ObjectManager;
1010
use Magento\Framework\DataObject;
11+
use Magento\Framework\Exception\LocalizedException;
1112
use Magento\Framework\Module\Dir;
1213
use Magento\Framework\Serialize\Serializer\Json;
1314
use Magento\Framework\Webapi\Soap\ClientFactory;
@@ -21,6 +22,7 @@
2122
*
2223
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
2324
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
25+
* @SuppressWarnings(PHPMD.TooManyFields)
2426
*/
2527
class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\Carrier\CarrierInterface
2628
{
@@ -149,6 +151,16 @@ class Carrier extends AbstractCarrierOnline implements \Magento\Shipping\Model\C
149151
*/
150152
private $soapClientFactory;
151153

154+
/**
155+
* @var array
156+
*/
157+
private $baseCurrencyRate;
158+
159+
/**
160+
* @var DataObject
161+
*/
162+
private $_rawTrackingRequest;
163+
152164
/**
153165
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
154166
* @param \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory
@@ -629,12 +641,13 @@ protected function _prepareRateResponse($response)
629641
protected function _getRateAmountOriginBased($rate)
630642
{
631643
$amount = null;
644+
$currencyCode = '';
632645
$rateTypeAmounts = [];
633-
634646
if (is_object($rate)) {
635647
// The "RATED..." rates are expressed in the currency of the origin country
636648
foreach ($rate->RatedShipmentDetails as $ratedShipmentDetail) {
637649
$netAmount = (string)$ratedShipmentDetail->ShipmentRateDetail->TotalNetCharge->Amount;
650+
$currencyCode = (string)$ratedShipmentDetail->ShipmentRateDetail->TotalNetCharge->Currency;
638651
$rateType = (string)$ratedShipmentDetail->ShipmentRateDetail->RateType;
639652
$rateTypeAmounts[$rateType] = $netAmount;
640653
}
@@ -649,11 +662,42 @@ protected function _getRateAmountOriginBased($rate)
649662
if ($amount === null) {
650663
$amount = (string)$rate->RatedShipmentDetails[0]->ShipmentRateDetail->TotalNetCharge->Amount;
651664
}
665+
666+
$amount = (float)$amount * $this->getBaseCurrencyRate($currencyCode);
652667
}
653668

654669
return $amount;
655670
}
656671

672+
/**
673+
* Returns base currency rate.
674+
*
675+
* @param string $currencyCode
676+
* @return float
677+
* @throws LocalizedException
678+
*/
679+
private function getBaseCurrencyRate(string $currencyCode): float
680+
{
681+
if (!isset($this->baseCurrencyRate[$currencyCode])) {
682+
$baseCurrencyCode = $this->_request->getBaseCurrency()->getCode();
683+
$rate = $this->_currencyFactory->create()
684+
->load($currencyCode)
685+
->getAnyRate($baseCurrencyCode);
686+
if ($rate === false) {
687+
$errorMessage = __(
688+
'Can\'t convert a shipping cost from "%1-%2" for FedEx carrier.',
689+
$currencyCode,
690+
$baseCurrencyCode
691+
);
692+
$this->_logger->critical($errorMessage);
693+
throw new LocalizedException($errorMessage);
694+
}
695+
$this->baseCurrencyRate[$currencyCode] = (float)$rate;
696+
}
697+
698+
return $this->baseCurrencyRate[$currencyCode];
699+
}
700+
657701
/**
658702
* Set free method request
659703
*
@@ -726,9 +770,8 @@ protected function _getXmlQuotes()
726770
$debugData = ['request' => $this->filterDebugData($request)];
727771
try {
728772
$url = $this->getConfigData('gateway_url');
729-
if (!$url) {
730-
$url = $this->_defaultGatewayUrl;
731-
}
773+
774+
// phpcs:disable Magento2.Functions.DiscouragedFunction
732775
$ch = curl_init();
733776
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
734777
curl_setopt($ch, CURLOPT_URL, $url);
@@ -737,6 +780,7 @@ protected function _getXmlQuotes()
737780
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
738781
$responseBody = curl_exec($ch);
739782
curl_close($ch);
783+
// phpcs:enable
740784

741785
$debugData['result'] = $this->filterDebugData($responseBody);
742786
$this->_setCachedQuotes($request, $responseBody);

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

Lines changed: 67 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
use Magento\Directory\Helper\Data;
1111
use Magento\Directory\Model\Country;
1212
use Magento\Directory\Model\CountryFactory;
13+
use Magento\Directory\Model\Currency;
1314
use Magento\Directory\Model\CurrencyFactory;
1415
use Magento\Directory\Model\RegionFactory;
1516
use Magento\Fedex\Model\Carrier;
1617
use Magento\Framework\App\Config\ScopeConfigInterface;
18+
use Magento\Framework\Exception\LocalizedException;
1719
use Magento\Framework\Module\Dir\Reader;
1820
use Magento\Framework\Pricing\PriceCurrencyInterface;
1921
use Magento\Framework\Serialize\Serializer\Json;
@@ -100,6 +102,11 @@ class CarrierTest extends \PHPUnit\Framework\TestCase
100102
*/
101103
private $logger;
102104

105+
/**
106+
* @var CurrencyFactory|MockObject
107+
*/
108+
private $currencyFactory;
109+
103110
protected function setUp()
104111
{
105112
$this->helper = new ObjectManager($this);
@@ -141,7 +148,7 @@ protected function setUp()
141148
->disableOriginalConstructor()
142149
->getMock();
143150

144-
$currencyFactory = $this->getMockBuilder(CurrencyFactory::class)
151+
$this->currencyFactory = $this->getMockBuilder(CurrencyFactory::class)
145152
->disableOriginalConstructor()
146153
->getMock();
147154

@@ -179,7 +186,7 @@ protected function setUp()
179186
'trackStatusFactory' => $this->statusFactory,
180187
'regionFactory' => $regionFactory,
181188
'countryFactory' => $countryFactory,
182-
'currencyFactory' => $currencyFactory,
189+
'currencyFactory' => $this->currencyFactory,
183190
'directoryData' => $data,
184191
'stockRegistry' => $stockRegistry,
185192
'storeManager' => $storeManager,
@@ -240,20 +247,29 @@ public function scopeConfigGetValue(string $path)
240247

241248
/**
242249
* @param float $amount
250+
* @param string $currencyCode
251+
* @param string $baseCurrencyCode
243252
* @param string $rateType
244253
* @param float $expected
245254
* @param int $callNum
246255
* @dataProvider collectRatesDataProvider
247256
*/
248-
public function testCollectRatesRateAmountOriginBased($amount, $rateType, $expected, $callNum = 1)
249-
{
257+
public function testCollectRatesRateAmountOriginBased(
258+
$amount,
259+
$currencyCode,
260+
$baseCurrencyCode,
261+
$rateType,
262+
$expected,
263+
$callNum = 1
264+
) {
250265
$this->scope->expects($this->any())
251266
->method('isSetFlag')
252267
->willReturn(true);
253268

254269
// @codingStandardsIgnoreStart
255270
$netAmount = new \stdClass();
256271
$netAmount->Amount = $amount;
272+
$netAmount->Currency = $currencyCode;
257273

258274
$totalNetCharge = new \stdClass();
259275
$totalNetCharge->TotalNetCharge = $netAmount;
@@ -274,9 +290,39 @@ public function testCollectRatesRateAmountOriginBased($amount, $rateType, $expec
274290
$this->serializer->method('serialize')
275291
->willReturn('CollectRateString' . $amount);
276292

293+
$rateCurrency = $this->getMockBuilder(Currency::class)
294+
->disableOriginalConstructor()
295+
->getMock();
296+
$rateCurrency->method('load')
297+
->willReturnSelf();
298+
$rateCurrency->method('getAnyRate')
299+
->willReturnMap(
300+
[
301+
['USD', 1],
302+
['EUR', 0.75],
303+
['UNKNOWN', false]
304+
]
305+
);
306+
307+
if ($baseCurrencyCode === 'UNKNOWN') {
308+
$this->expectException(LocalizedException::class);
309+
}
310+
311+
$this->currencyFactory->method('create')
312+
->willReturn($rateCurrency);
313+
314+
$baseCurrency = $this->getMockBuilder(Currency::class)
315+
->disableOriginalConstructor()
316+
->getMock();
317+
$baseCurrency->method('getCode')
318+
->willReturn($baseCurrencyCode);
319+
277320
$request = $this->getMockBuilder(RateRequest::class)
321+
->setMethods(['getBaseCurrency'])
278322
->disableOriginalConstructor()
279323
->getMock();
324+
$request->method('getBaseCurrency')
325+
->willReturn($baseCurrency);
280326

281327
$this->soapClient->expects($this->exactly($callNum))
282328
->method('getRates')
@@ -295,22 +341,23 @@ public function testCollectRatesRateAmountOriginBased($amount, $rateType, $expec
295341
public function collectRatesDataProvider()
296342
{
297343
return [
298-
[10.0, 'RATED_ACCOUNT_PACKAGE', 10],
299-
[10.0, 'RATED_ACCOUNT_PACKAGE', 10, 0],
300-
[11.50, 'PAYOR_ACCOUNT_PACKAGE', 11.5],
301-
[11.50, 'PAYOR_ACCOUNT_PACKAGE', 11.5, 0],
302-
[100.01, 'RATED_ACCOUNT_SHIPMENT', 100.01],
303-
[100.01, 'RATED_ACCOUNT_SHIPMENT', 100.01, 0],
304-
[32.2, 'PAYOR_ACCOUNT_SHIPMENT', 32.2],
305-
[32.2, 'PAYOR_ACCOUNT_SHIPMENT', 32.2, 0],
306-
[15.0, 'RATED_LIST_PACKAGE', 15],
307-
[15.0, 'RATED_LIST_PACKAGE', 15, 0],
308-
[123.25, 'PAYOR_LIST_PACKAGE', 123.25],
309-
[123.25, 'PAYOR_LIST_PACKAGE', 123.25, 0],
310-
[12.12, 'RATED_LIST_SHIPMENT', 12.12],
311-
[12.12, 'RATED_LIST_SHIPMENT', 12.12, 0],
312-
[38.9, 'PAYOR_LIST_SHIPMENT', 38.9],
313-
[38.9, 'PAYOR_LIST_SHIPMENT', 38.9, 0],
344+
[10.0, 'USD', 'EUR', 'RATED_ACCOUNT_PACKAGE', 7.5],
345+
[10.0, 'USD', 'UNKNOWN', 'RATED_ACCOUNT_PACKAGE', null, 0],
346+
[10.0, 'USD', 'USD', 'RATED_ACCOUNT_PACKAGE', 10, 0],
347+
[11.50, 'USD', 'USD', 'PAYOR_ACCOUNT_PACKAGE', 11.5],
348+
[11.50, 'USD', 'USD', 'PAYOR_ACCOUNT_PACKAGE', 11.5, 0],
349+
[100.01, 'USD', 'USD', 'RATED_ACCOUNT_SHIPMENT', 100.01],
350+
[100.01, 'USD', 'USD', 'RATED_ACCOUNT_SHIPMENT', 100.01, 0],
351+
[32.2, 'USD', 'USD', 'PAYOR_ACCOUNT_SHIPMENT', 32.2],
352+
[32.2, 'USD', 'USD', 'PAYOR_ACCOUNT_SHIPMENT', 32.2, 0],
353+
[15.0, 'USD', 'USD', 'RATED_LIST_PACKAGE', 15],
354+
[15.0, 'USD', 'USD', 'RATED_LIST_PACKAGE', 15, 0],
355+
[123.25, 'USD', 'USD', 'PAYOR_LIST_PACKAGE', 123.25],
356+
[123.25, 'USD', 'USD', 'PAYOR_LIST_PACKAGE', 123.25, 0],
357+
[12.12, 'USD', 'USD', 'RATED_LIST_SHIPMENT', 12.12],
358+
[12.12, 'USD', 'USD', 'RATED_LIST_SHIPMENT', 12.12, 0],
359+
[38.9, 'USD', 'USD', 'PAYOR_LIST_SHIPMENT', 38.9],
360+
[38.9, 'USD', 'USD', 'PAYOR_LIST_SHIPMENT', 38.9, 0],
314361
];
315362
}
316363

app/code/Magento/Fedex/i18n/en_US.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,4 @@ Dropoff,Dropoff
7777
Debug,Debug
7878
"Show Method if Not Applicable","Show Method if Not Applicable"
7979
"Sort Order","Sort Order"
80+
"Can't convert a shipping cost from ""%1-%2"" for FedEx carrier.","Can't convert a shipping cost from ""%1-%2"" for FedEx carrier."

0 commit comments

Comments
 (0)