From 32ca0849f84494c92769b22ae49017ff6f826ea8 Mon Sep 17 00:00:00 2001 From: Antonio Buznego Date: Fri, 27 Dec 2024 20:33:26 +0100 Subject: [PATCH] Retrieves rates from CNB API and converts it --- jobs/Backend/Task/ExchangeRateProvider.cs | 80 ++++++++++++++++++- jobs/Backend/Task/ExchangeRateUpdater.csproj | 4 + jobs/Backend/Task/Models/ExchangeRateApi.cs | 22 +++++ jobs/Backend/Task/Models/ExchangeRatesList.cs | 16 ++++ jobs/Backend/Task/Program.cs | 4 +- jobs/Backend/Task/RateConverter.cs | 15 ++++ 6 files changed, 137 insertions(+), 4 deletions(-) create mode 100644 jobs/Backend/Task/Models/ExchangeRateApi.cs create mode 100644 jobs/Backend/Task/Models/ExchangeRatesList.cs create mode 100644 jobs/Backend/Task/RateConverter.cs diff --git a/jobs/Backend/Task/ExchangeRateProvider.cs b/jobs/Backend/Task/ExchangeRateProvider.cs index 6f82a97fb..31f1ba503 100644 --- a/jobs/Backend/Task/ExchangeRateProvider.cs +++ b/jobs/Backend/Task/ExchangeRateProvider.cs @@ -1,5 +1,11 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; +using System.Net.Http.Headers; +using System.Net.Http; +using System.Threading.Tasks; +using Newtonsoft.Json; +using ExchangeRateUpdater.Models; namespace ExchangeRateUpdater { @@ -11,9 +17,77 @@ public class ExchangeRateProvider /// do not return exchange rate "USD/CZK" with value calculated as 1 / "CZK/USD". If the source does not provide /// some of the currencies, ignore them. /// - public IEnumerable GetExchangeRates(IEnumerable currencies) + public IEnumerable GetExchangeRates(IEnumerable currencies, Currency baseCurrency) { - return Enumerable.Empty(); + var exchangeRates = new List(); + + // Created two different calls to exemplify how API can change individually, despite being right now, returning the data in the same format + var ratesDaily = GetExchangeRatesDailyAsync(currencies).Result; + var ratesForex = GetExchangeRatesForexAsync(currencies).Result; + + // Conversion should be one or two different depending on what is done with the API calls. In this case, for simplicity, I've done one single converter + exchangeRates.AddRange(RateConverter.ConvertApiToExchangeRate(ratesDaily, baseCurrency)); + exchangeRates.AddRange(RateConverter.ConvertApiToExchangeRate(ratesForex, baseCurrency)); + + return exchangeRates; + } + + private async Task> GetExchangeRatesDailyAsync(IEnumerable currencies) + { + var exchangeRates = new List(); + + var dayDate = DateTime.Now.ToString("yyyy-MM-dd"); + + var urlApi = $"https://api.cnb.cz/cnbapi/exrates/daily"; + var parametersApi = $"?date={dayDate}"; + + HttpClient client = new HttpClient(); + client.BaseAddress = new Uri(urlApi); + client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + + HttpResponseMessage response = await client.GetAsync(parametersApi).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var jsonString = await response.Content.ReadAsStringAsync(); + var ratesList = JsonConvert.DeserializeObject(jsonString); + + if (ratesList != null) + { + exchangeRates.AddRange(ratesList.Rates.Where(e => currencies.Any(c => c.Code == e.CurrencyCode))); + } + } + + return exchangeRates; + } + + private async Task> GetExchangeRatesForexAsync(IEnumerable currencies) + { + var exchangeRates = new List(); + + var monthDate = DateTime.Now.AddMonths(-1).ToString("yyyy-MM"); + + var urlApi = $"https://api.cnb.cz/cnbapi/fxrates/daily-month"; + var parametersApi = $"?yearMonth={monthDate}"; + + HttpClient client = new HttpClient(); + client.BaseAddress = new Uri(urlApi); + client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + + HttpResponseMessage response = await client.GetAsync(parametersApi).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var jsonString = await response.Content.ReadAsStringAsync(); + var ratesList = JsonConvert.DeserializeObject(jsonString); + + if (ratesList != null) + { + exchangeRates.AddRange(ratesList.Rates.Where(e => currencies.Any(c => c.Code == e.CurrencyCode))); + } + } + + return exchangeRates; } } } diff --git a/jobs/Backend/Task/ExchangeRateUpdater.csproj b/jobs/Backend/Task/ExchangeRateUpdater.csproj index 2fc654a12..e651e76c1 100644 --- a/jobs/Backend/Task/ExchangeRateUpdater.csproj +++ b/jobs/Backend/Task/ExchangeRateUpdater.csproj @@ -5,4 +5,8 @@ net6.0 + + + + \ No newline at end of file diff --git a/jobs/Backend/Task/Models/ExchangeRateApi.cs b/jobs/Backend/Task/Models/ExchangeRateApi.cs new file mode 100644 index 000000000..9276da2e2 --- /dev/null +++ b/jobs/Backend/Task/Models/ExchangeRateApi.cs @@ -0,0 +1,22 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ExchangeRateUpdater.Models +{ + [Serializable] + public class ExchangeRateApi + { + [JsonProperty("currencyCode")] + public string CurrencyCode { get; set; } + + [JsonProperty("rate")] + public decimal Rate { get; set; } + + [JsonProperty("amount")] + public decimal Amount { get; set; } + } +} diff --git a/jobs/Backend/Task/Models/ExchangeRatesList.cs b/jobs/Backend/Task/Models/ExchangeRatesList.cs new file mode 100644 index 000000000..d00329d4c --- /dev/null +++ b/jobs/Backend/Task/Models/ExchangeRatesList.cs @@ -0,0 +1,16 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ExchangeRateUpdater.Models +{ + [Serializable] + public class ExchangeRatesList + { + [JsonProperty("rates")] + public IEnumerable Rates { get; set; } + } +} diff --git a/jobs/Backend/Task/Program.cs b/jobs/Backend/Task/Program.cs index 379a69b1f..e66870287 100644 --- a/jobs/Backend/Task/Program.cs +++ b/jobs/Backend/Task/Program.cs @@ -19,12 +19,14 @@ public static class Program new Currency("XYZ") }; + public static Currency baseCurrency = new Currency("CZK"); + public static void Main(string[] args) { try { var provider = new ExchangeRateProvider(); - var rates = provider.GetExchangeRates(currencies); + var rates = provider.GetExchangeRates(currencies, baseCurrency); Console.WriteLine($"Successfully retrieved {rates.Count()} exchange rates:"); foreach (var rate in rates) diff --git a/jobs/Backend/Task/RateConverter.cs b/jobs/Backend/Task/RateConverter.cs new file mode 100644 index 000000000..444b53a7a --- /dev/null +++ b/jobs/Backend/Task/RateConverter.cs @@ -0,0 +1,15 @@ +using ExchangeRateUpdater.Models; +using System.Collections.Generic; +using System.Linq; + +namespace ExchangeRateUpdater +{ + internal static class RateConverter + { + // Convert from ExchangeRateApi to ExchangeRate + public static IEnumerable ConvertApiToExchangeRate(IEnumerable ratesApi, Currency baseCurrency) + { + return ratesApi.Select(c => new ExchangeRate(new Currency(c.CurrencyCode), baseCurrency, c.Rate / c.Amount)); + } + } +}