Add currency pegging admin page.

This commit is contained in:
2020-08-07 21:46:48 +01:00
parent 43e1c282b9
commit db16a77988
14 changed files with 980 additions and 1 deletions

View File

@@ -39,5 +39,8 @@ namespace Marechai.Database.Models
public DateTime Start { get; set; } public DateTime Start { get; set; }
[DataType(DataType.Date)] [DataType(DataType.Date)]
public DateTime? End { get; set; } public DateTime? End { get; set; }
public string SourceCode { get; set; }
public string DestinationCode { get; set; }
} }
} }

View File

@@ -2,7 +2,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<Version>4.0.0.1800</Version> <Version>4.0.0.1801</Version>
<Company>Canary Islands Computer Museum</Company> <Company>Canary Islands Computer Museum</Company>
<Copyright>Copyright © 2003-2020 Natalia Portillo</Copyright> <Copyright>Copyright © 2003-2020 Natalia Portillo</Copyright>
<Product>Canary Islands Computer Museum Website</Product> <Product>Canary Islands Computer Museum Website</Product>

View File

@@ -0,0 +1,110 @@
@{
/******************************************************************************
// MARECHAI: Master repository of computing history artifacts information
// ----------------------------------------------------------------------------
//
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2003-2020 Natalia Portillo
*******************************************************************************/
}
@page "/admin/currency_pegging"
@using Marechai.Database.Models
@inherits OwningComponentBase<CurrencyPeggingService>
@inject IStringLocalizer<CurrencyPeggingService> L
@inject Microsoft.AspNetCore.Identity.UserManager<ApplicationUser> UserManager
@inject AuthenticationStateProvider AuthenticationStateProvider
@attribute [Authorize(Roles = "UberAdmin, Admin")]
<h3>@L["Currency pegging"]</h3>
@if (_peggings is null)
{
<p>@L["Loading..."]</p>
return;
}
<p>
<a class="btn btn-primary" href="/admin/currency_pegging/create">@L["Create new"]</a>
</p>
<table class="table table-striped">
<thead>
<tr>
<th>
@L["Source currency"]
</th>
<th>
@L["Destination currency"]
</th>
<th>
@L["Starting date"]
</th>
<th>
@L["Ending date"]
</th>
<th>
@L["Pegging"]
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in _peggings)
{
<tr>
<td>
@item.SourceName
</td>
<td>
@item.DestinationName
</td>
<td>
@item.Start.ToLongDateString()
</td>
<td>
@item.End?.ToLongDateString()
</td>
<td>
@($"{item.Ratio:F2}")
</td>
<td>
<a class="btn btn-primary" href="/admin/currency_pegging/details/@item.Id">@L["Details"]</a>
<a class="btn btn-secondary" href="/admin/currency_pegging/edit/@item.Id">@L["Edit"]</a>
<Button Color="Color.Danger" Clicked="() => {ShowModal(item.Id);}">@L["Delete"]</Button>
</td>
</tr>
}
</tbody>
</table>
<Modal @ref="_frmDelete" IsCentered="true" Closing="@ModalClosing">
<ModalBackdrop/>
<ModalContent Centered="true">
<ModalHeader>
<ModalTitle>@L["Delete currency pegging"]</ModalTitle>
<CloseButton Clicked="@HideModal"/>
</ModalHeader>
<ModalBody>
<Text>@string.Format(@L["Are you sure you want to delete the pegging of {0:F} happened to currency {1} with currency {2} since {3}?"], _currentPegging?.Ratio, _currentPegging?.SourceName, _currentPegging?.DestinationName, _currentPegging?.Start.ToLongDateString())</Text>
</ModalBody>
<ModalFooter>
<Button Color="Color.Primary" Clicked="@HideModal" Disabled="@_deleteInProgress">@L["Cancel"]</Button>
<Button Color="Color.Danger" Clicked="@ConfirmDelete" Disabled="@_deleteInProgress">@L["Delete"]</Button>
</ModalFooter>
</ModalContent>
</Modal>

View File

@@ -0,0 +1,88 @@
/******************************************************************************
// MARECHAI: Master repository of computing history artifacts information
// ----------------------------------------------------------------------------
//
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2003-2020 Natalia Portillo
*******************************************************************************/
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Blazorise;
using Marechai.ViewModels;
using Microsoft.AspNetCore.Components.Authorization;
namespace Marechai.Pages.Admin
{
public partial class CurrencyPegging
{
CurrencyPeggingViewModel _currentPegging;
bool _deleteInProgress;
Modal _frmDelete;
bool _loaded;
List<CurrencyPeggingViewModel> _peggings;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if(_loaded)
return;
_peggings = await Service.GetAsync();
_loaded = true;
StateHasChanged();
}
void ShowModal(long itemId)
{
_currentPegging = _peggings.FirstOrDefault(n => n.Id == itemId);
_frmDelete.Show();
}
void HideModal() => _frmDelete.Hide();
async void ConfirmDelete()
{
if(_currentPegging is null)
return;
_deleteInProgress = true;
_peggings = null;
AuthenticationState authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
// Yield thread to let UI to update
await Task.Yield();
await Service.DeleteAsync(_currentPegging.Id, (await UserManager.GetUserAsync(authState.User)).Id);
_peggings = await Service.GetAsync();
_deleteInProgress = false;
_frmDelete.Hide();
// Yield thread to let UI to update
await Task.Yield();
// Tell we finished loading
StateHasChanged();
}
void ModalClosing(ModalClosingEventArgs obj) => _currentPegging = null;
}
}

View File

@@ -0,0 +1,124 @@
@{
/******************************************************************************
// MARECHAI: Master repository of computing history artifacts information
// ----------------------------------------------------------------------------
//
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2003-2020 Natalia Portillo
*******************************************************************************/
}
@page "/admin/currency_pegging/details/{Id:int}"
@page "/admin/currency_pegging/edit/{Id:int}"
@page "/admin/currency_pegging/create"
@using Marechai.Database.Models
@inherits OwningComponentBase<CurrencyPeggingService>
@inject IStringLocalizer<CurrencyPeggingService> L
@inject Iso4217Service CurrenciesService
@inject NavigationManager NavigationManager
@inject IWebHostEnvironment Host
@inject Microsoft.AspNetCore.Identity.UserManager<ApplicationUser> UserManager
@inject AuthenticationStateProvider AuthenticationStateProvider
@attribute [Authorize(Roles = "UberAdmin, Admin")]
<h3>@L["Currency pegging details"]</h3>
<hr />
@if (!_loaded)
{
<p align="center">@L["Loading..."]</p>
return;
}
<div>
<Field>
<FieldLabel>@L["Source currency"]</FieldLabel>
<Select Disabled="!_editing" TValue="string" @bind-SelectedValue="@_model.SourceCode">
@foreach (var currency in _currencies)
{
<SelectItem TValue="string" Value="@currency.Code">@currency.Name</SelectItem>
}
</Select>
</Field>
<Field>
<FieldLabel>@L["Destination currency"]</FieldLabel>
<Select Disabled="!_editing" TValue="string" @bind-SelectedValue="@_model.DestinationCode">
@foreach (var currency in _currencies)
{
<SelectItem TValue="string" Value="@currency.Code">@currency.Name</SelectItem>
}
</Select>
</Field>
<Field>
<FieldLabel>@L["Pegging (ratio)"]</FieldLabel>
<Validation Validator="@ValidatePegging">
<NumericEdit Disabled="!_editing" TValue="float" Decimals="3" @bind-Value="@_model.Ratio">
<Feedback>
<ValidationError>@L["Please enter a valid pegging."]</ValidationError>
</Feedback>
</NumericEdit>
</Validation>
</Field>
<Field>
<FieldLabel>@L["Start date"]</FieldLabel>
<Validation Validator="@ValidateStart">
<DateEdit Disabled="!_editing" TValue="DateTime" @bind-Date="@_model.Start">
<Feedback>
<ValidationError>@L["Please enter a start date."]</ValidationError>
</Feedback>
</DateEdit>
</Validation>
</Field>
@if (_editing || _model.End.HasValue)
{
<Field>
<FieldLabel>@L["End date"]</FieldLabel>
@if (_editing)
{
<Check TValue="bool" @bind-Checked="@_unknownEnd">@L["Unknown or never (end date)"]</Check>
}
@if (!_editing ||
(!_unknownEnd))
{
<Validation Validator="@ValidateEnd">
<DateEdit Disabled="!_editing" TValue="DateTime?" @bind-Date="@_model.End">
<Feedback>
<ValidationError>@L["Please enter an ending date."]</ValidationError>
</Feedback>
</DateEdit>
</Validation>
}
</Field>
}
</div>
<div>
@if (!_editing)
{
<Button Color="Color.Primary" Clicked="@OnEditClicked">@L["Edit"]</Button>
}
else
{
<Button Color="Color.Success" Clicked="@OnSaveClicked">@L["Save"]</Button>
<Button Color="Color.Danger" Clicked="@OnCancelClicked">@L["Cancel"]</Button>
}
<a href="/admin/currency_pegging" class="btn btn-secondary">@L["Back to list"]</a>
</div>

View File

@@ -0,0 +1,183 @@
/******************************************************************************
// MARECHAI: Master repository of computing history artifacts information
// ----------------------------------------------------------------------------
//
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2003-2020 Natalia Portillo
*******************************************************************************/
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Blazorise;
using Marechai.Database.Models;
using Marechai.ViewModels;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization;
namespace Marechai.Pages.Admin.Details
{
public partial class CurrencyPegging
{
AuthenticationState _authState;
bool _creating;
List<Iso4217> _currencies;
bool _editing;
bool _loaded;
CurrencyPeggingViewModel _model;
bool _unknownEnd;
[Parameter]
public int Id { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if(_loaded)
return;
_loaded = true;
_creating = NavigationManager.ToBaseRelativePath(NavigationManager.Uri).ToLowerInvariant().
StartsWith("admin/currency_pegging/create",
StringComparison.InvariantCulture);
if(Id <= 0 &&
!_creating)
return;
_currencies = await CurrenciesService.GetAsync();
_model = _creating ? new CurrencyPeggingViewModel() : await Service.GetAsync(Id);
_authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
_editing = _creating || NavigationManager.ToBaseRelativePath(NavigationManager.Uri).ToLowerInvariant().
StartsWith("admin/currency_pegging/edit/",
StringComparison.InvariantCulture);
if(_editing)
SetCheckboxes();
StateHasChanged();
}
void SetCheckboxes() => _unknownEnd = !_model.End.HasValue;
void OnEditClicked()
{
_editing = true;
SetCheckboxes();
StateHasChanged();
}
async void OnCancelClicked()
{
_editing = false;
if(_creating)
{
NavigationManager.ToBaseRelativePath("admin/currency_pegging");
return;
}
_model = await Service.GetAsync(Id);
SetCheckboxes();
StateHasChanged();
}
async void OnSaveClicked()
{
if(string.IsNullOrWhiteSpace(_model.SourceCode))
return;
if(string.IsNullOrWhiteSpace(_model.DestinationCode))
return;
if(_model.Start >= DateTime.UtcNow)
return;
if(_model.End >= DateTime.UtcNow ||
_model.End < _model.Start)
return;
if(_model.Ratio <= 0)
return;
if(_creating)
Id = await Service.CreateAsync(_model, (await UserManager.GetUserAsync(_authState.User)).Id);
else
await Service.UpdateAsync(_model, (await UserManager.GetUserAsync(_authState.User)).Id);
_editing = false;
_creating = false;
_model = await Service.GetAsync(Id);
SetCheckboxes();
StateHasChanged();
}
void ValidateStart(ValidatorEventArgs e)
{
e.Status = ValidationStatus.Success;
if((DateTime)e.Value <= DateTime.UtcNow)
return;
e.Status = ValidationStatus.Error;
e.ErrorText = L["Starting date must be before now."];
}
void ValidatePegging(ValidatorEventArgs e)
{
e.Status = ValidationStatus.Success;
if((float)e.Value > 0)
return;
e.Status = ValidationStatus.Error;
e.ErrorText = L["Pegging must be bigger than 0."];
}
void ValidateEnd(ValidatorEventArgs e)
{
e.Status = ValidationStatus.Success;
if(e.Value is null)
{
e.Status = ValidationStatus.Error;
e.ErrorText = L["Please enter an ending date."];
return;
}
if((DateTime?)e.Value > DateTime.UtcNow)
{
e.Status = ValidationStatus.Error;
e.ErrorText = L["Ending date must be before now."];
return;
}
if(!((DateTime?)e.Value < _model.Start))
return;
e.Status = ValidationStatus.Error;
e.ErrorText = L["Ending date must be before starting date."];
}
}
}

View File

@@ -106,5 +106,8 @@
<li> <li>
<a href="/admin/currency_inflation">@L["Currency inflation"]</a> <a href="/admin/currency_inflation">@L["Currency inflation"]</a>
</li> </li>
<li>
<a href="/admin/currency_pegging">@L["Currency pegging"]</a>
</li>
</ul> </ul>
</div> </div>

View File

@@ -20,4 +20,7 @@
<data name="Currency inflation" xml:space="preserve"> <data name="Currency inflation" xml:space="preserve">
<value>Currency inflation</value> <value>Currency inflation</value>
</data> </data>
<data name="Currency pegging" xml:space="preserve">
<value>Currency pegging</value>
</data>
</root> </root>

View File

@@ -219,4 +219,7 @@
<data name="Currency inflation" xml:space="preserve"> <data name="Currency inflation" xml:space="preserve">
<value>Inflación de divisa</value> <value>Inflación de divisa</value>
</data> </data>
<data name="Currency pegging" xml:space="preserve">
<value>Vinculación de divisa</value>
</data>
</root> </root>

View File

@@ -0,0 +1,101 @@
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Currency pegging" xml:space="preserve">
<value>Currency pegging</value>
</data>
<data name="Loading..." xml:space="preserve">
<value>Loading...</value>
</data>
<data name="Create new" xml:space="preserve">
<value>Create new</value>
</data>
<data name="Source currency" xml:space="preserve">
<value>Source currency</value>
</data>
<data name="Destination currency" xml:space="preserve">
<value>Destination currency</value>
</data>
<data name="Starting date" xml:space="preserve">
<value>Starting date</value>
</data>
<data name="Ending date" xml:space="preserve">
<value>Ending date</value>
</data>
<data name="Pegging" xml:space="preserve">
<value>Pegging</value>
</data>
<data name="Details" xml:space="preserve">
<value>Details</value>
</data>
<data name="Edit" xml:space="preserve">
<value>Edit</value>
</data>
<data name="Delete" xml:space="preserve">
<value>Delete</value>
</data>
<data name="Delete currency pegging" xml:space="preserve">
<value>Delete currency pegging</value>
</data>
<data name="Are you sure you want to delete the pegging of {0:F} happened to currency {1} with currency {2} since {3}?" xml:space="preserve">
<value>Are you sure you want to delete the pegging of {0:F} happened to currency {1} with currency {2} since {3}?</value>
</data>
<data name="Cancel" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="Currency pegging details" xml:space="preserve">
<value>Currency pegging details</value>
</data>
<data name="Pegging (ratio)" xml:space="preserve">
<value>Pegging (ratio)</value>
</data>
<data name="Please enter a valid pegging." xml:space="preserve">
<value>Please enter a valid pegging.</value>
</data>
<data name="Start date" xml:space="preserve">
<value>Start date</value>
</data>
<data name="Please enter a start date." xml:space="preserve">
<value>Please enter a start date.</value>
</data>
<data name="End date" xml:space="preserve">
<value>End date</value>
</data>
<data name="Unknown or never (end date)" xml:space="preserve">
<value>Unknown or never</value>
</data>
<data name="Please enter an ending date." xml:space="preserve">
<value>Please enter an ending date.</value>
</data>
<data name="Save" xml:space="preserve">
<value>Save</value>
</data>
<data name="Back to list" xml:space="preserve">
<value>Back to list</value>
</data>
<data name="Starting date must be before now." xml:space="preserve">
<value>Starting date must be before now.</value>
</data>
<data name="Pegging must be bigger than 0." xml:space="preserve">
<value>Pegging must be bigger than 0.</value>
</data>
<data name="Please enter an ending date." xml:space="preserve">
<value>Please enter an ending date.</value>
</data>
<data name="Ending date must be before now." xml:space="preserve">
<value>Ending date must be before now.</value>
</data>
<data name="Ending date must be before starting date." xml:space="preserve">
<value>Ending date must be before starting date.</value>
</data>
</root>

View File

@@ -0,0 +1,205 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- ReSharper disable MarkupTextTypo -->
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Currency pegging" xml:space="preserve">
<value>Vinculación de divisa</value>
</data>
<data name="Loading..." xml:space="preserve">
<value>Cargando...</value>
</data>
<data name="Create new" xml:space="preserve">
<value>Crear nueva</value>
</data>
<data name="Source currency" xml:space="preserve">
<value>Divisa de origen</value>
</data>
<data name="Destination currency" xml:space="preserve">
<value>Divisa de destino</value>
</data>
<data name="Starting date" xml:space="preserve">
<value>Fecha de comienzo</value>
</data>
<data name="Ending date" xml:space="preserve">
<value>Fecha de finalización</value>
</data>
<data name="Pegging" xml:space="preserve">
<value>Vinculación</value>
</data>
<data name="Details" xml:space="preserve">
<value>Detalles</value>
</data>
<data name="Edit" xml:space="preserve">
<value>Editar</value>
</data>
<data name="Delete" xml:space="preserve">
<value>Eliminar</value>
</data>
<data name="Delete currency pegging" xml:space="preserve">
<value>Eliminar vinculación de divisa</value>
</data>
<data name="Are you sure you want to delete the pegging of {0:F} happened to currency {1} with currency {2} since {3}?" xml:space="preserve">
<value>¿Estás seguro de querer eliminar la vinculación de divisa de {0:F} en la divisa {1} con la divisa {2} desde {3}?</value>
</data>
<data name="Cancel" xml:space="preserve">
<value>Cancelar</value>
</data>
<data name="Currency pegging details" xml:space="preserve">
<value>Detalles de vinculación de divisa</value>
</data>
<data name="Pegging (ratio)" xml:space="preserve">
<value>Vinculación (relación)</value>
</data>
<data name="Please enter a valid pegging." xml:space="preserve">
<value>Por favor introduce una vinculación válida.</value>
</data>
<data name="Start date" xml:space="preserve">
<value>Fecha de comienzo</value>
</data>
<data name="Please enter a start date." xml:space="preserve">
<value>Por favor introduce una fecha de comienzo válida.</value>
</data>
<data name="End date" xml:space="preserve">
<value>Fecha de finalización</value>
</data>
<data name="Unknown or never (end date)" xml:space="preserve">
<value>Desconocida o nunca</value>
</data>
<data name="Please enter an ending date." xml:space="preserve">
<value>Por favor introduce una fecha de finalización.</value>
</data>
<data name="Save" xml:space="preserve">
<value>Guardar</value>
</data>
<data name="Back to list" xml:space="preserve">
<value>Volver a la lista</value>
</data>
<data name="Starting date must be before now." xml:space="preserve">
<value>La fecha de comienzo debe ser anterior a ahora.</value>
</data>
<data name="Pegging must be bigger than 0." xml:space="preserve">
<value>La vinculación debe ser mayor de 0.</value>
</data>
<data name="Ending date must be before now." xml:space="preserve">
<value>La fecha de finalización debe ser anterior a ahora.</value>
</data>
<data name="Ending date must be before starting date." xml:space="preserve">
<value>La fecha de finalización debe ser anterior a la de comienzo.</value>
</data>
</root>

View File

@@ -0,0 +1,115 @@
/******************************************************************************
// MARECHAI: Master repository of computing history artifacts information
// ----------------------------------------------------------------------------
//
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2003-2020 Natalia Portillo
*******************************************************************************/
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Marechai.Database.Models;
using Marechai.ViewModels;
using Microsoft.EntityFrameworkCore;
namespace Marechai.Services
{
public class CurrencyPeggingService
{
readonly MarechaiContext _context;
public CurrencyPeggingService(MarechaiContext context) => _context = context;
public async Task<List<CurrencyPeggingViewModel>> GetAsync() => await _context.
CurrenciesPegging.
OrderBy(i => i.Source.Name).
ThenBy(i => i.Destination.Name).
ThenBy(i => i.Start).ThenBy(i => i.End).
Select(i => new CurrencyPeggingViewModel
{
Id = i.Id,
SourceCode = i.Source.Code,
SourceName = i.Source.Name,
DestinationCode = i.Source.Code,
DestinationName = i.Source.Name,
Ratio = i.Ratio,
Start = i.Start,
End = i.End
}).ToListAsync();
public async Task<CurrencyPeggingViewModel> GetAsync(int id) =>
await _context.CurrenciesPegging.Where(b => b.Id == id).Select(i => new CurrencyPeggingViewModel
{
Id = i.Id,
SourceCode = i.Source.Code,
SourceName = i.Source.Name,
DestinationCode = i.Destination.Code,
DestinationName = i.Destination.Name,
Ratio = i.Ratio,
Start = i.Start,
End = i.End
}).FirstOrDefaultAsync();
public async Task UpdateAsync(CurrencyPeggingViewModel viewModel, string userId)
{
CurrencyPegging model = await _context.CurrenciesPegging.FindAsync(viewModel.Id);
if(model is null)
return;
model.SourceCode = viewModel.SourceCode;
model.DestinationCode = viewModel.DestinationCode;
model.Ratio = viewModel.Ratio;
model.Start = viewModel.Start;
model.End = viewModel.End;
await _context.SaveChangesWithUserAsync(userId);
}
public async Task<int> CreateAsync(CurrencyPeggingViewModel viewModel, string userId)
{
var model = new CurrencyPegging
{
SourceCode = viewModel.SourceCode,
DestinationCode = viewModel.DestinationCode,
Ratio = viewModel.Ratio,
Start = viewModel.Start,
End = viewModel.End
};
await _context.CurrenciesPegging.AddAsync(model);
await _context.SaveChangesWithUserAsync(userId);
return model.Id;
}
public async Task DeleteAsync(int id, string userId)
{
CurrencyPegging item = await _context.CurrenciesPegging.FindAsync(id);
if(item is null)
return;
_context.CurrenciesPegging.Remove(item);
await _context.SaveChangesWithUserAsync(userId);
}
}
}

View File

@@ -70,6 +70,7 @@ namespace Marechai.Services
services.AddScoped<BooksService>(); services.AddScoped<BooksService>();
services.AddScoped<CurrencyInflationService>(); services.AddScoped<CurrencyInflationService>();
services.AddScoped<Iso4217Service>(); services.AddScoped<Iso4217Service>();
services.AddScoped<CurrencyPeggingService>();
} }
} }
} }

View File

@@ -0,0 +1,40 @@
/******************************************************************************
// MARECHAI: Master repository of computing history artifacts information
// ----------------------------------------------------------------------------
//
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// --[ License ] --------------------------------------------------------------
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2003-2020 Natalia Portillo
*******************************************************************************/
using System;
namespace Marechai.ViewModels
{
public class CurrencyPeggingViewModel : BaseViewModel<int>
{
public string SourceCode { get; set; }
public string DestinationCode { get; set; }
public string SourceName { get; set; }
public string DestinationName { get; set; }
public float Ratio { get; set; }
public DateTime Start { get; set; }
public DateTime? End { get; set; }
}
}