****Note: This is setup for a single currency exchange rate for a single day. You can get averages over multiple days using the 'Candles' request instead of the 'Candle'
Classes\ExchangeRateProviderOanda\classDeclaration
Line 2 Original Code:
ExchangeRateProviderIdAttribute('CB024E9B-312B-44CE-BE89-3ED8597B007D')
Change To:
ExchangeRateProviderIdAttribute('CreateNew')
Create your own, unique GUID. You can do this in a Job in ax with the following code:
info(strFmt("%1", WinAPI::createGUID()));
Classes\ExchangeRateProviderOanda\classDeclaration
Lines 21 & 22 Original Code:
#define.BidXPath("//bid")
#define.DateXPath("//quote/date")
Change To:
#define.BidXPath("//average_bid")
#define.DateXPath("//quote/close_time")
These will get us the right xml nodes for the 'Bid' exchange rate and the quote date.Classes\ExchangeRateProviderOanda\getProviderId
Change To:
return 'YourNewlyCreatedGuid';
Copy your new GUID from above.
Classes\ExchangeRateProviderOanda\getConfigurationDefaults
Line 5 Original Code:
configurationDefaults.addNameValueConfigurationPair(#ServiceURL, 'https://www.oanda.com/rates/api/v1/rates/%1.xml?quote=%2&start=%3&end=%4&fields=averages');
Change To:
configurationDefaults.addNameValueConfigurationPair(#ServiceURL, 'https://www.oanda.com/rates/api/v2/rates/candle.xml?base=%1"e=%2&date_time=%3');
This is the V2 URL for the 'Candle' rate type.
Lines 41 & 42 Original Code:
fromDate = _exchangeRateRequest.parmFromDate();
compareResult = fromDate.CompareTo(_exchangeRateRequest.parmToDate());
Change To:
fromDate = _exchangeRateRequest.parmFromDate();
compareResult = fromDate.CompareTo(fromDate);
The 'CompareTo' method can't handle the 'Date' type in 'parmFromDate'. In essence, it was simply trying to compare the date to iteslf so I passed the 'fromDate' variable instead.
Classes\ExchangeRateProviderOanda\getExchangeRates
Line 61 Original Code:
oandaRequestString = strFmt(serviceUrl,currencyPairRequest.parmFromCurrency(), currencyPairRequest.parmToCurrency(), dateForRequest, dateForRequest);
Change To:
oandaRequestString = strFmt(serviceUrl, currencyPairRequest.parmFromCurrency(), currencyPairRequest.parmToCurrency(), dateForRequest);
This changes our 'oandaRequestString' to use the new url format and put the variables in the right spots.
Classes\ExchangeRateProviderOanda\getExchangeRates
Line 18 Original Code:
System.DateTime fromDate, fromUTCDate;
Change To:
System.DateTime fromDate, fromUTCDate, toDateDateTime;
This is needed for our next fix.
Classes\ExchangeRateProviderOanda\getExchangeRates
Lines 118 & 119 Original Code:
fromDate = fromDate.AddDays(1);
compareResult = fromDate.CompareTo(_exchangeRateRequest.parmToDate());
Change To:
fromDate = fromDate.AddDays(1);
toDateDateTime = _exchangeRateRequest.parmToDate();
compareResult = fromDate.CompareTo(toDateDateTime);
Similar to the issue above. The 'CompareTo' can't handle the 'Date' type in 'parmToDate'. We created a new 'System.DateTime' variable called toDateDateTime and then set that variable to the 'parmToDate()'. We can then pass this variable to the 'CompareTo' method.
Classes\ExchangeRateProviderOanda\getExchangeRates
Line 71
//webCollection.Add(#HttpHeaderAuthorization, #KeyTokenPrefix + TODO: Retrieve and concatenate your Key provided by OANDA);
Change To:
webCollection.Add(#HttpHeaderAuthorization, #KeyTokenPrefix + 'YourApiKey');
Put your OANDA provided API key here.
OPTIONAL:
Classes\ExchangeRateProviderOanda\getExchangeRates
Line 102 Original Code:
catch (Exception::CLRError)
{
{Comments}
}
Change To
catch (Exception::CLRError)
{
ex = CLRInterop::getLastException();
if (ex != null)
{
ex = ex.get_InnerException();
if (ex != null)
{
error(strFmt("From Currency:%1 - To Currency: %2 - Date: %3", currencyPairRequest.parmFromCurrency(),
currencyPairRequest.parmToCurrency(), oandaRequestString));
}
}
}
I just put in some error handling so that if my batch job errors out, I will be able to see some details.
Once you do this, compile into CIL. Then create your new provider through GL -> Setup -> Currency -> Configure exchange rate providers
Then run Gl -> Periodic -> Import currency exchange rates:
This will create exchange rates for Today for all currency pairs that you have in the system.
****Note: Daily exchange rates are posted at 0:00 UTC. For us in the US that means I can get the March 31 rate at 5:00 pm PT or 8:00 pm ET March 31. If you try and get a 'Candle' rate before then, your web api call will fail.
And that's it! This could easily be setup as a batch job and wouldn't require further intervention. Not a hard way to get exchange rates automatically pulled in to AX.