From 0a69d047303dd834639df6ae17bfdb42fb3427d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Jos=C3=A9=20Alves=20Pires?= Date: Wed, 3 Feb 2021 15:31:41 -0300 Subject: [PATCH] insert operation --- .../DI/DependencyInjection.cs | 3 +- .../Persistence/VirtualMindDbContext.cs | 7 +++ .../VirtuaMind.Infrastructure.csproj | 1 + .../Commands/CreateOperationCommand.cs | 47 ++++++++++++++----- .../Exceptions/ValidationException.cs | 6 +++ .../Interfaces/IVirtualMindDbContext.cs | 6 ++- .../VirtualMind.Application.csproj | 4 -- .../Entities/OperationCurrency.cs | 13 +++++ VirtualMind.WebApp/Startup.cs | 31 +++++++++++- 9 files changed, 98 insertions(+), 20 deletions(-) create mode 100644 VirtualMind.Domain/Entities/OperationCurrency.cs diff --git a/VirtuaMind.Infrastructure/DI/DependencyInjection.cs b/VirtuaMind.Infrastructure/DI/DependencyInjection.cs index ce6b7cd..5d31adc 100644 --- a/VirtuaMind.Infrastructure/DI/DependencyInjection.cs +++ b/VirtuaMind.Infrastructure/DI/DependencyInjection.cs @@ -1,4 +1,5 @@ using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using VirtualMind.Application.Interfaces; using VirtuaMind.Infrastructure.Persistence; @@ -21,7 +22,7 @@ private static void AddDatabase(IServiceCollection services) services.AddDbContext(options => options.UseInMemoryDatabase("VirtualMindDB")); - services.AddScoped(provider => provider.GetService()); + services.AddScoped(provider => provider.GetService()); } private static void AddRestServicesDependency(IServiceCollection services) diff --git a/VirtuaMind.Infrastructure/Persistence/VirtualMindDbContext.cs b/VirtuaMind.Infrastructure/Persistence/VirtualMindDbContext.cs index a046443..645295c 100644 --- a/VirtuaMind.Infrastructure/Persistence/VirtualMindDbContext.cs +++ b/VirtuaMind.Infrastructure/Persistence/VirtualMindDbContext.cs @@ -15,6 +15,13 @@ public VirtualMindDbContext(DbContextOptions options): base(options) public DbSet Operations { get; set; } + public DbSet OperationCurrencies { get; set; } + + public override int SaveChanges() + { + return base.SaveChanges(); + } + public override async Task SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken()) { foreach (Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry entry in ChangeTracker.Entries()) diff --git a/VirtuaMind.Infrastructure/VirtuaMind.Infrastructure.csproj b/VirtuaMind.Infrastructure/VirtuaMind.Infrastructure.csproj index 6e00c01..1f6764c 100644 --- a/VirtuaMind.Infrastructure/VirtuaMind.Infrastructure.csproj +++ b/VirtuaMind.Infrastructure/VirtuaMind.Infrastructure.csproj @@ -6,6 +6,7 @@ + diff --git a/VirtualMind.Application/Commands/CreateOperationCommand.cs b/VirtualMind.Application/Commands/CreateOperationCommand.cs index 1505334..99faa0a 100644 --- a/VirtualMind.Application/Commands/CreateOperationCommand.cs +++ b/VirtualMind.Application/Commands/CreateOperationCommand.cs @@ -4,11 +4,14 @@ using MediatR; using VirtualMind.Application.Queries; using VirtualMind.Application.DTOs; -using System.Collections.Generic; using VirtualMind.Domain.Entities; using VirtualMind.Domain.Enums; using System; using VirtualMind.Application.Extensions; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using VirtualMind.Application.Exceptions; +using System.Globalization; namespace VirtualMind.Application.Commands { @@ -26,7 +29,8 @@ public class CreateOperationCommandHandler : IRequestHandler Handle(CreateOperationCommand request, CancellationToken cancellationToken) { - var currentQuote = await GetCurrentQuote(request.CurrencyType); + var currentQuote = await GetCurrentQuote(request.CurrencyType); var purchasedAmount = CalcPurchasedAmount(request, currentQuote); + var currency = (Currency)Enum.Parse(typeof(Currency), request.CurrencyType); - - - + await CheckLimitOperation(request.UserId, purchasedAmount, currency); var operation = new Operation { - Currency = (Currency)Enum.Parse(typeof(Currency), request.CurrencyType), + Currency = currency, UserId = request.UserId, RequestedAmount = request.RequestedAmount, CurrentQuote = currentQuote.Purchase.ConvertStringToDecimal(), @@ -51,12 +54,9 @@ public async Task Handle(CreateOperationCommand request, CancellationToken }; await VirtualMindDbContext.Operations.AddAsync(operation); - await VirtualMindDbContext.SaveChangesAsync(); - - return await Task.FromResult(0); + return await VirtualMindDbContext.SaveChangesAsync(); } - private async Task GetCurrentQuote(string currencyType) { var result = await CurrencyExchangeFactory.GetExchangeRate(currencyType); @@ -70,9 +70,30 @@ private async Task GetCurrentQuote(string currencyType) return currnetQuote; } - private static decimal CalcPurchasedAmount(CreateOperationCommand request, ExchangeRateDTO currentQuote) + private decimal CalcPurchasedAmount(CreateOperationCommand request, ExchangeRateDTO currentQuote) { return decimal.Round(request.RequestedAmount / currentQuote.Purchase.ConvertStringToDecimal(), 2); - } + } + + private async Task CheckLimitOperation(int userId, decimal purchasedAmount, Currency currency) + { + var userSubmittedOperations = await VirtualMindDbContext.Operations + .Where(o => o.UserId == userId && o.Currency == currency && o.Created.Month == DateTime.Now.Month) + .ToListAsync(); + + var currencyParameters = await VirtualMindDbContext.OperationCurrencies.Where(c => c.Currency == currency) + .FirstOrDefaultAsync(); + + var total = userSubmittedOperations.Sum(o => o.PurchasedAmount) + purchasedAmount; + + if (total > currencyParameters.Limit) + { + throw new ValidationException("InvalidOperation", new[] + { + $"This operation is not allowed because it exceeds the limits for the currency [{currency}] and user.", + $"Limit: [{currencyParameters.Limit}], Operation Total: [{total.ToString(new CultureInfo("en-US"))}]" + }); + } + } } } diff --git a/VirtualMind.Application/Exceptions/ValidationException.cs b/VirtualMind.Application/Exceptions/ValidationException.cs index 0b53c4d..7648517 100644 --- a/VirtualMind.Application/Exceptions/ValidationException.cs +++ b/VirtualMind.Application/Exceptions/ValidationException.cs @@ -21,6 +21,12 @@ public ValidationException(IEnumerable failures) .ToDictionary(failureGroup => failureGroup.Key, failureGroup => failureGroup.ToArray()); } + public ValidationException(string type, string[] errorMessages) + : this() + { + Errors.Add(type, errorMessages); + } + public IDictionary Errors { get; } } } diff --git a/VirtualMind.Application/Interfaces/IVirtualMindDbContext.cs b/VirtualMind.Application/Interfaces/IVirtualMindDbContext.cs index ad2956d..369bcdb 100644 --- a/VirtualMind.Application/Interfaces/IVirtualMindDbContext.cs +++ b/VirtualMind.Application/Interfaces/IVirtualMindDbContext.cs @@ -9,6 +9,10 @@ public interface IVirtualMindDbContext { DbSet Operations { get; set; } - Task SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken()); + DbSet OperationCurrencies { get; set; } + + Task SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken()); + + int SaveChanges(); } } diff --git a/VirtualMind.Application/VirtualMind.Application.csproj b/VirtualMind.Application/VirtualMind.Application.csproj index 5626529..afe1b5e 100644 --- a/VirtualMind.Application/VirtualMind.Application.csproj +++ b/VirtualMind.Application/VirtualMind.Application.csproj @@ -16,8 +16,4 @@ - - - - diff --git a/VirtualMind.Domain/Entities/OperationCurrency.cs b/VirtualMind.Domain/Entities/OperationCurrency.cs new file mode 100644 index 0000000..36a9325 --- /dev/null +++ b/VirtualMind.Domain/Entities/OperationCurrency.cs @@ -0,0 +1,13 @@ +using VirtualMind.Domain.Enums; + +namespace VirtualMind.Domain.Entities +{ + public class OperationCurrency + { + public int Id { get; set; } + + public Currency Currency { get; set; } + + public decimal Limit { get; set; } + } +} diff --git a/VirtualMind.WebApp/Startup.cs b/VirtualMind.WebApp/Startup.cs index 9da2431..5c06b09 100644 --- a/VirtualMind.WebApp/Startup.cs +++ b/VirtualMind.WebApp/Startup.cs @@ -4,7 +4,9 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using System.Collections.Generic; using VirtualMind.Application.Configurations; +using VirtualMind.Application.Interfaces; using VirtualMind.WebApp.Filters; using VirtuaMind.Infrastructure.DI; @@ -21,7 +23,7 @@ public Startup(IConfiguration configuration) // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) - { + { services.AddApplicationDI(); services.RegisterGlobalFilters(); services.AddInfrastructure(); @@ -53,6 +55,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseRouting(); + AddInitialValues(app); + app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( @@ -73,5 +77,30 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) } }); } + + private void AddInitialValues(IApplicationBuilder app) + { + using (var serviceScope = app.ApplicationServices.CreateScope()) + { + var context = serviceScope.ServiceProvider.GetService(); + + var listCurrency = new List + { + new Domain.Entities.OperationCurrency + { + Currency = Domain.Enums.Currency.BRL, + Limit = 300 + }, + new Domain.Entities.OperationCurrency + { + Currency = Domain.Enums.Currency.USD, + Limit = 200 + }, + }; + + context.OperationCurrencies.AddRange(listCurrency); + context.SaveChanges(); + } + } } }