diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationCommands/Commands/ConfirmOrderStockCommandMsg.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationCommands/Commands/ConfirmOrderStockCommandMsg.cs new file mode 100644 index 000000000..abf93d0ef --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationCommands/Commands/ConfirmOrderStockCommandMsg.cs @@ -0,0 +1,30 @@ +namespace Ordering.API.Application.IntegrationCommands.Commands +{ + using System.Collections.Generic; + using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; + + public class ConfirmOrderStockCommandMsg : IntegrationEvent + { + public int OrderId { get; } + public IEnumerable OrderStockItem { get; } + + public ConfirmOrderStockCommandMsg(int orderId, + IEnumerable orderStockItem) + { + OrderId = orderId; + OrderStockItem = orderStockItem; + } + } + + public class OrderStockItem + { + public int ProductId { get; } + public int Units { get; } + + public OrderStockItem(int productId, int units) + { + ProductId = productId; + Units = units; + } + } +} \ 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 new file mode 100644 index 000000000..4b52c25cd --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockConfirmedIntegrationEventHandler.cs @@ -0,0 +1,15 @@ +namespace Ordering.API.Application.IntegrationEvents.EventHandling +{ + using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; + using System; + using System.Threading.Tasks; + using Events; + + public class OrderStockConfirmedIntegrationEventHandler : IIntegrationEventHandler + { + public async Task Handle(OrderStockConfirmedIntegrationEvent @event) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockNotConfirmedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockNotConfirmedIntegrationEventHandler.cs new file mode 100644 index 000000000..b7c9e7ee8 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockNotConfirmedIntegrationEventHandler.cs @@ -0,0 +1,15 @@ +namespace Ordering.API.Application.IntegrationEvents.EventHandling +{ + using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; + using System; + using System.Threading.Tasks; + using Events; + + public class OrderStockNotConfirmedIntegrationEventHandler : IIntegrationEventHandler + { + public async Task Handle(OrderStockNotConfirmedIntegrationEvent @event) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs index 82416db46..808b43a1d 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs @@ -16,4 +16,4 @@ namespace Ordering.API.Application.IntegrationEvents.Events public OrderStartedIntegrationEvent(string userId) => UserId = userId; } -} +} \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStockConfirmedIntegrationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStockConfirmedIntegrationEvent.cs new file mode 100644 index 000000000..4bcc9aab5 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStockConfirmedIntegrationEvent.cs @@ -0,0 +1,11 @@ +namespace Ordering.API.Application.IntegrationEvents.Events +{ + using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; + + public class OrderStockConfirmedIntegrationEvent : IntegrationEvent + { + public int OrderId { get; } + + public OrderStockConfirmedIntegrationEvent(int orderId) => OrderId = orderId; + } +} \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStockNotConfirmedIntegrationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStockNotConfirmedIntegrationEvent.cs new file mode 100644 index 000000000..bd2055fef --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStockNotConfirmedIntegrationEvent.cs @@ -0,0 +1,16 @@ +namespace Ordering.API.Application.IntegrationEvents.Events +{ + using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; + + public class OrderStockNotConfirmedIntegrationEvent : IntegrationEvent + { + public int OrderId { get; } + + //public IEnumerable { get; } + + public OrderStockNotConfirmedIntegrationEvent(int orderId) + { + OrderId = orderId; + } + } +} \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Application/Sagas/OrderProcessSaga.cs b/src/Services/Ordering/Ordering.API/Application/Sagas/OrderProcessSaga.cs index 500659e9b..28de7b10f 100644 --- a/src/Services/Ordering/Ordering.API/Application/Sagas/OrderProcessSaga.cs +++ b/src/Services/Ordering/Ordering.API/Application/Sagas/OrderProcessSaga.cs @@ -9,7 +9,11 @@ using Ordering.API.Application.Commands; using Ordering.API.Application.IntegrationCommands.Commands; using Ordering.Domain.Exceptions; using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; using System.Threading.Tasks; +using Ordering.API.Application.IntegrationEvents; using Ordering.API.Application.IntegrationEvents.Events; namespace Ordering.API.Application.Sagas @@ -29,14 +33,16 @@ namespace Ordering.API.Application.Sagas { private readonly IMediator _mediator; private readonly Func> _dbContextFactory; + private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; public OrderProcessSaga( Func> dbContextFactory, OrderingContext orderingContext, - IMediator mediator) + IMediator mediator, IOrderingIntegrationEventService orderingIntegrationEventService) : base(orderingContext) { _dbContextFactory = dbContextFactory; _mediator = mediator; + _orderingIntegrationEventService = orderingIntegrationEventService; } /// @@ -77,14 +83,22 @@ namespace Ordering.API.Application.Sagas var orderSaga = FindSagaById(command.OrderId); CheckValidSagaId(orderSaga); - // TODO: This handler should change to Integration command handler type once command bus is implemented + if (orderSaga.OrderStatus != OrderStatus.Cancelled) + { + orderSaga.SetOrderStatusId(OrderStatus.AwaitingValidation.Id); + await SaveChangesAsync(); + + var orderStockList = orderSaga.OrderItems + .Select(orderItem => new OrderStockItem(orderItem.ProductId, orderItem.GetUnits())); - // TODO: If order status is not cancelled, change state to awaitingValidation and - // send ConfirmOrderStockCommandMsg to Inventory api - + //Create Integration Event to be published through the Event Bus + var confirmOrderStockEvent = new ConfirmOrderStockCommandMsg(orderSaga.Id, orderStockList); + + // Publish through the Event Bus and mark the saved event as published + await _orderingIntegrationEventService.PublishThroughEventBusAsync(confirmOrderStockEvent); + } } - /// /// Handler which processes the command when /// customer executes cancel order from app diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/OrderingContextSeed.cs b/src/Services/Ordering/Ordering.API/Infrastructure/OrderingContextSeed.cs index de3294df7..b41d019fb 100644 --- a/src/Services/Ordering/Ordering.API/Infrastructure/OrderingContextSeed.cs +++ b/src/Services/Ordering/Ordering.API/Infrastructure/OrderingContextSeed.cs @@ -31,9 +31,12 @@ if (!context.OrderStatus.Any()) { - context.OrderStatus.Add(OrderStatus.Canceled); - context.OrderStatus.Add(OrderStatus.InProcess); + context.OrderStatus.Add(OrderStatus.Submited); + context.OrderStatus.Add(OrderStatus.AwaitingValidation); + context.OrderStatus.Add(OrderStatus.StockValidated); + context.OrderStatus.Add(OrderStatus.Paid); context.OrderStatus.Add(OrderStatus.Shipped); + context.OrderStatus.Add(OrderStatus.Cancelled); } await context.SaveChangesAsync(); diff --git a/src/Services/Ordering/Ordering.API/Startup.cs b/src/Services/Ordering/Ordering.API/Startup.cs index a02dba45c..fb32d3a08 100644 --- a/src/Services/Ordering/Ordering.API/Startup.cs +++ b/src/Services/Ordering/Ordering.API/Startup.cs @@ -1,10 +1,4 @@ - - -using Ordering.API.Application.IntegrationCommands.Commands; -using Ordering.API.Application.IntegrationEvents.EventHandling; -using Ordering.API.Application.Sagas; - -namespace Microsoft.eShopOnContainers.Services.Ordering.API +namespace Microsoft.eShopOnContainers.Services.Ordering.API { using AspNetCore.Http; using Autofac; @@ -12,6 +6,9 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API using global::Ordering.API.Application.IntegrationEvents; using global::Ordering.API.Application.IntegrationEvents.EventHandling; using global::Ordering.API.Infrastructure.Middlewares; + using global::Ordering.API.Application.IntegrationCommands.Commands; + using global::Ordering.API.Application.IntegrationEvents.Events; + using global::Ordering.API.Application.Sagas; using Infrastructure; using Infrastructure.Auth; using Infrastructure.AutofacModules; @@ -131,6 +128,10 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API services.AddSingleton(); services.AddSingleton(); services.AddTransient(); + services.AddTransient, OrderProcessSaga>(); + services.AddTransient, OrderProcessSaga>(); + services.AddTransient(); + services.AddTransient(); services.AddOptions(); //configure autofac @@ -179,11 +180,14 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API "UserCheckoutAccepted", () => app.ApplicationServices.GetRequiredService()); - eventBus.Subscribe>( - () => app.ApplicationServices - .GetService>() - ); + eventBus.Subscribe> + (() => app.ApplicationServices.GetRequiredService>()); + + eventBus.Subscribe + (() => app.ApplicationServices.GetRequiredService()); + eventBus.Subscribe + (() => app.ApplicationServices.GetRequiredService()); } protected virtual void ConfigureAuth(IApplicationBuilder app) diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs index 281cf6ecc..9539c5184 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs @@ -46,7 +46,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O _orderItems = new List(); _buyerId = buyerId; _paymentMethodId = paymentMethodId; - _orderStatusId = OrderStatus.InProcess.Id; + _orderStatusId = OrderStatus.Submited.Id; _orderDate = DateTime.UtcNow; Address = address; @@ -94,6 +94,11 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O _buyerId = id; } + public void SetOrderStatusId(int id) + { + _orderStatusId = id; + } + private void AddOrderStartedDomainEvent(int cardTypeId, string cardNumber, string cardSecurityNumber, string cardHolderName, DateTime cardExpiration) { diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderItem.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderItem.cs index 5d011981a..991fb8730 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderItem.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderItem.cs @@ -54,6 +54,11 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O return _discount; } + public int GetUnits() + { + return _units; + } + public void SetNewDiscount(decimal discount) { if (discount < 0) diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderStatus.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderStatus.cs index 6e3ff74b1..73178cbe5 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderStatus.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderStatus.cs @@ -10,9 +10,12 @@ public class OrderStatus : Enumeration { - public static OrderStatus InProcess = new OrderStatus(1, nameof(InProcess).ToLowerInvariant()); - public static OrderStatus Shipped = new OrderStatus(2, nameof(Shipped).ToLowerInvariant()); - public static OrderStatus Canceled = new OrderStatus(3, nameof(Canceled).ToLowerInvariant()); + public static OrderStatus Submited = new OrderStatus(1, nameof(Submited).ToLowerInvariant()); + public static OrderStatus AwaitingValidation = new OrderStatus(2, nameof(AwaitingValidation).ToLowerInvariant()); + public static OrderStatus StockValidated = new OrderStatus(3, nameof(StockValidated).ToLowerInvariant()); + public static OrderStatus Paid = new OrderStatus(4, nameof(Paid).ToLowerInvariant()); + public static OrderStatus Shipped = new OrderStatus(5, nameof(Shipped).ToLowerInvariant()); + public static OrderStatus Cancelled = new OrderStatus(6, nameof(Cancelled).ToLowerInvariant()); protected OrderStatus() { @@ -23,10 +26,8 @@ { } - public static IEnumerable List() - { - return new[] { InProcess, Shipped, Canceled }; - } + public static IEnumerable List() => + new[] { Submited, AwaitingValidation, StockValidated, Paid, Shipped, Cancelled }; public static OrderStatus FromName(string name) {