Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
*.tgz
*.sublime-*

.vs/

node_modules
bower_components
npm-debug.log
19 changes: 0 additions & 19 deletions jobs/Backend/Task/ExchangeRateProvider.cs

This file was deleted.

8 changes: 0 additions & 8 deletions jobs/Backend/Task/ExchangeRateUpdater.csproj

This file was deleted.

138 changes: 116 additions & 22 deletions jobs/Backend/Task/ExchangeRateUpdater.sln
Original file line number Diff line number Diff line change
@@ -1,22 +1,116 @@

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

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 18
VisualStudioVersion = 18.0.11205.157
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExchangeRateUpdater.Console", "src\ExchangeRateUpdater.Console\ExchangeRateUpdater.Console.csproj", "{7B2695D6-D24C-4460-A58E-A10F08550CE0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExchangeRateUpdater.BusinessLogic", "src\ExchangeRateUpdater.BusinessLogic\ExchangeRateUpdater.BusinessLogic.csproj", "{741FA146-0B48-4A16-80F0-0A4D84A6AEA5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExchangeRateUpdater.Data", "src\ExchangeRateUpdater.Data\ExchangeRateUpdater.Data.csproj", "{2046544F-2178-4BB8-9E5A-904780231DB2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0AB3BF05-4346-4AA6-1389-037BE0695223}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExchangeRateUpdater.UnitTests", "tests\ExchangeRateUpdater.UnitTests\ExchangeRateUpdater.UnitTests.csproj", "{02DCD6F6-F79D-460E-9943-A9E164F79452}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExchangeRateUpdater.Api", "src\ExchangeRateUpdater.Api\ExchangeRateUpdater.Api.csproj", "{60D975FE-B57B-E1C4-6D3F-CF509327D85B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExchangeRateUpdater.Client", "src\ExchangeRateUpdater.Client\ExchangeRateUpdater.Client.csproj", "{26F867DC-B5EF-9545-2053-6EEE6D5E8BE9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
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}.Debug|x64.ActiveCfg = Debug|Any CPU
{7B2695D6-D24C-4460-A58E-A10F08550CE0}.Debug|x64.Build.0 = Debug|Any CPU
{7B2695D6-D24C-4460-A58E-A10F08550CE0}.Debug|x86.ActiveCfg = Debug|Any CPU
{7B2695D6-D24C-4460-A58E-A10F08550CE0}.Debug|x86.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
{7B2695D6-D24C-4460-A58E-A10F08550CE0}.Release|x64.ActiveCfg = Release|Any CPU
{7B2695D6-D24C-4460-A58E-A10F08550CE0}.Release|x64.Build.0 = Release|Any CPU
{7B2695D6-D24C-4460-A58E-A10F08550CE0}.Release|x86.ActiveCfg = Release|Any CPU
{7B2695D6-D24C-4460-A58E-A10F08550CE0}.Release|x86.Build.0 = Release|Any CPU
{741FA146-0B48-4A16-80F0-0A4D84A6AEA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{741FA146-0B48-4A16-80F0-0A4D84A6AEA5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{741FA146-0B48-4A16-80F0-0A4D84A6AEA5}.Debug|x64.ActiveCfg = Debug|Any CPU
{741FA146-0B48-4A16-80F0-0A4D84A6AEA5}.Debug|x64.Build.0 = Debug|Any CPU
{741FA146-0B48-4A16-80F0-0A4D84A6AEA5}.Debug|x86.ActiveCfg = Debug|Any CPU
{741FA146-0B48-4A16-80F0-0A4D84A6AEA5}.Debug|x86.Build.0 = Debug|Any CPU
{741FA146-0B48-4A16-80F0-0A4D84A6AEA5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{741FA146-0B48-4A16-80F0-0A4D84A6AEA5}.Release|Any CPU.Build.0 = Release|Any CPU
{741FA146-0B48-4A16-80F0-0A4D84A6AEA5}.Release|x64.ActiveCfg = Release|Any CPU
{741FA146-0B48-4A16-80F0-0A4D84A6AEA5}.Release|x64.Build.0 = Release|Any CPU
{741FA146-0B48-4A16-80F0-0A4D84A6AEA5}.Release|x86.ActiveCfg = Release|Any CPU
{741FA146-0B48-4A16-80F0-0A4D84A6AEA5}.Release|x86.Build.0 = Release|Any CPU
{2046544F-2178-4BB8-9E5A-904780231DB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2046544F-2178-4BB8-9E5A-904780231DB2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2046544F-2178-4BB8-9E5A-904780231DB2}.Debug|x64.ActiveCfg = Debug|Any CPU
{2046544F-2178-4BB8-9E5A-904780231DB2}.Debug|x64.Build.0 = Debug|Any CPU
{2046544F-2178-4BB8-9E5A-904780231DB2}.Debug|x86.ActiveCfg = Debug|Any CPU
{2046544F-2178-4BB8-9E5A-904780231DB2}.Debug|x86.Build.0 = Debug|Any CPU
{2046544F-2178-4BB8-9E5A-904780231DB2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2046544F-2178-4BB8-9E5A-904780231DB2}.Release|Any CPU.Build.0 = Release|Any CPU
{2046544F-2178-4BB8-9E5A-904780231DB2}.Release|x64.ActiveCfg = Release|Any CPU
{2046544F-2178-4BB8-9E5A-904780231DB2}.Release|x64.Build.0 = Release|Any CPU
{2046544F-2178-4BB8-9E5A-904780231DB2}.Release|x86.ActiveCfg = Release|Any CPU
{2046544F-2178-4BB8-9E5A-904780231DB2}.Release|x86.Build.0 = Release|Any CPU
{02DCD6F6-F79D-460E-9943-A9E164F79452}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{02DCD6F6-F79D-460E-9943-A9E164F79452}.Debug|Any CPU.Build.0 = Debug|Any CPU
{02DCD6F6-F79D-460E-9943-A9E164F79452}.Debug|x64.ActiveCfg = Debug|Any CPU
{02DCD6F6-F79D-460E-9943-A9E164F79452}.Debug|x64.Build.0 = Debug|Any CPU
{02DCD6F6-F79D-460E-9943-A9E164F79452}.Debug|x86.ActiveCfg = Debug|Any CPU
{02DCD6F6-F79D-460E-9943-A9E164F79452}.Debug|x86.Build.0 = Debug|Any CPU
{02DCD6F6-F79D-460E-9943-A9E164F79452}.Release|Any CPU.ActiveCfg = Release|Any CPU
{02DCD6F6-F79D-460E-9943-A9E164F79452}.Release|Any CPU.Build.0 = Release|Any CPU
{02DCD6F6-F79D-460E-9943-A9E164F79452}.Release|x64.ActiveCfg = Release|Any CPU
{02DCD6F6-F79D-460E-9943-A9E164F79452}.Release|x64.Build.0 = Release|Any CPU
{02DCD6F6-F79D-460E-9943-A9E164F79452}.Release|x86.ActiveCfg = Release|Any CPU
{02DCD6F6-F79D-460E-9943-A9E164F79452}.Release|x86.Build.0 = Release|Any CPU
{60D975FE-B57B-E1C4-6D3F-CF509327D85B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{60D975FE-B57B-E1C4-6D3F-CF509327D85B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{60D975FE-B57B-E1C4-6D3F-CF509327D85B}.Debug|x64.ActiveCfg = Debug|Any CPU
{60D975FE-B57B-E1C4-6D3F-CF509327D85B}.Debug|x64.Build.0 = Debug|Any CPU
{60D975FE-B57B-E1C4-6D3F-CF509327D85B}.Debug|x86.ActiveCfg = Debug|Any CPU
{60D975FE-B57B-E1C4-6D3F-CF509327D85B}.Debug|x86.Build.0 = Debug|Any CPU
{60D975FE-B57B-E1C4-6D3F-CF509327D85B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{60D975FE-B57B-E1C4-6D3F-CF509327D85B}.Release|Any CPU.Build.0 = Release|Any CPU
{60D975FE-B57B-E1C4-6D3F-CF509327D85B}.Release|x64.ActiveCfg = Release|Any CPU
{60D975FE-B57B-E1C4-6D3F-CF509327D85B}.Release|x64.Build.0 = Release|Any CPU
{60D975FE-B57B-E1C4-6D3F-CF509327D85B}.Release|x86.ActiveCfg = Release|Any CPU
{60D975FE-B57B-E1C4-6D3F-CF509327D85B}.Release|x86.Build.0 = Release|Any CPU
{26F867DC-B5EF-9545-2053-6EEE6D5E8BE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{26F867DC-B5EF-9545-2053-6EEE6D5E8BE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{26F867DC-B5EF-9545-2053-6EEE6D5E8BE9}.Debug|x64.ActiveCfg = Debug|Any CPU
{26F867DC-B5EF-9545-2053-6EEE6D5E8BE9}.Debug|x64.Build.0 = Debug|Any CPU
{26F867DC-B5EF-9545-2053-6EEE6D5E8BE9}.Debug|x86.ActiveCfg = Debug|Any CPU
{26F867DC-B5EF-9545-2053-6EEE6D5E8BE9}.Debug|x86.Build.0 = Debug|Any CPU
{26F867DC-B5EF-9545-2053-6EEE6D5E8BE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{26F867DC-B5EF-9545-2053-6EEE6D5E8BE9}.Release|Any CPU.Build.0 = Release|Any CPU
{26F867DC-B5EF-9545-2053-6EEE6D5E8BE9}.Release|x64.ActiveCfg = Release|Any CPU
{26F867DC-B5EF-9545-2053-6EEE6D5E8BE9}.Release|x64.Build.0 = Release|Any CPU
{26F867DC-B5EF-9545-2053-6EEE6D5E8BE9}.Release|x86.ActiveCfg = Release|Any CPU
{26F867DC-B5EF-9545-2053-6EEE6D5E8BE9}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{7B2695D6-D24C-4460-A58E-A10F08550CE0} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{741FA146-0B48-4A16-80F0-0A4D84A6AEA5} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{2046544F-2178-4BB8-9E5A-904780231DB2} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{02DCD6F6-F79D-460E-9943-A9E164F79452} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
{60D975FE-B57B-E1C4-6D3F-CF509327D85B} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{26F867DC-B5EF-9545-2053-6EEE6D5E8BE9} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
EndGlobalSection
EndGlobal
43 changes: 0 additions & 43 deletions jobs/Backend/Task/Program.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using Microsoft.AspNetCore.Mvc;
using ExchangeRateUpdater.BusinessLogic;
using ExchangeRateUpdater.BusinessLogic.Models;

namespace ExchangeRateUpdater.Api.Controllers
{
/// <summary>
/// API controller for exchange rate operations.
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class ExchangeRatesController : ControllerBase
{
private readonly IExchangeRateManager _exchangeRateManager;
private readonly ILogger<ExchangeRatesController> _logger;

/// <summary>
/// Constructor for ExchangeRatesController.
/// </summary>
public ExchangeRatesController(IExchangeRateManager exchangeRateManager, ILogger<ExchangeRatesController> logger)
{
_exchangeRateManager = exchangeRateManager ?? throw new ArgumentNullException(nameof(exchangeRateManager));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}

/// <summary>
/// Gets exchange rates for specified currency codes.
/// </summary>
/// <param name="currencies">Comma-separated list of currency codes (e.g., "USD,EUR,JPY")</param>
/// <returns>List of exchange rates from source currency to CZK</returns>
[HttpGet]
[ProducesResponseType(typeof(IEnumerable<ExchangeRateViewModel>), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public IActionResult GetExchangeRates([FromQuery] string? currencies = null)
{
try
{
if (string.IsNullOrWhiteSpace(currencies))
{
return BadRequest("Currencies parameter is required. Provide comma-separated currency codes.");
}

var currencyList = currencies
.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Select(c => new Currency(c.ToUpperInvariant()))
.ToList();

if (currencyList.Count == 0)
{
return BadRequest("At least one currency code is required.");
}

// Always include CZK for consistency
if (!currencyList.Any(c => c.Code == "CZK"))
{
currencyList.Add(new Currency("CZK"));
}

var rates = _exchangeRateManager.GetExchangeRates(currencyList);

var result = rates
.Select(r => new ExchangeRateViewModel
{
SourceCurrencyCode = r.SourceCurrency.Code,
TargetCurrencyCode = r.TargetCurrency.Code,
Rate = r.Value
})
.ToList();

return Ok(result);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving exchange rates for currencies: {Currencies}", currencies);
return StatusCode(StatusCodes.Status500InternalServerError, new { error = "Failed to retrieve exchange rates." });
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\ExchangeRateUpdater.BusinessLogic\ExchangeRateUpdater.BusinessLogic.csproj" />
<ProjectReference Include="..\ExchangeRateUpdater.Data\ExchangeRateUpdater.Data.csproj" />
</ItemGroup>

<ItemGroup>
<Folder Include="Models\" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace ExchangeRateUpdater.Api.Controllers
{
/// <summary>
/// DTO for exchange rate information.
/// </summary>
public class ExchangeRateViewModel
{
/// <summary>
/// Source currency code (e.g., USD, EUR).
/// </summary>
public string SourceCurrencyCode { get; set; } = string.Empty;

/// <summary>
/// Target currency code (typically CZK).
/// </summary>
public string TargetCurrencyCode { get; set; } = string.Empty;

/// <summary>
/// Exchange rate (how many target currency units per one source currency unit).
/// </summary>
public decimal Rate { get; set; }
}
}
Loading
Loading