Skip to content

Commit 2a01d7f

Browse files
Merge pull request #218 from jeffreysSharp/develop
#181 - Camada de application de pedido - pt II
2 parents fba9425 + 526f668 commit 2a01d7f

File tree

6 files changed

+220
-1
lines changed

6 files changed

+220
-1
lines changed

src/services/JSE.Pedido.API/Application/Commands/AdicionarPedidoCommand.cs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
using JSE.Core.Messages;
1+
2+
using FluentValidation;
3+
using JSE.Core.Messages;
4+
25
using JSE.Pedidos.API.Application.DTO;
36

47
namespace JSE.Pedidos.API.Application.Commands
@@ -23,5 +26,46 @@ public class AdicionarPedidoCommand : Command
2326
public string NomeCartao { get; set; }
2427
public string ExpiracaoCartao { get; set; }
2528
public string CvvCartao { get; set; }
29+
30+
public override bool IsValid()
31+
{
32+
ValidationResult = new AdicionarPedidoValidation().Validate(this);
33+
return ValidationResult.IsValid;
34+
}
35+
36+
public class AdicionarPedidoValidation : AbstractValidator<AdicionarPedidoCommand>
37+
{
38+
public AdicionarPedidoValidation()
39+
{
40+
RuleFor(c => c.ClienteId)
41+
.NotEqual(Guid.Empty)
42+
.WithMessage("Id do cliente inválido");
43+
44+
RuleFor(c => c.PedidoItems.Count)
45+
.GreaterThan(0)
46+
.WithMessage("O pedido precisa ter no mínimo 1 item");
47+
48+
RuleFor(c => c.ValorTotal)
49+
.GreaterThan(0)
50+
.WithMessage("Valor do pedido inválido");
51+
52+
RuleFor(c => c.NumeroCartao)
53+
.CreditCard()
54+
.WithMessage("Número de cartão inválido");
55+
56+
RuleFor(c => c.NomeCartao)
57+
.NotNull()
58+
.WithMessage("Nome do portador do cartão requerido.");
59+
60+
RuleFor(c => c.CvvCartao.Length)
61+
.GreaterThan(2)
62+
.LessThan(5)
63+
.WithMessage("O CVV do cartão precisa ter 3 ou 4 números.");
64+
65+
RuleFor(c => c.ExpiracaoCartao)
66+
.NotNull()
67+
.WithMessage("Data expiração do cartão requerida.");
68+
}
69+
}
2670
}
2771
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
using FluentValidation.Results;
2+
using JSE.Core.Messages;
3+
using JSE.Pedido_API.Application.Events;
4+
using JSE.Pedidos.API.Application.Commands;
5+
using JSE.Pedidos.API.Application.DTO;
6+
using JSE.Pedidos.Domain;
7+
using JSE.Pedidos.Domain.Pedidos;
8+
using JSE.Pedidos.Domain.Vouchers.Specs;
9+
using MediatR;
10+
11+
namespace NSE.Pedidos.API.Application.Commands
12+
{
13+
public class PedidoCommandHandler : CommandHandler,
14+
IRequestHandler<AdicionarPedidoCommand, ValidationResult>
15+
{
16+
private readonly IPedidoRepository _pedidoRepository;
17+
private readonly IVoucherRepository _voucherRepository;
18+
19+
public PedidoCommandHandler(IVoucherRepository voucherRepository,
20+
IPedidoRepository pedidoRepository)
21+
{
22+
_voucherRepository = voucherRepository;
23+
_pedidoRepository = pedidoRepository;
24+
}
25+
26+
public async Task<ValidationResult> Handle(AdicionarPedidoCommand message, CancellationToken cancellationToken)
27+
{
28+
// Validação do comando
29+
if (!message.IsValid()) return message.ValidationResult;
30+
31+
// Mapear Pedido
32+
var pedido = MapearPedido(message);
33+
34+
// Aplicar voucher se houver
35+
if (!await AplicarVoucher(message, pedido)) return ValidationResult;
36+
37+
// Validar pedido
38+
if (!ValidarPedido(pedido)) return ValidationResult;
39+
40+
// Processar pagamento
41+
if (!ProcessarPagamento(pedido)) return ValidationResult;
42+
43+
// Se pagamento tudo ok!
44+
pedido.AutorizarPedido();
45+
46+
// Adicionar Evento
47+
pedido.AddEvent(new PedidoRealizadoEvent(pedido.Id, pedido.ClienteId));
48+
49+
// Adicionar Pedido Repositorio
50+
_pedidoRepository.Adicionar(pedido);
51+
52+
// Persistir dados de pedido e voucher
53+
return await PersistData(_pedidoRepository.UnitOfWork);
54+
}
55+
56+
private Pedido MapearPedido(AdicionarPedidoCommand message)
57+
{
58+
var endereco = new Endereco
59+
{
60+
Logradouro = message.Endereco.Logradouro,
61+
Numero = message.Endereco.Numero,
62+
Complemento = message.Endereco.Complemento,
63+
Bairro = message.Endereco.Bairro,
64+
Cep = message.Endereco.Cep,
65+
Cidade = message.Endereco.Cidade,
66+
Estado = message.Endereco.Estado
67+
};
68+
69+
var pedido = new Pedido(message.ClienteId, message.ValorTotal, message.PedidoItems.Select(PedidoItemDTO.ParaPedidoItem).ToList(),
70+
message.VoucherUtilizado, message.Desconto);
71+
72+
pedido.AtribuirEndereco(endereco);
73+
return pedido;
74+
}
75+
76+
private async Task<bool> AplicarVoucher(AdicionarPedidoCommand message, Pedido pedido)
77+
{
78+
if (!message.VoucherUtilizado) return true;
79+
80+
var voucher = await _voucherRepository.ObterVoucherPorCodigo(message.VoucherCodigo);
81+
82+
if (voucher == null)
83+
{
84+
AddError("O voucher informado não existe!");
85+
return false;
86+
}
87+
88+
var voucherValidation = new VoucherValidation().Validate(voucher);
89+
90+
if (!voucherValidation.IsValid)
91+
{
92+
voucherValidation.Errors.ToList().ForEach(m => AddError(m.ErrorMessage));
93+
return false;
94+
}
95+
96+
pedido.AtribuirVoucher(voucher);
97+
voucher.DebitarQuantidade();
98+
99+
_voucherRepository.Atualizar(voucher);
100+
101+
return true;
102+
}
103+
104+
private bool ValidarPedido(Pedido pedido)
105+
{
106+
var pedidoValorOriginal = pedido.ValorTotal;
107+
var pedidoDesconto = pedido.Desconto;
108+
109+
pedido.CalcularValorPedido();
110+
111+
if (pedido.ValorTotal != pedidoValorOriginal)
112+
{
113+
AddError("O valor total do pedido não confere com o cálculo do pedido");
114+
return false;
115+
}
116+
117+
if (pedido.Desconto != pedidoDesconto)
118+
{
119+
AddError("O valor total não confere com o cálculo do pedido");
120+
return false;
121+
}
122+
123+
return true;
124+
}
125+
126+
public bool ProcessarPagamento(Pedido pedido)
127+
{
128+
return true;
129+
}
130+
}
131+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using JSE.Core.Messages;
2+
3+
namespace JSE.Pedido_API.Application.Events
4+
{
5+
public class PedidoRealizadoEvent : Event
6+
{
7+
public Guid PedidoId { get; set; }
8+
public Guid ClienteId { get; set; }
9+
10+
public PedidoRealizadoEvent(Guid pedidoId, Guid clienteId)
11+
{
12+
PedidoId = pedidoId;
13+
ClienteId = clienteId;
14+
}
15+
}
16+
}

src/services/JSE.Pedido.API/JSE.Pedidos.API.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
</ItemGroup>
2525

2626
<ItemGroup>
27+
2728
<ProjectReference Include="..\..\building blocks\JSE.Core\JSE.Core.csproj" />
2829
<ProjectReference Include="..\..\building blocks\JSE.MessageBus\JSE.MessageBus.csproj" />
2930
<ProjectReference Include="..\..\building blocks\JSE.WebAPI.Core\JSE.WebAPI.Core.csproj" />
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using NetDevPack.Specification;
2+
using static JSE.Pedidos.Domain.Vouchers.Specs.VoucherDataSpecification;
3+
4+
namespace JSE.Pedidos.Domain.Vouchers.Specs
5+
{
6+
public class VoucherValidation : SpecValidator<Voucher>
7+
{
8+
public VoucherValidation()
9+
{
10+
var dataSpec = new VoucherDataSpecification();
11+
var qtdeSpec = new VoucherQuantidadeSpecification();
12+
var ativoSpec = new VoucherAtivoSpecification();
13+
14+
Add("dataSpec", new Rule<Voucher>(dataSpec, "Este voucher está expirado"));
15+
Add("qtdeSpec", new Rule<Voucher>(qtdeSpec, "Este voucher já foi utilizado"));
16+
Add("ativoSpec", new Rule<Voucher>(ativoSpec, "Este voucher não está mais ativo"));
17+
}
18+
}
19+
}

src/services/JSE.Pedido.Domain/Vouchers/Voucher.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,13 @@ public void MarcarComoUtilizado()
3131
Utilizado = true;
3232
Quantidade = 0;
3333
}
34+
35+
public void DebitarQuantidade()
36+
{
37+
Quantidade -= 1;
38+
if (Quantidade >= 1) return;
39+
40+
MarcarComoUtilizado();
41+
}
3442
}
3543
}

0 commit comments

Comments
 (0)