diff --git a/jobs/Backend/Task/.vs/ExchangeRateUpdater/CopilotIndices/17.14.1561.44479/CodeChunks.db b/jobs/Backend/Task/.vs/ExchangeRateUpdater/CopilotIndices/17.14.1561.44479/CodeChunks.db
new file mode 100644
index 0000000000..c5f5534d12
Binary files /dev/null and b/jobs/Backend/Task/.vs/ExchangeRateUpdater/CopilotIndices/17.14.1561.44479/CodeChunks.db differ
diff --git a/jobs/Backend/Task/.vs/ExchangeRateUpdater/CopilotIndices/17.14.1561.44479/SemanticSymbols.db b/jobs/Backend/Task/.vs/ExchangeRateUpdater/CopilotIndices/17.14.1561.44479/SemanticSymbols.db
new file mode 100644
index 0000000000..7f986412dc
Binary files /dev/null and b/jobs/Backend/Task/.vs/ExchangeRateUpdater/CopilotIndices/17.14.1561.44479/SemanticSymbols.db differ
diff --git a/jobs/Backend/Task/.vs/ExchangeRateUpdater/DesignTimeBuild/.dtbcache.v2 b/jobs/Backend/Task/.vs/ExchangeRateUpdater/DesignTimeBuild/.dtbcache.v2
new file mode 100644
index 0000000000..eafba410b4
Binary files /dev/null and b/jobs/Backend/Task/.vs/ExchangeRateUpdater/DesignTimeBuild/.dtbcache.v2 differ
diff --git a/jobs/Backend/Task/.vs/ExchangeRateUpdater/FileContentIndex/1529f4e8-7121-44d7-a522-f9458941e288.vsidx b/jobs/Backend/Task/.vs/ExchangeRateUpdater/FileContentIndex/1529f4e8-7121-44d7-a522-f9458941e288.vsidx
new file mode 100644
index 0000000000..3885b9ca24
Binary files /dev/null and b/jobs/Backend/Task/.vs/ExchangeRateUpdater/FileContentIndex/1529f4e8-7121-44d7-a522-f9458941e288.vsidx differ
diff --git a/jobs/Backend/Task/.vs/ExchangeRateUpdater/FileContentIndex/270454c7-59aa-4032-9097-c8628fc3e48d.vsidx b/jobs/Backend/Task/.vs/ExchangeRateUpdater/FileContentIndex/270454c7-59aa-4032-9097-c8628fc3e48d.vsidx
new file mode 100644
index 0000000000..e500a71662
Binary files /dev/null and b/jobs/Backend/Task/.vs/ExchangeRateUpdater/FileContentIndex/270454c7-59aa-4032-9097-c8628fc3e48d.vsidx differ
diff --git a/jobs/Backend/Task/.vs/ExchangeRateUpdater/FileContentIndex/b458b426-8543-4dbb-9281-b6b850fe5a50.vsidx b/jobs/Backend/Task/.vs/ExchangeRateUpdater/FileContentIndex/b458b426-8543-4dbb-9281-b6b850fe5a50.vsidx
new file mode 100644
index 0000000000..580960b3a1
Binary files /dev/null and b/jobs/Backend/Task/.vs/ExchangeRateUpdater/FileContentIndex/b458b426-8543-4dbb-9281-b6b850fe5a50.vsidx differ
diff --git a/jobs/Backend/Task/.vs/ExchangeRateUpdater/FileContentIndex/ba775ec1-5bc6-4bf6-b449-7820d82c70d8.vsidx b/jobs/Backend/Task/.vs/ExchangeRateUpdater/FileContentIndex/ba775ec1-5bc6-4bf6-b449-7820d82c70d8.vsidx
new file mode 100644
index 0000000000..d6592805c2
Binary files /dev/null and b/jobs/Backend/Task/.vs/ExchangeRateUpdater/FileContentIndex/ba775ec1-5bc6-4bf6-b449-7820d82c70d8.vsidx differ
diff --git a/jobs/Backend/Task/.vs/ExchangeRateUpdater/FileContentIndex/c5c0f666-451b-4ebb-ac3c-ee67c67229f9.vsidx b/jobs/Backend/Task/.vs/ExchangeRateUpdater/FileContentIndex/c5c0f666-451b-4ebb-ac3c-ee67c67229f9.vsidx
new file mode 100644
index 0000000000..f833502a25
Binary files /dev/null and b/jobs/Backend/Task/.vs/ExchangeRateUpdater/FileContentIndex/c5c0f666-451b-4ebb-ac3c-ee67c67229f9.vsidx differ
diff --git a/jobs/Backend/Task/.vs/ExchangeRateUpdater/copilot-chat/6c67098b/sessions/f77f7d85-a1fd-4ed5-a771-869a169f1e73 b/jobs/Backend/Task/.vs/ExchangeRateUpdater/copilot-chat/6c67098b/sessions/f77f7d85-a1fd-4ed5-a771-869a169f1e73
new file mode 100644
index 0000000000..6bde8cf69a
Binary files /dev/null and b/jobs/Backend/Task/.vs/ExchangeRateUpdater/copilot-chat/6c67098b/sessions/f77f7d85-a1fd-4ed5-a771-869a169f1e73 differ
diff --git a/jobs/Backend/Task/.vs/ExchangeRateUpdater/v17/.futdcache.v2 b/jobs/Backend/Task/.vs/ExchangeRateUpdater/v17/.futdcache.v2
new file mode 100644
index 0000000000..9059b41916
Binary files /dev/null and b/jobs/Backend/Task/.vs/ExchangeRateUpdater/v17/.futdcache.v2 differ
diff --git a/jobs/Backend/Task/.vs/ExchangeRateUpdater/v17/DocumentLayout.backup.json b/jobs/Backend/Task/.vs/ExchangeRateUpdater/v17/DocumentLayout.backup.json
new file mode 100644
index 0000000000..b43643971a
--- /dev/null
+++ b/jobs/Backend/Task/.vs/ExchangeRateUpdater/v17/DocumentLayout.backup.json
@@ -0,0 +1,162 @@
+{
+ "Version": 1,
+ "WorkspaceRootPath": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\",
+ "Documents": [
+ {
+ "AbsoluteMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|c:\\users\\raula\\source\\repos\\backendmewsraul\\jobs\\backend\\task\\readme.md||{EFC0BB08-EA7D-40C6-A696-C870411A895B}",
+ "RelativeMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|solutionrelative:readme.md||{EFC0BB08-EA7D-40C6-A696-C870411A895B}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|c:\\users\\raula\\source\\repos\\backendmewsraul\\jobs\\backend\\task\\responses\\exchangeratefixingresponse.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|solutionrelative:responses\\exchangeratefixingresponse.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|c:\\users\\raula\\source\\repos\\backendmewsraul\\jobs\\backend\\task\\models\\currencyratemodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|solutionrelative:models\\currencyratemodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|c:\\users\\raula\\source\\repos\\backendmewsraul\\jobs\\backend\\task\\models\\currencymodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|solutionrelative:models\\currencymodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|c:\\users\\raula\\source\\repos\\backendmewsraul\\jobs\\backend\\task\\models\\exchangeratemodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|solutionrelative:models\\exchangeratemodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|c:\\users\\raula\\source\\repos\\backendmewsraul\\jobs\\backend\\task\\exchangerateupdater.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}|",
+ "RelativeMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|solutionrelative:exchangerateupdater.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}|"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|c:\\users\\raula\\source\\repos\\backendmewsraul\\jobs\\backend\\task\\program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|solutionrelative:program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|c:\\users\\raula\\source\\repos\\backendmewsraul\\jobs\\backend\\task\\providers\\exchangerateprovider.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|solutionrelative:providers\\exchangerateprovider.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ }
+ ],
+ "DocumentGroupContainers": [
+ {
+ "Orientation": 0,
+ "VerticalTabListWidth": 256,
+ "DocumentGroups": [
+ {
+ "DockedWidth": 129,
+ "SelectedChildIndex": 0,
+ "Children": [
+ {
+ "$type": "Document",
+ "DocumentIndex": 1,
+ "Title": "ExchangeRateFixingResponse.cs",
+ "DocumentMoniker": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Responses\\ExchangeRateFixingResponse.cs",
+ "RelativeDocumentMoniker": "Responses\\ExchangeRateFixingResponse.cs",
+ "ToolTip": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Responses\\ExchangeRateFixingResponse.cs",
+ "RelativeToolTip": "Responses\\ExchangeRateFixingResponse.cs",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2025-12-23T11:29:39.762Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 2,
+ "Title": "CurrencyRateModel.cs",
+ "DocumentMoniker": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Models\\CurrencyRateModel.cs",
+ "RelativeDocumentMoniker": "Models\\CurrencyRateModel.cs",
+ "ToolTip": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Models\\CurrencyRateModel.cs",
+ "RelativeToolTip": "Models\\CurrencyRateModel.cs",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAABAAAAAsAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2025-12-23T11:27:31.354Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 3,
+ "Title": "CurrencyModel.cs",
+ "DocumentMoniker": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Models\\CurrencyModel.cs",
+ "RelativeDocumentMoniker": "Models\\CurrencyModel.cs",
+ "ToolTip": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Models\\CurrencyModel.cs",
+ "RelativeToolTip": "Models\\CurrencyModel.cs",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2025-12-23T11:46:42.54Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 4,
+ "Title": "ExchangeRateModel.cs",
+ "DocumentMoniker": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Models\\ExchangeRateModel.cs",
+ "RelativeDocumentMoniker": "Models\\ExchangeRateModel.cs",
+ "ToolTip": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Models\\ExchangeRateModel.cs",
+ "RelativeToolTip": "Models\\ExchangeRateModel.cs",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAABcAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2025-12-23T13:31:29.018Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 5,
+ "Title": "ExchangeRateUpdater",
+ "DocumentMoniker": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\ExchangeRateUpdater.csproj",
+ "RelativeDocumentMoniker": "ExchangeRateUpdater.csproj",
+ "ToolTip": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\ExchangeRateUpdater.csproj",
+ "RelativeToolTip": "ExchangeRateUpdater.csproj",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAkAAAAvAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000758|",
+ "WhenOpened": "2025-12-23T13:31:50.793Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 6,
+ "Title": "Program.cs",
+ "DocumentMoniker": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Program.cs",
+ "RelativeDocumentMoniker": "Program.cs",
+ "ToolTip": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Program.cs",
+ "RelativeToolTip": "Program.cs",
+ "ViewState": "AgIAABwAAAAAAAAAAAA6wEYAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2025-12-22T15:14:03.972Z",
+ "EditorCaption": ""
+ }
+ ]
+ },
+ {
+ "DockedWidth": 379,
+ "SelectedChildIndex": 0,
+ "Children": [
+ {
+ "$type": "Document",
+ "DocumentIndex": 0,
+ "Title": "Readme.md",
+ "DocumentMoniker": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Readme.md",
+ "RelativeDocumentMoniker": "Readme.md",
+ "ToolTip": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Readme.md",
+ "RelativeToolTip": "Readme.md",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAcAAAAiAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001818|",
+ "WhenOpened": "2025-12-23T13:16:40.632Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 7,
+ "Title": "ExchangeRateProvider.cs",
+ "DocumentMoniker": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Providers\\ExchangeRateProvider.cs",
+ "RelativeDocumentMoniker": "Providers\\ExchangeRateProvider.cs",
+ "ToolTip": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Providers\\ExchangeRateProvider.cs",
+ "RelativeToolTip": "Providers\\ExchangeRateProvider.cs",
+ "ViewState": "AgIAABcAAAAAAAAAAAAUwDYAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2025-12-22T15:11:46.713Z",
+ "EditorCaption": ""
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/jobs/Backend/Task/.vs/ExchangeRateUpdater/v17/DocumentLayout.json b/jobs/Backend/Task/.vs/ExchangeRateUpdater/v17/DocumentLayout.json
new file mode 100644
index 0000000000..49001edad8
--- /dev/null
+++ b/jobs/Backend/Task/.vs/ExchangeRateUpdater/v17/DocumentLayout.json
@@ -0,0 +1,122 @@
+{
+ "Version": 1,
+ "WorkspaceRootPath": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\",
+ "Documents": [
+ {
+ "AbsoluteMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|c:\\users\\raula\\source\\repos\\backendmewsraul\\jobs\\backend\\task\\responses\\exchangeratefixingresponse.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|solutionrelative:responses\\exchangeratefixingresponse.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|c:\\users\\raula\\source\\repos\\backendmewsraul\\jobs\\backend\\task\\models\\currencyratemodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|solutionrelative:models\\currencyratemodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|c:\\users\\raula\\source\\repos\\backendmewsraul\\jobs\\backend\\task\\models\\currencymodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|solutionrelative:models\\currencymodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|c:\\users\\raula\\source\\repos\\backendmewsraul\\jobs\\backend\\task\\models\\exchangeratemodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|solutionrelative:models\\exchangeratemodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|c:\\users\\raula\\source\\repos\\backendmewsraul\\jobs\\backend\\task\\exchangerateupdater.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}|",
+ "RelativeMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|solutionrelative:exchangerateupdater.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}|"
+ },
+ {
+ "AbsoluteMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|c:\\users\\raula\\source\\repos\\backendmewsraul\\jobs\\backend\\task\\program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
+ "RelativeMoniker": "D:0:0:{7B2695D6-D24C-4460-A58E-A10F08550CE0}|ExchangeRateUpdater.csproj|solutionrelative:program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
+ }
+ ],
+ "DocumentGroupContainers": [
+ {
+ "Orientation": 0,
+ "VerticalTabListWidth": 256,
+ "DocumentGroups": [
+ {
+ "DockedWidth": 129,
+ "SelectedChildIndex": 0,
+ "Children": [
+ {
+ "$type": "Document",
+ "DocumentIndex": 0,
+ "Title": "ExchangeRateFixingResponse.cs",
+ "DocumentMoniker": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Responses\\ExchangeRateFixingResponse.cs",
+ "RelativeDocumentMoniker": "Responses\\ExchangeRateFixingResponse.cs",
+ "ToolTip": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Responses\\ExchangeRateFixingResponse.cs",
+ "RelativeToolTip": "Responses\\ExchangeRateFixingResponse.cs",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAcAAAAFAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2025-12-23T11:29:39.762Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 1,
+ "Title": "CurrencyRateModel.cs",
+ "DocumentMoniker": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Models\\CurrencyRateModel.cs",
+ "RelativeDocumentMoniker": "Models\\CurrencyRateModel.cs",
+ "ToolTip": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Models\\CurrencyRateModel.cs",
+ "RelativeToolTip": "Models\\CurrencyRateModel.cs",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAABAAAAAsAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2025-12-23T11:27:31.354Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 2,
+ "Title": "CurrencyModel.cs",
+ "DocumentMoniker": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Models\\CurrencyModel.cs",
+ "RelativeDocumentMoniker": "Models\\CurrencyModel.cs",
+ "ToolTip": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Models\\CurrencyModel.cs",
+ "RelativeToolTip": "Models\\CurrencyModel.cs",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2025-12-23T11:46:42.54Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 3,
+ "Title": "ExchangeRateModel.cs",
+ "DocumentMoniker": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Models\\ExchangeRateModel.cs",
+ "RelativeDocumentMoniker": "Models\\ExchangeRateModel.cs",
+ "ToolTip": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Models\\ExchangeRateModel.cs",
+ "RelativeToolTip": "Models\\ExchangeRateModel.cs",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAABcAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2025-12-23T13:31:29.018Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 4,
+ "Title": "ExchangeRateUpdater",
+ "DocumentMoniker": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\ExchangeRateUpdater.csproj",
+ "RelativeDocumentMoniker": "ExchangeRateUpdater.csproj",
+ "ToolTip": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\ExchangeRateUpdater.csproj",
+ "RelativeToolTip": "ExchangeRateUpdater.csproj",
+ "ViewState": "AgIAAAAAAAAAAAAAAAAAAAkAAAAvAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000758|",
+ "WhenOpened": "2025-12-23T13:31:50.793Z",
+ "EditorCaption": ""
+ },
+ {
+ "$type": "Document",
+ "DocumentIndex": 5,
+ "Title": "Program.cs",
+ "DocumentMoniker": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Program.cs",
+ "RelativeDocumentMoniker": "Program.cs",
+ "ToolTip": "C:\\Users\\raula\\source\\repos\\backendMewsRaul\\jobs\\Backend\\Task\\Program.cs",
+ "RelativeToolTip": "Program.cs",
+ "ViewState": "AgIAABwAAAAAAAAAAAA6wEYAAAAAAAAAAAAAAA==",
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
+ "WhenOpened": "2025-12-22T15:14:03.972Z",
+ "EditorCaption": ""
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/jobs/Backend/Task/.vs/ProjectEvaluation/exchangerateupdater.metadata.v9.bin b/jobs/Backend/Task/.vs/ProjectEvaluation/exchangerateupdater.metadata.v9.bin
new file mode 100644
index 0000000000..9560f800a6
Binary files /dev/null and b/jobs/Backend/Task/.vs/ProjectEvaluation/exchangerateupdater.metadata.v9.bin differ
diff --git a/jobs/Backend/Task/.vs/ProjectEvaluation/exchangerateupdater.projects.v9.bin b/jobs/Backend/Task/.vs/ProjectEvaluation/exchangerateupdater.projects.v9.bin
new file mode 100644
index 0000000000..c3c5238ca1
Binary files /dev/null and b/jobs/Backend/Task/.vs/ProjectEvaluation/exchangerateupdater.projects.v9.bin differ
diff --git a/jobs/Backend/Task/.vs/ProjectEvaluation/exchangerateupdater.strings.v9.bin b/jobs/Backend/Task/.vs/ProjectEvaluation/exchangerateupdater.strings.v9.bin
new file mode 100644
index 0000000000..afe08be56b
Binary files /dev/null and b/jobs/Backend/Task/.vs/ProjectEvaluation/exchangerateupdater.strings.v9.bin differ
diff --git a/jobs/Backend/Task/ExchangeRateProvider.cs b/jobs/Backend/Task/ExchangeRateProvider.cs
deleted file mode 100644
index 6f82a97fbe..0000000000
--- 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
index 2fc654a12b..463cc45993 100644
--- a/jobs/Backend/Task/ExchangeRateUpdater.csproj
+++ b/jobs/Backend/Task/ExchangeRateUpdater.csproj
@@ -5,4 +5,9 @@
net6.0
+
+
+
+
+
\ No newline at end of file
diff --git a/jobs/Backend/Task/ExchangeRateUpdater.sln b/jobs/Backend/Task/ExchangeRateUpdater.sln
index 89be84daff..9e294baa09 100644
--- a/jobs/Backend/Task/ExchangeRateUpdater.sln
+++ b/jobs/Backend/Task/ExchangeRateUpdater.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-VisualStudioVersion = 14.0.25123.0
+# Visual Studio Version 17
+VisualStudioVersion = 17.14.36811.4
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExchangeRateUpdater", "ExchangeRateUpdater.csproj", "{7B2695D6-D24C-4460-A58E-A10F08550CE0}"
EndProject
@@ -19,4 +19,7 @@ Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {A2D251C4-D515-440F-B0FB-050BDDD9A5F3}
+ EndGlobalSection
EndGlobal
diff --git a/jobs/Backend/Task/Currency.cs b/jobs/Backend/Task/Models/CurrencyModel.cs
similarity index 71%
rename from jobs/Backend/Task/Currency.cs
rename to jobs/Backend/Task/Models/CurrencyModel.cs
index f375776f25..40028e1477 100644
--- a/jobs/Backend/Task/Currency.cs
+++ b/jobs/Backend/Task/Models/CurrencyModel.cs
@@ -1,8 +1,8 @@
-namespace ExchangeRateUpdater
+namespace ExchangeRateUpdater.Models
{
- public class Currency
+ public class CurrencyModel
{
- public Currency(string code)
+ public CurrencyModel(string code)
{
Code = code;
}
diff --git a/jobs/Backend/Task/Models/CurrencyRateModel.cs b/jobs/Backend/Task/Models/CurrencyRateModel.cs
new file mode 100644
index 0000000000..f34d324bc3
--- /dev/null
+++ b/jobs/Backend/Task/Models/CurrencyRateModel.cs
@@ -0,0 +1,28 @@
+using System.Text.Json.Serialization;
+
+namespace ExchangeRateUpdater.Models
+{
+ public class CurrencyRateModel
+ {
+ [JsonPropertyName("validFor")]
+ public string ValidFor { get; set; }
+
+ [JsonPropertyName("order")]
+ public int Order { get; set; }
+
+ [JsonPropertyName("country")]
+ public string Country { get; set; }
+
+ [JsonPropertyName("currency")]
+ public string Currency { get; set; }
+
+ [JsonPropertyName("amount")]
+ public int Amount { get; set; }
+
+ [JsonPropertyName("currencyCode")]
+ public string CurrencyCode { get; set; }
+
+ [JsonPropertyName("rate")]
+ public decimal Rate { get; set; }
+ }
+}
diff --git a/jobs/Backend/Task/ExchangeRate.cs b/jobs/Backend/Task/Models/ExchangeRateModel.cs
similarity index 52%
rename from jobs/Backend/Task/ExchangeRate.cs
rename to jobs/Backend/Task/Models/ExchangeRateModel.cs
index 58c5bb10e0..9889f950ba 100644
--- a/jobs/Backend/Task/ExchangeRate.cs
+++ b/jobs/Backend/Task/Models/ExchangeRateModel.cs
@@ -1,17 +1,17 @@
-namespace ExchangeRateUpdater
+namespace ExchangeRateUpdater.Models
{
- public class ExchangeRate
+ public class ExchangeRateModel
{
- public ExchangeRate(Currency sourceCurrency, Currency targetCurrency, decimal value)
+ public ExchangeRateModel(CurrencyModel sourceCurrency, CurrencyModel targetCurrency, decimal value)
{
SourceCurrency = sourceCurrency;
TargetCurrency = targetCurrency;
Value = value;
}
- public Currency SourceCurrency { get; }
+ public CurrencyModel SourceCurrency { get; }
- public Currency TargetCurrency { get; }
+ public CurrencyModel TargetCurrency { get; }
public decimal Value { get; }
diff --git a/jobs/Backend/Task/Program.cs b/jobs/Backend/Task/Program.cs
index 379a69b1f8..072b2f51df 100644
--- a/jobs/Backend/Task/Program.cs
+++ b/jobs/Backend/Task/Program.cs
@@ -1,30 +1,57 @@
-using System;
+using ExchangeRateUpdater.Models;
+using ExchangeRateUpdater.Providers;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using System;
using System.Collections.Generic;
using System.Linq;
+using System.Net.Http.Headers;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
namespace ExchangeRateUpdater
{
public static class Program
{
- private static IEnumerable currencies = new[]
+ 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")
+ new CurrencyModel("USD"),
+ new CurrencyModel("EUR"),
+ new CurrencyModel("CZK"),
+ new CurrencyModel("JPY"),
+ new CurrencyModel("KES"),
+ new CurrencyModel("RUB"),
+ new CurrencyModel("THB"),
+ new CurrencyModel("TRY"),
+ new CurrencyModel("XYZ")
};
- public static void Main(string[] args)
+ public static async Task Main(string[] args)
{
+ using var host = Host.CreateDefaultBuilder(args)
+ .ConfigureLogging(logging =>
+ {
+ logging.ClearProviders();
+ logging.AddSimpleConsole();
+ })
+ .ConfigureServices(services =>
+ {
+ services.AddHttpClient(client =>
+ {
+ client.BaseAddress = new Uri("https://api.cnb.cz/");
+ client.Timeout = TimeSpan.FromSeconds(10);
+
+ client.DefaultRequestHeaders.Accept.Clear();
+ client.DefaultRequestHeaders.Accept.Add(
+ new MediaTypeWithQualityHeaderValue("application/json"));
+ });
+ })
+ .Build();
+
try
{
- var provider = new ExchangeRateProvider();
- var rates = provider.GetExchangeRates(currencies);
+ var provider = host.Services.GetRequiredService();
+ var rates = await provider.GetExchangeRatesAsync(currencies);
Console.WriteLine($"Successfully retrieved {rates.Count()} exchange rates:");
foreach (var rate in rates)
diff --git a/jobs/Backend/Task/Providers/ExchangeRateProvider.cs b/jobs/Backend/Task/Providers/ExchangeRateProvider.cs
new file mode 100644
index 0000000000..9f97afad19
--- /dev/null
+++ b/jobs/Backend/Task/Providers/ExchangeRateProvider.cs
@@ -0,0 +1,54 @@
+using ExchangeRateUpdater.Interfaces;
+using ExchangeRateUpdater.Models;
+using ExchangeRateUpdater.Responses;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Text.Json;
+using System.Threading.Tasks;
+
+namespace ExchangeRateUpdater.Providers
+{
+ public class ExchangeRateProvider
+ {
+ private readonly HttpClient _httpClient;
+
+ public ExchangeRateProvider(HttpClient httpClient)
+ {
+ _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
+ }
+ ///
+ /// 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.
+ ///
+
+ private async Task> AccessCurrentExchangeRateFixingCZKAsync()
+ {
+ var exchangeRateFixingResponse = await _httpClient.GetStringAsync("cnbapi/exrates/daily") ?? throw new Exception("Could not retrieve exchange rate fixing from CNB.");
+
+ ExchangeRateFixingResponse exchangeRateFixing = JsonSerializer.Deserialize(exchangeRateFixingResponse);
+
+ if (exchangeRateFixing?.Rates == null)
+ throw new InvalidOperationException("CNB response did not contain 'rates'.");
+
+ List exchangeRates = new List();
+
+ foreach (var line in exchangeRateFixing.Rates)
+ {
+ exchangeRates.Add(new ExchangeRateModel(new CurrencyModel(line.CurrencyCode), new CurrencyModel("CZK"), line.Amount > 1 ? line.Rate/line.Amount : line.Rate));
+ }
+
+ return exchangeRates;
+ }
+
+ public async Task> GetExchangeRatesAsync(IEnumerable currencies)
+ {
+ List exchanges = await AccessCurrentExchangeRateFixingCZKAsync();
+
+ return exchanges.Where(ex => currencies.Any(cur => cur.Code == ex.TargetCurrency.Code) && currencies.Any(cur => cur.Code == ex.SourceCurrency.Code));
+ }
+ }
+}
diff --git a/jobs/Backend/Task/Readme.md b/jobs/Backend/Task/Readme.md
new file mode 100644
index 0000000000..c60099eee4
--- /dev/null
+++ b/jobs/Backend/Task/Readme.md
@@ -0,0 +1,8 @@
+I refactored the provider into a real implementation by introducing a clear separation
+between domain models and API responses. The provider is now injected via the .NET Generic Host using AddHttpClient,
+which centralizes HTTP configuration (base address, timeout, headers) and improves maintainability.
+
+Exchange rates are fetched asynchronously from the CNB daily endpoint, deserialized with System.Text.Json,
+and normalized for currencies quoted per multiple units (rate divided by amount).
+
+Finally, results are filtered to only include currencies requested by the caller from what the source provides.
\ No newline at end of file
diff --git a/jobs/Backend/Task/Responses/ExchangeRateFixingResponse.cs b/jobs/Backend/Task/Responses/ExchangeRateFixingResponse.cs
new file mode 100644
index 0000000000..35b4e883b3
--- /dev/null
+++ b/jobs/Backend/Task/Responses/ExchangeRateFixingResponse.cs
@@ -0,0 +1,12 @@
+using ExchangeRateUpdater.Models;
+using System.Collections.Generic;
+using System.Text.Json.Serialization;
+
+namespace ExchangeRateUpdater.Responses
+{
+ public class ExchangeRateFixingResponse
+ {
+ [JsonPropertyName("rates")]
+ public List Rates { get; set; }
+ }
+}