diff --git a/README.md b/README.md index 9074ed0..6975a89 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ - EasyNetQ - Application Query Stack e Specification Pattern - NetDevPack +- Facade # Ferramentas - Visual Studio 2022 - Version 17.11.4 ++ diff --git a/src/building blocks/JSE.Core/Messages/Integration/PedidoAutorizadoIntegrationEvent.cs b/src/building blocks/JSE.Core/Messages/Integration/PedidoAutorizadoIntegrationEvent.cs new file mode 100644 index 0000000..fbeea69 --- /dev/null +++ b/src/building blocks/JSE.Core/Messages/Integration/PedidoAutorizadoIntegrationEvent.cs @@ -0,0 +1,16 @@ +namespace JSE.Core.Messages.Integration +{ + public class PedidoAutorizadoIntegrationEvent : IntegrationEvent + { + public Guid ClienteId { get; private set; } + public Guid PedidoId { get; private set; } + public IDictionary Itens { get; private set; } + + public PedidoAutorizadoIntegrationEvent(Guid clienteId, Guid pedidoId, IDictionary itens) + { + ClienteId = clienteId; + PedidoId = pedidoId; + Itens = itens; + } + } +} \ No newline at end of file diff --git a/src/services/JSE.Pagamento.API/appsettings.Development.json b/src/services/JSE.Pagamento.API/appsettings.Development.json index ec61c56..d96fd35 100644 --- a/src/services/JSE.Pagamento.API/appsettings.Development.json +++ b/src/services/JSE.Pagamento.API/appsettings.Development.json @@ -25,5 +25,4 @@ "DefaultApiKey": "ak_ewr4dsWehiwAT", "DefaultEncryptionKey": "ek_SweRsdFas4uT5" } - } diff --git a/src/services/JSE.Pedido.API/Application/DTO/PedidoDTO.cs b/src/services/JSE.Pedido.API/Application/DTO/PedidoDTO.cs index 44e8a44..b445cd2 100644 --- a/src/services/JSE.Pedido.API/Application/DTO/PedidoDTO.cs +++ b/src/services/JSE.Pedido.API/Application/DTO/PedidoDTO.cs @@ -6,7 +6,7 @@ public class PedidoDTO { public Guid Id { get; set; } public int Codigo { get; set; } - + public Guid ClienteId { get; set; } public int Status { get; set; } public DateTime Data { get; set; } public decimal ValorTotal { get; set; } diff --git a/src/services/JSE.Pedido.API/Application/Queries/IPedidoQueries.cs b/src/services/JSE.Pedido.API/Application/Queries/IPedidoQueries.cs index cdd01b7..f8303ca 100644 --- a/src/services/JSE.Pedido.API/Application/Queries/IPedidoQueries.cs +++ b/src/services/JSE.Pedido.API/Application/Queries/IPedidoQueries.cs @@ -6,6 +6,6 @@ public interface IPedidoQueries { Task ObterUltimoPedido(Guid clienteId); Task> ObterListaPorClienteId(Guid clienteId); + Task ObterPedidosAutorizados(); } - } \ No newline at end of file diff --git a/src/services/JSE.Pedido.API/Application/Queries/PedidoQueries.cs b/src/services/JSE.Pedido.API/Application/Queries/PedidoQueries.cs index 273929f..a2c73aa 100644 --- a/src/services/JSE.Pedido.API/Application/Queries/PedidoQueries.cs +++ b/src/services/JSE.Pedido.API/Application/Queries/PedidoQueries.cs @@ -40,6 +40,37 @@ public async Task> ObterListaPorClienteId(Guid clienteId) return pedidos.Select(PedidoDTO.ParaPedidoDTO); } + public async Task ObterPedidosAutorizados() + { + // Correção para pegar todos os itens do pedido e ordernar pelo pedido mais antigo + const string sql = @"SELECT + P.ID as 'PedidoId', P.ID, P.CLIENTEID, + PI.ID as 'PedidoItemId', PI.ID, PI.PRODUTOID, PI.QUANTIDADE + FROM PEDIDOS P + INNER JOIN PEDIDOITEMS PI ON P.ID = PI.PEDIDOID + WHERE P.PEDIDOSTATUS = 1 + ORDER BY P.DATACADASTRO"; + + // Utilizacao do lookup para manter o estado a cada ciclo de registro retornado + var lookup = new Dictionary(); + + await _pedidoRepository.ObterConexao().QueryAsync(sql, + (p, pi) => + { + if (!lookup.TryGetValue(p.Id, out var pedidoDTO)) + lookup.Add(p.Id, pedidoDTO = p); + + pedidoDTO.PedidoItems ??= new List(); + pedidoDTO.PedidoItems.Add(pi); + + return pedidoDTO; + + }, splitOn: "PedidoId,PedidoItemId"); + + // Obtendo dados o lookup + return lookup.Values.OrderBy(p => p.Data).FirstOrDefault(); + } + private PedidoDTO MapearPedido(dynamic result) { var pedido = new PedidoDTO diff --git a/src/services/JSE.Pedido.API/Configuration/MessageBusConfig.cs b/src/services/JSE.Pedido.API/Configuration/MessageBusConfig.cs index 9269e8c..1497f78 100644 --- a/src/services/JSE.Pedido.API/Configuration/MessageBusConfig.cs +++ b/src/services/JSE.Pedido.API/Configuration/MessageBusConfig.cs @@ -1,5 +1,6 @@ using JSE.Core.Utils; using JSE.MessageBus; +using JSE.Pedidos.API.Services; namespace JSE.Pedidos.API.Configuration { @@ -8,7 +9,8 @@ public static class MessageBusConfig public static void AddMessageBusConfiguration(this IServiceCollection services, IConfiguration configuration) { - services.AddMessageBus(configuration.GetMessageQueueConnection("MessageBus")); + services.AddMessageBus(configuration.GetMessageQueueConnection("MessageBus")) + .AddHostedService(); } } } \ No newline at end of file diff --git a/src/services/JSE.Pedido.API/Controllers/PedidoController.cs b/src/services/JSE.Pedido.API/Controllers/PedidoController.cs index e575396..726d757 100644 --- a/src/services/JSE.Pedido.API/Controllers/PedidoController.cs +++ b/src/services/JSE.Pedido.API/Controllers/PedidoController.cs @@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -namespace JSE.Pedido_API.Controllers +namespace JSE.Pedidos.API.Controllers { [Authorize] public class PedidoController : MainController diff --git a/src/services/JSE.Pedido.API/Services/PedidoOrquestradorIntegrationHandler.cs b/src/services/JSE.Pedido.API/Services/PedidoOrquestradorIntegrationHandler.cs new file mode 100644 index 0000000..8e1d681 --- /dev/null +++ b/src/services/JSE.Pedido.API/Services/PedidoOrquestradorIntegrationHandler.cs @@ -0,0 +1,65 @@ + +using JSE.Core.Messages.Integration; +using JSE.MessageBus; +using JSE.Pedidos.API.Application.Queries; + +namespace JSE.Pedidos.API.Services +{ + public class PedidoOrquestradorIntegrationHandler : IHostedService, IDisposable + { + + private readonly IServiceProvider _serviceProvider; + private readonly ILogger _logger; + private Timer _timer; + + public PedidoOrquestradorIntegrationHandler(ILogger logger, IServiceProvider serviceProvider) + { + _logger = logger; + _serviceProvider = serviceProvider; + } + + public Task StartAsync(CancellationToken cancellationToken) + { + _logger.LogInformation("Serviço de pedidos iniciado."); + + _timer = new Timer(ProcessarPedidos, null, TimeSpan.Zero, + TimeSpan.FromSeconds(15)); + + return Task.CompletedTask; + } + + private async void ProcessarPedidos(object state) + { + using (var scope = _serviceProvider.CreateScope()) + { + var pedidoQueries = scope.ServiceProvider.GetRequiredService(); + var pedido = await pedidoQueries.ObterPedidosAutorizados(); + + if (pedido == null) return; + + var bus = scope.ServiceProvider.GetRequiredService(); + + var pedidoAutorizado = new PedidoAutorizadoIntegrationEvent(pedido.ClienteId, pedido.Id, + pedido.PedidoItems.ToDictionary(p => p.ProdutoId, p => p.Quantidade)); + + await bus.PublishAsync(pedidoAutorizado); + + _logger.LogInformation($"Pedido ID: {pedido.Id} foi encaminhado para baixa no estoque."); + } + } + + public Task StopAsync(CancellationToken cancellationToken) + { + _logger.LogInformation("Serviço de pedidos finalizado."); + + _timer?.Change(Timeout.Infinite, 0); + + return Task.CompletedTask; + } + + public void Dispose() + { + _timer?.Dispose(); + } + } +} diff --git a/src/web/JSE.WebApp.MVC/Views/Pedido/ConfirmacaoPedido.cshtml b/src/web/JSE.WebApp.MVC/Views/Pedido/ConfirmacaoPedido.cshtml new file mode 100644 index 0000000..0c44488 --- /dev/null +++ b/src/web/JSE.WebApp.MVC/Views/Pedido/ConfirmacaoPedido.cshtml @@ -0,0 +1,110 @@ +@using JSE.WebApp.MVC.Extensions +@model JSE.WebApp.MVC.Models.PedidoViewModel + +@{ + ViewData["Title"] = "Pedido confirmado!"; +} + +
+
+ + + + @{ + if (Model.PedidoItems.Any()) + { +
+
+
+ + + + Endereço +
+
+ + + + Pagamento +
+
+ + + + Confirmação +
+
+
+
+

Pedido concluído com sucesso!

+
+
+ @{ + foreach (var item in Model.PedidoItems) + { +
+
+
+ @item.Nome +
+
+

+ @item.Nome +

+ @this.UnidadesPorProdutoValorTotal(item.Quantidade, item.Valor) +
+
+
+ } + } + +
+
+ +
+

Pedido número: #@Model.Codigo

+
+
+ +
+
+
+
Entregar em
+

+ @Model.Endereco.ToString() +

+
+
+
Pagamento
+ + + Transação em cartão de crédito + +

+ Total: @this.FormatoMoeda(Model.ValorTotal) +

+
+
+ +
+
+ + + +
+ } + } +
+
+ +@section Scripts { + + @{ + await Html.RenderPartialAsync("_ValidationScriptsPartial"); + } + +} \ No newline at end of file diff --git a/src/web/JSE.WebApp.MVC/Views/Pedido/MeusPedidos.cshtml b/src/web/JSE.WebApp.MVC/Views/Pedido/MeusPedidos.cshtml new file mode 100644 index 0000000..eab2bee --- /dev/null +++ b/src/web/JSE.WebApp.MVC/Views/Pedido/MeusPedidos.cshtml @@ -0,0 +1,68 @@ +@using JSE.WebApp.MVC.Extensions +@model IEnumerable + +@{ + ViewData["Title"] = "Meus Pedidos"; +} + +
+
+ + @{ + foreach (var pedido in Model.OrderBy(p=>p.Data)) + { +
+
+
+ Pedido ID: #@pedido.Codigo @Html.Raw(this.ExibeStatus(pedido.Status)) + @pedido.Data.ToLongDateString() +
+
+
+
+
Pagamento
+ + + Transação em cartão de crédito + + +

+ Total: @this.FormatoMoeda(pedido.ValorTotal) +

+ +
+
+
Endereço de entrega
+

+ @pedido.Endereco.ToString() +

+
+
+
+
    + @{ + foreach (var item in pedido.PedidoItems) + { +
  • +
    +
    + @item.Nome +
    +
    +

    + @item.Nome +

    + @this.UnidadesPorProdutoValorTotal(item.Quantidade, item.Valor) +
    +
    +
  • + } + } +
+
+
+
+ } + } +
+
\ No newline at end of file