diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommand.cs new file mode 100644 index 000000000..2007b95c6 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommand.cs @@ -0,0 +1,21 @@ +using MediatR; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Threading.Tasks; + +namespace Ordering.API.Application.Commands +{ + public class SetAwaitingValidationOrderStatusCommand : IRequest + { + + [DataMember] + public int OrderNumber { get; private set; } + + public SetAwaitingValidationOrderStatusCommand(int orderNumber) + { + OrderNumber = orderNumber; + } + } +} \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommandHandler.cs new file mode 100644 index 000000000..cee307ca2 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetAwaitingValidationOrderStatusCommandHandler.cs @@ -0,0 +1,52 @@ +using MediatR; +using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; +using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; +using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; +using System.Threading; +using System.Threading.Tasks; + +namespace Ordering.API.Application.Commands +{ + // Regular CommandHandler + public class SetAwaitingValidationOrderStatusCommandHandler : IRequestHandler + { + private readonly IOrderRepository _orderRepository; + + public SetAwaitingValidationOrderStatusCommandHandler(IOrderRepository orderRepository) + { + _orderRepository = orderRepository; + } + + /// + /// Handler which processes the command when + /// graceperiod has finished + /// + /// + /// + public async Task Handle(SetAwaitingValidationOrderStatusCommand command, CancellationToken cancellationToken) + { + var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber); + if(orderToUpdate == null) + { + return false; + } + + orderToUpdate.SetAwaitingValidationStatus(); + return await _orderRepository.UnitOfWork.SaveEntitiesAsync(); + } + } + + + // Use for Idempotency in Command process + public class SetAwaitingValidationIdentifiedOrderStatusCommandHandler : IdentifiedCommandHandler + { + public SetAwaitingValidationIdentifiedOrderStatusCommandHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager) + { + } + + protected override bool CreateResultForDuplicateRequest() + { + return true; // Ignore duplicate requests for processing order. + } + } +} diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommand.cs new file mode 100644 index 000000000..12bab9ac5 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommand.cs @@ -0,0 +1,21 @@ +using MediatR; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Threading.Tasks; + +namespace Ordering.API.Application.Commands +{ + public class SetPaidOrderStatusCommand : IRequest + { + + [DataMember] + public int OrderNumber { get; private set; } + + public SetPaidOrderStatusCommand(int orderNumber) + { + OrderNumber = orderNumber; + } + } +} \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommandHandler.cs new file mode 100644 index 000000000..211e568cb --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetPaidOrderStatusCommandHandler.cs @@ -0,0 +1,55 @@ +using MediatR; +using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; +using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; +using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; +using System.Threading; +using System.Threading.Tasks; + +namespace Ordering.API.Application.Commands +{ + // Regular CommandHandler + public class SetPaidOrderStatusCommandHandler : IRequestHandler + { + private readonly IOrderRepository _orderRepository; + + public SetPaidOrderStatusCommandHandler(IOrderRepository orderRepository) + { + _orderRepository = orderRepository; + } + + /// + /// Handler which processes the command when + /// Shipment service confirms the payment + /// + /// + /// + public async Task Handle(SetPaidOrderStatusCommand command, CancellationToken cancellationToken) + { + // Simulate a work time for validating the payment + await Task.Delay(10000); + + var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber); + if(orderToUpdate == null) + { + return false; + } + + orderToUpdate.SetPaidStatus(); + return await _orderRepository.UnitOfWork.SaveEntitiesAsync(); + } + } + + + // Use for Idempotency in Command process + public class SetPaidIdentifiedOrderStatusCommandHandler : IdentifiedCommandHandler + { + public SetPaidIdentifiedOrderStatusCommandHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager) + { + } + + protected override bool CreateResultForDuplicateRequest() + { + return true; // Ignore duplicate requests for processing order. + } + } +} diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommand.cs new file mode 100644 index 000000000..74f002e21 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommand.cs @@ -0,0 +1,21 @@ +using MediatR; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Threading.Tasks; + +namespace Ordering.API.Application.Commands +{ + public class SetStockConfirmedOrderStatusCommand : IRequest + { + + [DataMember] + public int OrderNumber { get; private set; } + + public SetStockConfirmedOrderStatusCommand(int orderNumber) + { + OrderNumber = orderNumber; + } + } +} \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommandHandler.cs new file mode 100644 index 000000000..4e1bc6185 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockConfirmedOrderStatusCommandHandler.cs @@ -0,0 +1,55 @@ +using MediatR; +using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; +using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; +using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; +using System.Threading; +using System.Threading.Tasks; + +namespace Ordering.API.Application.Commands +{ + // Regular CommandHandler + public class SetStockConfirmedOrderStatusCommandHandler : IRequestHandler + { + private readonly IOrderRepository _orderRepository; + + public SetStockConfirmedOrderStatusCommandHandler(IOrderRepository orderRepository) + { + _orderRepository = orderRepository; + } + + /// + /// Handler which processes the command when + /// Stock service confirms the request + /// + /// + /// + public async Task Handle(SetStockConfirmedOrderStatusCommand command, CancellationToken cancellationToken) + { + // Simulate a work time for confirming the stock + await Task.Delay(10000); + + var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber); + if(orderToUpdate == null) + { + return false; + } + + orderToUpdate.SetStockConfirmedStatus(); + return await _orderRepository.UnitOfWork.SaveEntitiesAsync(); + } + } + + + // Use for Idempotency in Command process + public class SetStockConfirmedOrderStatusIdenfifiedCommandHandler : IdentifiedCommandHandler + { + public SetStockConfirmedOrderStatusIdenfifiedCommandHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager) + { + } + + protected override bool CreateResultForDuplicateRequest() + { + return true; // Ignore duplicate requests for processing order. + } + } +} diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommand.cs new file mode 100644 index 000000000..c2293c0aa --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommand.cs @@ -0,0 +1,25 @@ +using MediatR; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Threading.Tasks; + +namespace Ordering.API.Application.Commands +{ + public class SetStockRejectedOrderStatusCommand : IRequest + { + + [DataMember] + public int OrderNumber { get; private set; } + + [DataMember] + public List OrderStockItems { get; private set; } + + public SetStockRejectedOrderStatusCommand(int orderNumber, List orderStockItems) + { + OrderNumber = orderNumber; + OrderStockItems = orderStockItems; + } + } +} \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommandHandler.cs new file mode 100644 index 000000000..2b7a72526 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetStockRejectedOrderStatusCommandHandler.cs @@ -0,0 +1,56 @@ +using MediatR; +using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; +using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; +using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; +using System.Threading; +using System.Threading.Tasks; + +namespace Ordering.API.Application.Commands +{ + // Regular CommandHandler + public class SetStockRejectedOrderStatusCommandHandler : IRequestHandler + { + private readonly IOrderRepository _orderRepository; + + public SetStockRejectedOrderStatusCommandHandler(IOrderRepository orderRepository) + { + _orderRepository = orderRepository; + } + + /// + /// Handler which processes the command when + /// Stock service rejects the request + /// + /// + /// + public async Task Handle(SetStockRejectedOrderStatusCommand command, CancellationToken cancellationToken) + { + // Simulate a work time for rejecting the stock + await Task.Delay(10000); + + var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber); + if(orderToUpdate == null) + { + return false; + } + + orderToUpdate.SetCancelledStatusWhenStockIsRejected(command.OrderStockItems); + + return await _orderRepository.UnitOfWork.SaveEntitiesAsync(); + } + } + + + // Use for Idempotency in Command process + public class SetStockRejectedOrderStatusIdenfifiedCommandHandler : IdentifiedCommandHandler + { + public SetStockRejectedOrderStatusIdenfifiedCommandHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager) + { + } + + protected override bool CreateResultForDuplicateRequest() + { + return true; // Ignore duplicate requests for processing order. + } + } +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/GracePeriodConfirmedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/GracePeriodConfirmedIntegrationEventHandler.cs index c51619ff6..f8dcc6edb 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/GracePeriodConfirmedIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/GracePeriodConfirmedIntegrationEventHandler.cs @@ -1,5 +1,7 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +using MediatR; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; +using Ordering.API.Application.Commands; using Ordering.API.Application.IntegrationEvents.Events; using System.Threading.Tasks; @@ -7,11 +9,11 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling { public class GracePeriodConfirmedIntegrationEventHandler : IIntegrationEventHandler { - private readonly IOrderRepository _orderRepository; + private readonly IMediator _mediator; - public GracePeriodConfirmedIntegrationEventHandler(IOrderRepository orderRepository) + public GracePeriodConfirmedIntegrationEventHandler(IMediator mediator) { - _orderRepository = orderRepository; + _mediator = mediator; } /// @@ -24,9 +26,8 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling /// public async Task Handle(GracePeriodConfirmedIntegrationEvent @event) { - var orderToUpdate = await _orderRepository.GetAsync(@event.OrderId); - orderToUpdate.SetAwaitingValidationStatus(); - await _orderRepository.UnitOfWork.SaveEntitiesAsync(); + var command = new SetAwaitingValidationOrderStatusCommand(@event.OrderId); + await _mediator.Send(command); } } } diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentFailedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentFailedIntegrationEventHandler.cs index 259b7ec34..5f4fc28e1 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentFailedIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentFailedIntegrationEventHandler.cs @@ -1,27 +1,27 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling { + using MediatR; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; + using Ordering.API.Application.Commands; using Ordering.API.Application.IntegrationEvents.Events; + using System; using System.Threading.Tasks; public class OrderPaymentFailedIntegrationEventHandler : IIntegrationEventHandler { - private readonly IOrderRepository _orderRepository; + private readonly IMediator _mediator; - public OrderPaymentFailedIntegrationEventHandler(IOrderRepository orderRepository) + public OrderPaymentFailedIntegrationEventHandler(IMediator mediator) { - _orderRepository = orderRepository; + _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); } public async Task Handle(OrderPaymentFailedIntegrationEvent @event) { - var orderToUpdate = await _orderRepository.GetAsync(@event.OrderId); - - orderToUpdate.SetCancelledStatus(); - - await _orderRepository.UnitOfWork.SaveEntitiesAsync(); + var command = new CancelOrderCommand(@event.OrderId); + await _mediator.Send(command); } } } diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentSuccededIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentSuccededIntegrationEventHandler.cs index 1dbe59e10..6c201d77e 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentSuccededIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentSuccededIntegrationEventHandler.cs @@ -1,30 +1,27 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling { + using MediatR; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; + using Ordering.API.Application.Commands; using Ordering.API.Application.IntegrationEvents.Events; + using System; using System.Threading.Tasks; public class OrderPaymentSuccededIntegrationEventHandler : IIntegrationEventHandler { - private readonly IOrderRepository _orderRepository; + private readonly IMediator _mediator; - public OrderPaymentSuccededIntegrationEventHandler(IOrderRepository orderRepository) + public OrderPaymentSuccededIntegrationEventHandler(IMediator mediator) { - _orderRepository = orderRepository; + _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); } public async Task Handle(OrderPaymentSuccededIntegrationEvent @event) { - // Simulate a work time for validating the payment - await Task.Delay(10000); - - var orderToUpdate = await _orderRepository.GetAsync(@event.OrderId); - - orderToUpdate.SetPaidStatus(); - - await _orderRepository.UnitOfWork.SaveEntitiesAsync(); + var command = new SetPaidOrderStatusCommand(@event.OrderId); + await _mediator.Send(command); } } } \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockConfirmedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockConfirmedIntegrationEventHandler.cs index c08554066..c5561508b 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockConfirmedIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockConfirmedIntegrationEventHandler.cs @@ -4,27 +4,24 @@ using System.Threading.Tasks; using Events; using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; + using MediatR; + using System; + using Ordering.API.Application.Commands; public class OrderStockConfirmedIntegrationEventHandler : IIntegrationEventHandler { - private readonly IOrderRepository _orderRepository; + private readonly IMediator _mediator; - public OrderStockConfirmedIntegrationEventHandler(IOrderRepository orderRepository) + public OrderStockConfirmedIntegrationEventHandler(IMediator mediator) { - _orderRepository = orderRepository; + _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); } public async Task Handle(OrderStockConfirmedIntegrationEvent @event) { - // Simulate a work time for confirming the stock - await Task.Delay(10000); - - var orderToUpdate = await _orderRepository.GetAsync(@event.OrderId); - - orderToUpdate.SetStockConfirmedStatus(); - - await _orderRepository.UnitOfWork.SaveEntitiesAsync(); + var command = new SetStockConfirmedOrderStatusCommand(@event.OrderId); + await _mediator.Send(command); } } } \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockRejectedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockRejectedIntegrationEventHandler.cs index c70eba187..af7d98f74 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockRejectedIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockRejectedIntegrationEventHandler.cs @@ -5,27 +5,27 @@ using Events; using System.Linq; using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; + using MediatR; + using Ordering.API.Application.Commands; public class OrderStockRejectedIntegrationEventHandler : IIntegrationEventHandler { - private readonly IOrderRepository _orderRepository; + private readonly IMediator _mediator; - public OrderStockRejectedIntegrationEventHandler(IOrderRepository orderRepository) + public OrderStockRejectedIntegrationEventHandler(IMediator mediator) { - _orderRepository = orderRepository; + _mediator = mediator; } public async Task Handle(OrderStockRejectedIntegrationEvent @event) { - var orderToUpdate = await _orderRepository.GetAsync(@event.OrderId); - var orderStockRejectedItems = @event.OrderStockItems .FindAll(c => !c.HasStock) - .Select(c => c.ProductId); - - orderToUpdate.SetCancelledStatusWhenStockIsRejected(orderStockRejectedItems); + .Select(c => c.ProductId) + .ToList(); - await _orderRepository.UnitOfWork.SaveEntitiesAsync(); + var command = new SetStockRejectedOrderStatusCommand(@event.OrderId, orderStockRejectedItems); + await _mediator.Send(command); } } } \ No newline at end of file