diff --git a/jobs/Backend/Task/Currency.cs b/jobs/Backend/Task/Currency.cs
deleted file mode 100644
index f375776f2..000000000
--- a/jobs/Backend/Task/Currency.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-namespace ExchangeRateUpdater
-{
- public class Currency
- {
- public Currency(string code)
- {
- Code = code;
- }
-
- ///
- /// Three-letter ISO 4217 code of the currency.
- ///
- public string Code { get; }
-
- public override string ToString()
- {
- return Code;
- }
- }
-}
diff --git a/jobs/Backend/Task/ExchangeRate.cs b/jobs/Backend/Task/ExchangeRate.cs
deleted file mode 100644
index 58c5bb10e..000000000
--- a/jobs/Backend/Task/ExchangeRate.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-namespace ExchangeRateUpdater
-{
- public class ExchangeRate
- {
- public ExchangeRate(Currency sourceCurrency, Currency targetCurrency, decimal value)
- {
- SourceCurrency = sourceCurrency;
- TargetCurrency = targetCurrency;
- Value = value;
- }
-
- public Currency SourceCurrency { get; }
-
- public Currency TargetCurrency { get; }
-
- public decimal Value { get; }
-
- public override string ToString()
- {
- return $"{SourceCurrency}/{TargetCurrency}={Value}";
- }
- }
-}
diff --git a/jobs/Backend/Task/ExchangeRateProvider.cs b/jobs/Backend/Task/ExchangeRateProvider.cs
deleted file mode 100644
index 6f82a97fb..000000000
--- a/jobs/Backend/Task/ExchangeRateProvider.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-
-namespace ExchangeRateUpdater
-{
- public class ExchangeRateProvider
- {
- ///
- /// Should return exchange rates among the specified currencies that are defined by the source. But only those defined
- /// by the source, do not return calculated exchange rates. E.g. if the source contains "CZK/USD" but not "USD/CZK",
- /// 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)
- {
- return Enumerable.Empty();
- }
- }
-}
diff --git a/jobs/Backend/Task/ExchangeRateUpdater.csproj b/jobs/Backend/Task/ExchangeRateUpdater.csproj
deleted file mode 100644
index 2fc654a12..000000000
--- a/jobs/Backend/Task/ExchangeRateUpdater.csproj
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
- Exe
- net6.0
-
-
-
\ No newline at end of file
diff --git a/jobs/Backend/Task/ExchangeRateUpdater.sln b/jobs/Backend/Task/ExchangeRateUpdater.sln
deleted file mode 100644
index 89be84daf..000000000
--- a/jobs/Backend/Task/ExchangeRateUpdater.sln
+++ /dev/null
@@ -1,22 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-VisualStudioVersion = 14.0.25123.0
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExchangeRateUpdater", "ExchangeRateUpdater.csproj", "{7B2695D6-D24C-4460-A58E-A10F08550CE0}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {7B2695D6-D24C-4460-A58E-A10F08550CE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {7B2695D6-D24C-4460-A58E-A10F08550CE0}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {7B2695D6-D24C-4460-A58E-A10F08550CE0}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {7B2695D6-D24C-4460-A58E-A10F08550CE0}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/.gitignore b/jobs/Backend/Task/ExchangeRateUpdater/.gitignore
new file mode 100644
index 000000000..440219560
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/.gitignore
@@ -0,0 +1,49 @@
+# Archivos de sistema operativo
+.DS_Store
+Thumbs.db
+
+# Configuración de Visual Studio
+.vs/
+*.vcxproj.user
+*.suo
+*.user
+*.sln.docstates
+
+# Carpetas de compilación y temporales
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Dd]ebug*/
+[Rr]elease*/
+x64/
+x86/
+[Aa]rm/
+[Aa]rm64/
+*.log
+*.tmp
+
+# Archivos de paquetes y dependencias
+packages/
+*.nupkg
+project.lock.json
+project.fragment.lock.json
+
+# Archivos de publicación
+*.publishsettings
+*.azurePubxml
+*.azurePubxml.user
+
+# Configuración de IDEs
+.idea/
+.vscode/
+
+# Archivos de pruebas
+TestResults/
+*.trx
+*.coverage
+
+# Archivos sensibles
+*.config
+*.env
+*.key
+*.pem
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Business/ExchangeRateUpdater.Business.csproj b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Business/ExchangeRateUpdater.Business.csproj
new file mode 100644
index 000000000..ee753b73e
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Business/ExchangeRateUpdater.Business.csproj
@@ -0,0 +1,18 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Business/Interfaces/IExchangeRateService.cs b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Business/Interfaces/IExchangeRateService.cs
new file mode 100644
index 000000000..3e9c502b9
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Business/Interfaces/IExchangeRateService.cs
@@ -0,0 +1,8 @@
+using ExchangeRateUpdater.Data.Responses;
+using ExchangeRateUpdater.Models.Requests;
+
+namespace ExchangeRateUpdater.Business.Interfaces;
+public interface IExchangeRateService
+{
+ Task> GetExchangeRates(IEnumerable currencies, DateTime date, CancellationToken cancellationToken);
+}
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Business/Services/ExchangeRateService.cs b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Business/Services/ExchangeRateService.cs
new file mode 100644
index 000000000..f223571e0
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Business/Services/ExchangeRateService.cs
@@ -0,0 +1,43 @@
+using ExchangeRateUpdater.Models.Requests;
+using ExchangeRateUpdater.Data.Interfaces;
+using ExchangeRateUpdater.Data.Responses;
+using ExchangeRateUpdater.Business.Interfaces;
+using ExchangeRateUpdater.Models.Models;
+using Microsoft.Extensions.Logging;
+
+namespace ExchangeRateUpdater.Business.Services;
+public class ExchangeRateService : IExchangeRateService
+{
+ private readonly IExchangeRateRepository _exchangeRatesRepository;
+ private readonly ILogger _logger;
+ public ExchangeRateService(IExchangeRateRepository exchangeRatesRepository, ILogger logger)
+ {
+ _exchangeRatesRepository = exchangeRatesRepository;
+ _logger = logger;
+ }
+ public async Task> GetExchangeRates(IEnumerable currencies, DateTime date, CancellationToken cancellationToken)
+ {
+ var exchangeRatesByCurrency = new List();
+
+ //Get all the rates for a specified date
+ var exchangeRates = await _exchangeRatesRepository.GetExchangeRatesByDateAsync(date, cancellationToken);
+
+ //Get only the requested ones
+ var requestedExchangeRates = exchangeRates.Where(p => currencies
+ .Any(e => e.ToString() == p.ToString()))
+ .ToList();
+
+ _logger.LogInformation($"{requestedExchangeRates.Count}/{currencies.ToList().Count} exchange rate(s) have been obtained.");
+ //Map to a new object that simplifies reading the response
+ return requestedExchangeRates.Select(rate => MapToResult(rate)).ToList();
+ }
+
+ private ExchangeRateResultDto MapToResult(ExchangeRate rate)
+ {
+ return new ExchangeRateResultDto(
+ new Currency(rate.SourceCurrency.Code),
+ new Currency(rate.TargetCurrency.Code),
+ rate.Value,
+ rate.Date);
+ }
+}
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/ExchangeRateUpdater.Data.csproj b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/ExchangeRateUpdater.Data.csproj
new file mode 100644
index 000000000..49bfa6c4d
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/ExchangeRateUpdater.Data.csproj
@@ -0,0 +1,23 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Interfaces/IExchangeRateCacheRepository.cs b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Interfaces/IExchangeRateCacheRepository.cs
new file mode 100644
index 000000000..2c85cdc18
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Interfaces/IExchangeRateCacheRepository.cs
@@ -0,0 +1,9 @@
+
+using ExchangeRateUpdater.Data.Responses;
+
+namespace ExchangeRateUpdater.Data.Interfaces;
+public interface IExchangeRateCacheRepository
+{
+ ExchangeRatesResponseDto GetExchangeRates(DateTime date);
+ void SetExchangeRates(ExchangeRatesResponseDto rates);
+}
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Interfaces/IExchangeRateRepository.cs b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Interfaces/IExchangeRateRepository.cs
new file mode 100644
index 000000000..b0a6f4eb1
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Interfaces/IExchangeRateRepository.cs
@@ -0,0 +1,8 @@
+
+using ExchangeRateUpdater.Data.Responses;
+
+namespace ExchangeRateUpdater.Data.Interfaces;
+public interface IExchangeRateRepository
+{
+ Task> GetExchangeRatesByDateAsync(DateTime date, CancellationToken cancellationToken);
+}
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Repositories/ExchangeRateCacheRepository.cs b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Repositories/ExchangeRateCacheRepository.cs
new file mode 100644
index 000000000..a3daf9210
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Repositories/ExchangeRateCacheRepository.cs
@@ -0,0 +1,60 @@
+using ExchangeRateUpdater.Data.Interfaces;
+using ExchangeRateUpdater.Data.Responses;
+using Microsoft.Extensions.Caching.Memory;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
+
+
+namespace ExchangeRateUpdater.Data.Repositories;
+public class ExchangeRateCacheRepository : IExchangeRateCacheRepository
+{
+ private readonly IMemoryCache _cache;
+ private readonly ILogger _logger;
+
+ public ExchangeRateCacheRepository(IMemoryCache cache, ILogger logger)
+ {
+ _cache = cache;
+ _logger = logger;
+ }
+
+ public ExchangeRatesResponseDto GetExchangeRates(DateTime date)
+ {
+ var result = new ExchangeRatesResponseDto() { Rates = new List()};
+ var key = date.ToString("yyyy-MM-dd");
+
+ if (_cache.TryGetValue(key, out ExchangeRatesResponseDto ratesCached))
+ {
+ _logger.LogInformation($"{ratesCached.Rates.Count} retrieved from cache");
+ result.Rates = ratesCached.Rates.Where(t => t.ValidFor == date).ToList();
+ }
+
+ return result;
+ }
+
+ public void SetExchangeRates(ExchangeRatesResponseDto rates)
+ {
+ try
+ {
+ var cacheEntryOptions = new MemoryCacheEntryOptions()
+ .SetAbsoluteExpiration(TimeSpan.FromDays(1)); //Keep cache for 1 day max
+
+ //Since weekends there's no rates and the api always returns the las data avaiable,
+ //the rates in cache have the actual date and not the requested
+ var key = rates.Rates[0].ValidFor.ToString("yyyy-MM-dd");
+
+ if (!_cache.TryGetValue(key, out _))
+ {
+ _logger.LogInformation($"{rates.Rates.Count} have been saved on cache");
+ _cache.Set(key, rates, cacheEntryOptions);
+ }
+
+
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex.Message);
+ throw new Exception($"There was an error while saving in cache. Error: {ex.Message}");
+ }
+ }
+}
+
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Repositories/ExchangeRateRepository.cs b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Repositories/ExchangeRateRepository.cs
new file mode 100644
index 000000000..078ddfc33
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Repositories/ExchangeRateRepository.cs
@@ -0,0 +1,86 @@
+using ExchangeRateUpdater.Data.Interfaces;
+using ExchangeRateUpdater.Data.Responses;
+using ExchangeRateUpdater.Models.Models;
+using Flurl;
+using Flurl.Http;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
+
+namespace ExchangeRateUpdater.Data.Repositories;
+public class ExchangeRateRepository : IExchangeRateRepository
+{
+ private readonly IConfiguration _configuration;
+ private readonly IExchangeRateCacheRepository _cacheRepository; // Instancia de IMemoryCache
+ private readonly ILogger _logger;
+
+ public ExchangeRateRepository(IConfiguration configuration, IExchangeRateCacheRepository cacheRepository, ILogger logger)
+ {
+ _configuration = configuration;
+ _cacheRepository = cacheRepository;
+ _logger = logger;
+ }
+ public async Task> GetExchangeRatesByDateAsync(DateTime date, CancellationToken cancellationToken)
+ {
+ ExchangeRatesResponseDto? exchangeRates;
+
+ // Try get exchange rates from caché first
+ exchangeRates = _cacheRepository.GetExchangeRates(date);
+
+ //If no results from cache, get the data from the client
+ if (!exchangeRates.Rates.Any())
+ {
+ exchangeRates = await GetExchangeRates(date, cancellationToken);
+
+ //Set the data in cache
+ _cacheRepository.SetExchangeRates(exchangeRates);
+ }
+
+ var result = exchangeRates.Rates.Select(rate => MapToExchangeRate(rate)).ToList();
+
+ return result;
+ }
+
+ private async Task GetExchangeRates(DateTime date, CancellationToken cancellationToken)
+ {
+ var resul = new ExchangeRatesResponseDto();
+
+ try
+ {
+ using (var httpClient = new HttpClient())
+ {
+ if (string.IsNullOrEmpty(_configuration["ExchangeRateUrl"]))
+ {
+ _logger.LogError("Czech National Bank Url not defined.");
+ throw new ApplicationException("Czech National Bank Url not defined.");
+ }
+
+ string baseUrl = _configuration["ExchangeRateUrl"] ;
+
+ resul = await baseUrl
+ .SetQueryParams(new
+ {
+ date = date.ToString("yyyy-MM-dd"),
+ lang = "EN"
+ })
+ .GetJsonAsync();
+ }
+ }
+ catch (FlurlHttpException ex)
+ {
+ _logger.LogError(ex.Message);
+ throw new ApplicationException(ex.Message);
+ }
+
+ _logger.LogInformation($"{resul.Rates.Count} exchange rates have been obtained.");
+ return resul;
+ }
+
+ private ExchangeRate MapToExchangeRate(ExchangeRateDto exchangeRateDto)
+ {
+ return new ExchangeRate(
+ new Currency("CZK"), //CNB only retrieve rates for CZK
+ new Currency(exchangeRateDto.CurrencyCode),
+ exchangeRateDto.Rate,
+ exchangeRateDto.ValidFor);
+ }
+}
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Responses/ExchangeRate.cs b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Responses/ExchangeRate.cs
new file mode 100644
index 000000000..470749dbe
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Responses/ExchangeRate.cs
@@ -0,0 +1,31 @@
+using ExchangeRateUpdater.Models.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ExchangeRateUpdater.Data.Responses;
+public class ExchangeRate
+{
+ public ExchangeRate(Currency sourceCurrency, Currency targetCurrency, decimal value, DateTime date)
+ {
+ SourceCurrency = sourceCurrency;
+ TargetCurrency = targetCurrency;
+ Value = value;
+ Date = date;
+ }
+
+ public Currency SourceCurrency { get; }
+
+ public Currency TargetCurrency { get; }
+
+ public decimal Value { get; }
+
+ public DateTime Date { get; }
+
+ public override string ToString()
+ {
+ return $"{SourceCurrency}/{TargetCurrency}";
+ }
+}
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Responses/ExchangeRateDto.cs b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Responses/ExchangeRateDto.cs
new file mode 100644
index 000000000..7a16f534e
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Responses/ExchangeRateDto.cs
@@ -0,0 +1,12 @@
+
+namespace ExchangeRateUpdater.Data.Responses;
+public class ExchangeRateDto
+{
+ public DateTime ValidFor { get; set; }
+ public int Order { get; set; }
+ public string Country { get; set; }
+ public string Currency { get; set; }
+ public int Amount { get; set; }
+ public string CurrencyCode { get; set; }
+ public decimal Rate { get; set; }
+}
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Responses/ExchangeRateResponseDto.cs b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Responses/ExchangeRateResponseDto.cs
new file mode 100644
index 000000000..6d3c2dcad
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Responses/ExchangeRateResponseDto.cs
@@ -0,0 +1,8 @@
+using Newtonsoft.Json;
+
+namespace ExchangeRateUpdater.Data.Responses;
+public class ExchangeRatesResponseDto
+{
+ [JsonProperty("rates")]
+ public List Rates { get; set; }
+}
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Responses/RateResultDto.cs b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Responses/RateResultDto.cs
new file mode 100644
index 000000000..b9ea91e12
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Data/Responses/RateResultDto.cs
@@ -0,0 +1,18 @@
+using ExchangeRateUpdater.Models.Models;
+
+namespace ExchangeRateUpdater.Data.Responses;
+public class ExchangeRateResultDto
+{
+ public ExchangeRateResultDto(Currency sourceCurrency, Currency targetCurrency, decimal value, DateTime date)
+ {
+ Currencies = $"{sourceCurrency} / {targetCurrency}";
+ Value = value;
+ Date = date;
+ }
+
+ public string Currencies { get; }
+
+ public decimal Value { get; }
+
+ public DateTime Date { get; }
+}
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Models/ExchangeRateUpdater.Models.csproj b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Models/ExchangeRateUpdater.Models.csproj
new file mode 100644
index 000000000..fa71b7ae6
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Models/ExchangeRateUpdater.Models.csproj
@@ -0,0 +1,9 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Models/Models/Currency.cs b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Models/Models/Currency.cs
new file mode 100644
index 000000000..2518d5e7a
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Models/Models/Currency.cs
@@ -0,0 +1,18 @@
+namespace ExchangeRateUpdater.Models.Models;
+public class Currency
+{
+ public Currency(string code)
+ {
+ Code = code;
+ }
+
+ ///
+ /// Three-letter ISO 4217 code of the currency.
+ ///
+ public string Code { get; }
+
+ public override string ToString()
+ {
+ return Code;
+ }
+}
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Models/Requests/ExchangeRateRequest.cs b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Models/Requests/ExchangeRateRequest.cs
new file mode 100644
index 000000000..f44f7579c
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Models/Requests/ExchangeRateRequest.cs
@@ -0,0 +1,14 @@
+using ExchangeRateUpdater.Models.Models;
+
+namespace ExchangeRateUpdater.Models.Requests;
+public class ExchangeRateRequest
+{
+ public Currency SourceCurrency { get; set; }
+ public Currency TargetCurrency { get; set; }
+
+ public override string ToString()
+ {
+ return $"{SourceCurrency}/{TargetCurrency}";
+ }
+
+}
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Models/Requests/ExchangeRateRequestDto.cs b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Models/Requests/ExchangeRateRequestDto.cs
new file mode 100644
index 000000000..f784d3b86
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Models/Requests/ExchangeRateRequestDto.cs
@@ -0,0 +1,7 @@
+
+namespace ExchangeRateUpdater.Models.Requests;
+public class ExchangeRateRequestDto
+{
+ public DateTime Date { get; set; }
+ public List ExchangeRatesDetails { get; set; }
+}
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Tests/ExchangeControllerTests.cs b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Tests/ExchangeControllerTests.cs
new file mode 100644
index 000000000..3f02edb94
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Tests/ExchangeControllerTests.cs
@@ -0,0 +1,125 @@
+using Microsoft.Extensions.Logging;
+
+namespace ExchangeRateUpdater.Tests;
+
+[TestFixture]
+public class ExchangeControllerTests
+{
+ private ExchangeRatesController _controller;
+ private Mock _mockService;
+ private Mock> _mockLogger;
+
+ [SetUp]
+ public void SetUp()
+ {
+ _mockService = new Mock();
+ _mockLogger = new Mock>();
+ _controller = new ExchangeRatesController(_mockService.Object, _mockLogger.Object);
+ }
+
+ [Test]
+ public async Task GivenNullExchangeRate_ShouldReturnBadRequest()
+ {
+ // Arrange
+ var exchangeRatesToRequest = new ExchangeRateRequestDto() { Date = new DateTime(2025, 01, 20) };
+
+ // Act
+ var result = await _controller.GetDailyExchangeRatesAsync(exchangeRatesToRequest, new CancellationToken());
+
+ // Assert
+ var badRequestResult = result as BadRequestObjectResult;
+ Assert.IsNotNull(badRequestResult); // Verifica que sea un BadRequestObjectResult
+ Assert.AreEqual(400, badRequestResult.StatusCode); // Verifica que el código de estado sea 400
+ Assert.AreEqual("Exchange rate(s) cannot be empty or null", badRequestResult.Value); // Verifica el mensaje
+ }
+
+ [Test]
+ public async Task GivenEmptyExchangeRate_ShouldReturnBadRequest()
+ {
+ // Arrange
+ var exchangeRatesToRequest = new ExchangeRateRequestDto()
+ {
+ Date = new DateTime(2025, 01, 20),
+ ExchangeRatesDetails = new List()
+ };
+
+ // Act
+ var result = await _controller.GetDailyExchangeRatesAsync(exchangeRatesToRequest, new CancellationToken());
+
+ // Assert
+ var badRequestResult = result as BadRequestObjectResult;
+ Assert.IsNotNull(badRequestResult); // Verifica que sea un BadRequestObjectResult
+ Assert.AreEqual(400, badRequestResult.StatusCode); // Verifica que el código de estado sea 400
+ Assert.AreEqual("Exchange rate(s) cannot be empty or null", badRequestResult.Value); // Verifica el mensaje
+ }
+
+ [Test]
+ public async Task GivenValidExchangeRate_ShouldReturnExchangeRate()
+ {
+ // Arrange
+ var request = new ExchangeRateRequestDto()
+ {
+ Date = new DateTime(2025, 01, 20),
+ ExchangeRatesDetails = new List()
+ {
+ new ExchangeRateRequest()
+ {
+ SourceCurrency = new Currency("CZK"),
+ TargetCurrency = new Currency("USD")
+ }
+ }
+ };
+ var resultado = new List() {
+ new ExchangeRateResultDto(targetCurrency: new Currency("USD"), sourceCurrency: new Currency("CZK"), value:10, date: new DateTime(2025, 01, 20))
+ };
+
+ _mockService.Setup(s => s.GetExchangeRates(request.ExchangeRatesDetails, request.Date, new CancellationToken())).ReturnsAsync(resultado);
+
+ //// Act
+ var result = await _controller.GetDailyExchangeRatesAsync(request, new CancellationToken());
+
+ // Assert
+ var OkResult = result as OkObjectResult;
+ Assert.IsNotNull(OkResult);
+ Assert.AreEqual(200, OkResult.StatusCode);
+
+ var rates = OkResult.Value as List;
+ Assert.IsNotNull(rates);
+ Assert.IsNotEmpty(rates);
+ Assert.IsTrue(rates.Any());
+ }
+
+ [Test]
+ public async Task GivenInalidExchangeRate_ShouldReturnEmptyList()
+ {
+ // Arrange
+ var request = new ExchangeRateRequestDto()
+ {
+ Date = new DateTime(2025, 01, 20),
+ ExchangeRatesDetails = new List()
+ {
+ new ExchangeRateRequest()
+ {
+ SourceCurrency = new Currency("CZK"),
+ TargetCurrency = new Currency("ABC")
+ }
+ }
+ };
+ var resultado = new List();
+
+ _mockService.Setup(s => s.GetExchangeRates(request.ExchangeRatesDetails, request.Date, new CancellationToken())).ReturnsAsync(resultado);
+
+ //// Act
+ var result = await _controller.GetDailyExchangeRatesAsync(request, new CancellationToken());
+
+ // Assert
+ var OkResult = result as OkObjectResult;
+ Assert.IsNotNull(OkResult);
+ Assert.AreEqual(200, OkResult.StatusCode);
+
+ var rates = OkResult.Value as List;
+ Assert.IsNotNull(rates);
+ Assert.IsEmpty(rates);
+ Assert.IsFalse(rates.Any());
+ }
+}
\ No newline at end of file
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Tests/ExchangeRateServicesTests.cs b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Tests/ExchangeRateServicesTests.cs
new file mode 100644
index 000000000..28d1f2f7f
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Tests/ExchangeRateServicesTests.cs
@@ -0,0 +1,80 @@
+
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
+
+namespace ExchangeRateUpdater.Tests;
+
+[TestFixture]
+public class ExchangeRateServicesTests
+{
+ private Mock _mockRepository;
+ private Mock> _mockLogger;
+ private ExchangeRateService _service;
+
+ [SetUp]
+ public void SetUp()
+ {
+ _mockRepository = new Mock();
+ _mockLogger = new Mock >();
+ _service = new ExchangeRateService(_mockRepository.Object, _mockLogger.Object);
+ }
+
+
+ [Test]
+ public async Task GivenInalidExchangeRate_ShouldReturnEmptyList()
+ {
+ // Arrange
+ var currencies = new List()
+ {
+ new ExchangeRateRequest()
+ {
+ SourceCurrency = new Currency("CZK"),
+ TargetCurrency = new Currency("ABC")
+ }
+ };
+
+ var resultado = new List();
+ _mockRepository.Setup(s => s.GetExchangeRatesByDateAsync(new DateTime(2025, 01, 01), new CancellationToken())).ReturnsAsync(resultado);
+
+ //// Act
+ var result = await _service.GetExchangeRates(currencies, new DateTime(2025, 01, 01), new CancellationToken());
+
+ // Assert
+ Assert.IsNotNull(result);
+ Assert.IsEmpty(result);
+ Assert.IsFalse(result.Any());
+ }
+
+ [Test]
+ public async Task GivenValidExchangeRate_ShouldReturnExchangeRate()
+ {
+ // Arrange
+ var currencies = new List()
+ {
+ new ExchangeRateRequest()
+ {
+ SourceCurrency = new Currency("CZK"),
+ TargetCurrency = new Currency("USD")
+ }
+ };
+
+ var resultado = new List()
+ {
+ new ExchangeRate(sourceCurrency: new Currency("CZK"),
+ targetCurrency: new Currency("USD"),
+ value: 24,
+ date: new DateTime(2025, 01, 20))
+ };
+
+ _mockRepository.Setup(s => s.GetExchangeRatesByDateAsync(new DateTime(2025, 01, 01), new CancellationToken())).ReturnsAsync(resultado);
+
+ //// Act
+ var result = await _service.GetExchangeRates(currencies, new DateTime(2025, 01, 01), new CancellationToken());
+
+ // Assert
+ Assert.IsNotNull(result);
+ Assert.IsNotEmpty(result);
+ Assert.IsTrue(result.Any());
+ Assert.AreEqual("CZK / USD", result[0].Currencies);
+ }
+}
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Tests/ExchangeRateUpdater.Tests.csproj b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Tests/ExchangeRateUpdater.Tests.csproj
new file mode 100644
index 000000000..c49837f1f
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Tests/ExchangeRateUpdater.Tests.csproj
@@ -0,0 +1,29 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Tests/Usings.cs b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Tests/Usings.cs
new file mode 100644
index 000000000..7c746b1b3
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.Tests/Usings.cs
@@ -0,0 +1,9 @@
+global using Moq;
+global using ExchangeRateUpdater.Business.Interfaces;
+global using ExchangeRateUpdater.Controllers;
+global using ExchangeRateUpdater.Models.Models;
+global using ExchangeRateUpdater.Data.Responses;
+global using ExchangeRateUpdater.Models.Requests;
+global using Microsoft.AspNetCore.Mvc;
+global using ExchangeRateUpdater.Data.Interfaces;
+global using ExchangeRateUpdater.Business.Services;
\ No newline at end of file
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.api/Controllers/ExchangeRatesController.cs b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.api/Controllers/ExchangeRatesController.cs
new file mode 100644
index 000000000..43feb155e
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.api/Controllers/ExchangeRatesController.cs
@@ -0,0 +1,42 @@
+using ExchangeRateUpdater.Business.Interfaces;
+using ExchangeRateUpdater.Models.Requests;
+using Microsoft.AspNetCore.Mvc;
+
+namespace ExchangeRateUpdater.Controllers;
+
+[ApiController]
+[Route("/api/exchangerates")]
+public class ExchangeRatesController : ControllerBase
+{
+ private readonly IExchangeRateService _exchangeRateService;
+ private readonly ILogger _logger;
+
+
+ public ExchangeRatesController(IExchangeRateService exchangeRateService, ILogger logger)
+ {
+ _exchangeRateService = exchangeRateService;
+ _logger = logger;
+ }
+ ///
+ /// Gets the exchange rates for the currencies requested and the specified date
+ /// Uses POST to get an objetct (containing a list) as parameter
+ ///
+ ///
+ ///
+ ///
+ [HttpPost("getExchangeRates")]
+ public async Task GetDailyExchangeRatesAsync([FromBody] ExchangeRateRequestDto exchangeRatesRequest, CancellationToken cancellationToken)
+ {
+ if (exchangeRatesRequest.ExchangeRatesDetails is null || !exchangeRatesRequest.ExchangeRatesDetails.Any())
+ {
+ _logger.LogError("Exchange rate(s) cannot be empty or null");
+ return BadRequest("Exchange rate(s) cannot be empty or null");
+ }
+
+ var result = await _exchangeRateService.GetExchangeRates(exchangeRatesRequest.ExchangeRatesDetails, exchangeRatesRequest.Date, cancellationToken);
+
+ _logger.LogInformation("Exchange rates successfully obtained.");
+ return Ok(result);
+ }
+
+}
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.api/ExchangeRateUpdater.Api.csproj b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.api/ExchangeRateUpdater.Api.csproj
new file mode 100644
index 000000000..7b792eaee
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.api/ExchangeRateUpdater.Api.csproj
@@ -0,0 +1,18 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.api/Program.cs b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.api/Program.cs
new file mode 100644
index 000000000..ea8a0f7be
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.api/Program.cs
@@ -0,0 +1,49 @@
+using ExchangeRateUpdater.Business.Interfaces;
+using ExchangeRateUpdater.Business.Services;
+using ExchangeRateUpdater.Data.Interfaces;
+using ExchangeRateUpdater.Data.Repositories;
+using Microsoft.OpenApi.Models;
+
+var builder = WebApplication.CreateBuilder(args);
+
+builder.Services.AddMemoryCache();
+builder.Services.AddScoped();
+builder.Services.AddScoped();
+builder.Services.AddScoped();
+builder.Services.AddControllers();
+builder.Services.AddEndpointsApiExplorer();
+builder.Services.AddSwaggerGen(c =>
+{
+ c.SwaggerDoc("v1", new OpenApiInfo
+ {
+ Title = "Exchange Rate Updater",
+ Version = "v1",
+ Description = "This API can be used to get the conversion rates between CZK currency and many others"
+ });
+});
+
+builder.Logging.ClearProviders();
+builder.Logging.AddConsole();
+builder.Logging.AddDebug();
+builder.Logging.SetMinimumLevel(LogLevel.Information);
+
+var serviceProvider = new ServiceCollection()
+ .AddSingleton(new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
+ .Build()
+ );
+
+
+var app = builder.Build();
+
+if (app.Environment.IsDevelopment())
+{
+ app.UseSwagger();
+ app.UseSwaggerUI();
+}
+
+app.UseHttpsRedirection();
+app.MapControllers();
+
+app.Run();
\ No newline at end of file
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.api/Properties/launchSettings.json b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.api/Properties/launchSettings.json
new file mode 100644
index 000000000..7d3e34914
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.api/Properties/launchSettings.json
@@ -0,0 +1,41 @@
+{
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "launchUrl": "weatherforecast",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "dotnetRunMessages": true,
+ "applicationUrl": "http://localhost:5276"
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "launchUrl": "weatherforecast",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "ExchangeRateUpdater.Api": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "dotnetRunMessages": true,
+ "applicationUrl": "https://localhost:7276;http://localhost:5276"
+ }
+ },
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:52301",
+ "sslPort": 44368
+ }
+ }
+}
\ No newline at end of file
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.api/appsettings.Development.json b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.api/appsettings.Development.json
new file mode 100644
index 000000000..0c208ae91
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.api/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.api/appsettings.json b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.api/appsettings.json
new file mode 100644
index 000000000..5cb2a407c
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.api/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*",
+ "ExchangeRateUrl": "https://api.cnb.cz/cnbapi/exrates/daily"
+}
diff --git a/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.sln b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.sln
new file mode 100644
index 000000000..073406b68
--- /dev/null
+++ b/jobs/Backend/Task/ExchangeRateUpdater/ExchangeRateUpdater.sln
@@ -0,0 +1,49 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.9.34902.65
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExchangeRateUpdater.Api", "ExchangeRateUpdater.api\ExchangeRateUpdater.Api.csproj", "{9CAC3044-FCBC-41D8-93A6-294F916292EE}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExchangeRateUpdater.Data", "ExchangeRateUpdater.Data\ExchangeRateUpdater.Data.csproj", "{98DEBA7B-E32C-44EF-BF6D-966FD66C58F3}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExchangeRateUpdater.Business", "ExchangeRateUpdater.Business\ExchangeRateUpdater.Business.csproj", "{73CD85B9-7C24-424D-90C7-4702706AD48A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExchangeRateUpdater.Models", "ExchangeRateUpdater.Models\ExchangeRateUpdater.Models.csproj", "{625CC8EA-2E4A-4308-B041-CA77AEC2186A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExchangeRateUpdater.Tests", "ExchangeRateUpdater.Tests\ExchangeRateUpdater.Tests.csproj", "{1060BFDF-C994-47E0-9FC5-79E9813BEE5F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {9CAC3044-FCBC-41D8-93A6-294F916292EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9CAC3044-FCBC-41D8-93A6-294F916292EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9CAC3044-FCBC-41D8-93A6-294F916292EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9CAC3044-FCBC-41D8-93A6-294F916292EE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {98DEBA7B-E32C-44EF-BF6D-966FD66C58F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {98DEBA7B-E32C-44EF-BF6D-966FD66C58F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {98DEBA7B-E32C-44EF-BF6D-966FD66C58F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {98DEBA7B-E32C-44EF-BF6D-966FD66C58F3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {73CD85B9-7C24-424D-90C7-4702706AD48A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {73CD85B9-7C24-424D-90C7-4702706AD48A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {73CD85B9-7C24-424D-90C7-4702706AD48A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {73CD85B9-7C24-424D-90C7-4702706AD48A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {625CC8EA-2E4A-4308-B041-CA77AEC2186A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {625CC8EA-2E4A-4308-B041-CA77AEC2186A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {625CC8EA-2E4A-4308-B041-CA77AEC2186A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {625CC8EA-2E4A-4308-B041-CA77AEC2186A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1060BFDF-C994-47E0-9FC5-79E9813BEE5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1060BFDF-C994-47E0-9FC5-79E9813BEE5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1060BFDF-C994-47E0-9FC5-79E9813BEE5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1060BFDF-C994-47E0-9FC5-79E9813BEE5F}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {B38D1E9E-34E8-462E-B003-4E2921260A09}
+ EndGlobalSection
+EndGlobal
diff --git a/jobs/Backend/Task/Program.cs b/jobs/Backend/Task/Program.cs
deleted file mode 100644
index 379a69b1f..000000000
--- a/jobs/Backend/Task/Program.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace ExchangeRateUpdater
-{
- public static class Program
- {
- private static IEnumerable currencies = new[]
- {
- new Currency("USD"),
- new Currency("EUR"),
- new Currency("CZK"),
- new Currency("JPY"),
- new Currency("KES"),
- new Currency("RUB"),
- new Currency("THB"),
- new Currency("TRY"),
- new Currency("XYZ")
- };
-
- public static void Main(string[] args)
- {
- try
- {
- var provider = new ExchangeRateProvider();
- var rates = provider.GetExchangeRates(currencies);
-
- Console.WriteLine($"Successfully retrieved {rates.Count()} exchange rates:");
- foreach (var rate in rates)
- {
- Console.WriteLine(rate.ToString());
- }
- }
- catch (Exception e)
- {
- Console.WriteLine($"Could not retrieve exchange rates: '{e.Message}'.");
- }
-
- Console.ReadLine();
- }
- }
-}