@ -0,0 +1,16 @@ | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; | |||
public class CompleteOrderCommand : IRequest<bool> | |||
{ | |||
[DataMember] | |||
public int OrderNumber { get; set; } | |||
public CompleteOrderCommand() | |||
{ | |||
} | |||
public CompleteOrderCommand(int orderNumber) | |||
{ | |||
OrderNumber = orderNumber; | |||
} | |||
} |
@ -0,0 +1,48 @@ | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; | |||
// Regular CommandHandler | |||
public class CompleteOrderCommandHandler : IRequestHandler<CompleteOrderCommand, bool> | |||
{ | |||
private readonly IOrderRepository _orderRepository; | |||
public CompleteOrderCommandHandler(IOrderRepository orderRepository) | |||
{ | |||
_orderRepository = orderRepository; | |||
} | |||
/// <summary> | |||
/// Handler which processes the command when | |||
/// customer executes complete order from app | |||
/// </summary> | |||
/// <param name="command"></param> | |||
/// <returns></returns> | |||
public async Task<bool> Handle(CompleteOrderCommand command, CancellationToken cancellationToken) | |||
{ | |||
var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber); | |||
if (orderToUpdate == null) | |||
{ | |||
return false; | |||
} | |||
orderToUpdate.SetCompletedStatus(); | |||
return await _orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); | |||
} | |||
} | |||
// Use for Idempotency in Command process | |||
public class CompleteOrderIdentifiedCommandHandler : IdentifiedCommandHandler<CompleteOrderCommand, bool> | |||
{ | |||
public CompleteOrderIdentifiedCommandHandler( | |||
IMediator mediator, | |||
IRequestManager requestManager, | |||
ILogger<IdentifiedCommandHandler<CompleteOrderCommand, bool>> logger) | |||
: base(mediator, requestManager, logger) | |||
{ | |||
} | |||
protected override bool CreateResultForDuplicateRequest() | |||
{ | |||
return true; // Ignore duplicate requests for processing order. | |||
} | |||
} |
@ -0,0 +1,33 @@ | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.DomainEventHandlers; | |||
public partial class OrderCompletedDomainEventHandler | |||
: INotificationHandler<OrderCompletedDomainEvent> | |||
{ | |||
private readonly IOrderRepository _orderRepository; | |||
private readonly IBuyerRepository _buyerRepository; | |||
private readonly ILogger _logger; | |||
private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; | |||
public OrderCompletedDomainEventHandler( | |||
IOrderRepository orderRepository, | |||
ILogger<OrderCompletedDomainEventHandler> logger, | |||
IBuyerRepository buyerRepository, | |||
IOrderingIntegrationEventService orderingIntegrationEventService) | |||
{ | |||
_orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository)); | |||
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); | |||
_buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository)); | |||
_orderingIntegrationEventService = orderingIntegrationEventService; | |||
} | |||
public async Task Handle(OrderCompletedDomainEvent domainEvent, CancellationToken cancellationToken) | |||
{ | |||
OrderingApiTrace.LogOrderStatusUpdated(_logger, domainEvent.Order.Id, nameof(OrderStatus.Cancelled), OrderStatus.Cancelled.Id); | |||
var order = await _orderRepository.GetAsync(domainEvent.Order.Id); | |||
var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString()); | |||
var integrationEvent = new OrderStatusChangedToCompletedIntegrationEvent(order.Id, order.OrderStatus.Name, buyer.Name); | |||
await _orderingIntegrationEventService.AddAndSaveEventAsync(integrationEvent); | |||
} | |||
} |
@ -0,0 +1,15 @@ | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.Events; | |||
public record OrderStatusChangedToCompletedIntegrationEvent : IntegrationEvent | |||
{ | |||
public int OrderId { get; } | |||
public string OrderStatus { get; } | |||
public string BuyerName { get; } | |||
public OrderStatusChangedToCompletedIntegrationEvent(int orderId, string orderStatus, string buyerName) | |||
{ | |||
OrderId = orderId; | |||
OrderStatus = orderStatus; | |||
BuyerName = buyerName; | |||
} | |||
} |
@ -0,0 +1,11 @@ | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Validations; | |||
public class CompleteOrderCommandValidator : AbstractValidator<CompleteOrderCommand> | |||
{ | |||
public CompleteOrderCommandValidator(ILogger<CompleteOrderCommandValidator> logger) | |||
{ | |||
RuleFor(order => order.OrderNumber).NotEmpty().WithMessage("No orderId found"); | |||
logger.LogTrace("INSTANCE CREATED - {ClassName}", GetType().Name); | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Events; | |||
public class OrderCompletedDomainEvent : INotification | |||
{ | |||
public Order Order { get; } | |||
public OrderCompletedDomainEvent(Order order) | |||
{ | |||
Order = order; | |||
} | |||
} | |||
@ -0,0 +1,30 @@ | |||
using System.Collections.Generic; | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.EventHandling; | |||
public class OrderStatusChangedToCompletedIntegrationEventHandler : IIntegrationEventHandler<OrderStatusChangedToCompletedIntegrationEvent> | |||
{ | |||
private readonly IHubContext<NotificationsHub> _hubContext; | |||
private readonly ILogger<OrderStatusChangedToCompletedIntegrationEventHandler> _logger; | |||
public OrderStatusChangedToCompletedIntegrationEventHandler( | |||
IHubContext<NotificationsHub> hubContext, | |||
ILogger<OrderStatusChangedToCompletedIntegrationEventHandler> logger) | |||
{ | |||
_hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext)); | |||
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); | |||
} | |||
public async Task Handle(OrderStatusChangedToCompletedIntegrationEvent @event) | |||
{ | |||
using (_logger.BeginScope(new List<KeyValuePair<string, object>> { new ("IntegrationEventContext", @event.Id) })) | |||
{ | |||
_logger.LogInformation("Handling integration event: {IntegrationEventId} - ({@IntegrationEvent})", @event.Id, @event); | |||
await _hubContext.Clients | |||
.Group(@event.BuyerName) | |||
.SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus }); | |||
} | |||
} | |||
} |
@ -0,0 +1,16 @@ | |||
namespace Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.Events; | |||
public record OrderStatusChangedToCompletedIntegrationEvent : IntegrationEvent | |||
{ | |||
public int OrderId { get; } | |||
public string OrderStatus { get; } | |||
public string BuyerName { get; } | |||
public OrderStatusChangedToCompletedIntegrationEvent(int orderId, string orderStatus, string buyerName) | |||
{ | |||
OrderId = orderId; | |||
OrderStatus = orderStatus; | |||
BuyerName = buyerName; | |||
} | |||
} | |||