From 78a45cdad32bbdc9f22110d4de3f76451e6ec45c Mon Sep 17 00:00:00 2001 From: cemaleddin Date: Sat, 23 Jul 2022 13:35:24 +0300 Subject: [PATCH] add order status change add order status event add order status event handler --- .../Identity/Identity.API/Identity.API.csproj | 8 +- .../Application/Commands/IdentifiedCommand.cs | 1 + .../SetCompletedOrderStatusCommand.cs | 13 +++ .../SetCompletedOrderStatusCommandHandler.cs | 51 ++++++++++++ ...tusChangedToCompletedDomainEventHandler.cs | 44 ++++++++++ ...rCompletedFailedIntegrationEventHandler.cs | 35 ++++++++ ...mpletedSucceededIntegrationEventHandler.cs | 35 ++++++++ .../OrderCompletedFailedIntegrationEvent.cs | 8 ++ ...OrderCompletedSucceededIntegrationEvent.cs | 8 ++ ...tatusChangedToCompletedIntegrationEvent.cs | 21 +++++ .../Controllers/OrdersController.cs | 25 ++++++ src/Services/Ordering/Ordering.API/Startup.cs | 2 + .../AggregatesModel/OrderAggregate/Order.cs | 10 +++ .../OrderAggregate/OrderStatus.cs | 3 +- ...rderStatusChangedToCompletedDomainEvent.cs | 18 ++++ ...angedToCompletedIntegrationEventHandler.cs | 28 +++++++ ...tatusChangedToCompletedIntegrationEvent.cs | 16 ++++ .../Ordering/Ordering.SignalrHub/Startup.cs | 1 + .../Application/OrdersWebApiTest.cs | 16 ++++ src/Web/WebMVC/Controllers/OrderController.cs | 7 ++ src/Web/WebMVC/Infrastructure/API.cs | 8 ++ src/Web/WebMVC/Services/IOrderingService.cs | 2 + src/Web/WebMVC/Services/OrderingService.cs | 20 +++++ src/Web/WebMVC/Views/Order/Index.cshtml | 83 ++++++++++++------- src/Web/WebMVC/Views/Shared/_Layout.cshtml | 34 ++++++-- src/Web/WebMVC/WebMVC.csproj | 6 +- src/Web/WebStatus/WebStatus.csproj | 6 +- src/eShopOnContainers-ServicesAndWebApps.sln | 8 +- 28 files changed, 470 insertions(+), 47 deletions(-) create mode 100644 src/Services/Ordering/Ordering.API/Application/Commands/SetCompletedOrderStatusCommand.cs create mode 100644 src/Services/Ordering/Ordering.API/Application/Commands/SetCompletedOrderStatusCommandHandler.cs create mode 100644 src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderCompleted/OrderStatusChangedToCompletedDomainEventHandler.cs create mode 100644 src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderCompletedFailedIntegrationEventHandler.cs create mode 100644 src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderCompletedSucceededIntegrationEventHandler.cs create mode 100644 src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderCompletedFailedIntegrationEvent.cs create mode 100644 src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderCompletedSucceededIntegrationEvent.cs create mode 100644 src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToCompletedIntegrationEvent.cs create mode 100644 src/Services/Ordering/Ordering.Domain/Events/OrderStatusChangedToCompletedDomainEvent.cs create mode 100644 src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToCompletedIntegrationEventHandler.cs create mode 100644 src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToCompletedIntegrationEvent.cs diff --git a/src/Services/Identity/Identity.API/Identity.API.csproj b/src/Services/Identity/Identity.API/Identity.API.csproj index 0398ccb4b..930057ec0 100644 --- a/src/Services/Identity/Identity.API/Identity.API.csproj +++ b/src/Services/Identity/Identity.API/Identity.API.csproj @@ -39,8 +39,12 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + - + @@ -50,7 +54,7 @@ - + diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommand.cs index 5109ced4e..b5858dc40 100644 --- a/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommand.cs +++ b/src/Services/Ordering/Ordering.API/Application/Commands/IdentifiedCommand.cs @@ -10,4 +10,5 @@ public class IdentifiedCommand : IRequest Command = command; Id = id; } + } diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetCompletedOrderStatusCommand.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetCompletedOrderStatusCommand.cs new file mode 100644 index 000000000..d83913d4f --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetCompletedOrderStatusCommand.cs @@ -0,0 +1,13 @@ +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; + +public class SetCompletedOrderStatusCommand : IRequest +{ + + [DataMember] + public int OrderNumber { get; private set; } + + public SetCompletedOrderStatusCommand(int orderNumber) + { + OrderNumber = orderNumber; + } +} diff --git a/src/Services/Ordering/Ordering.API/Application/Commands/SetCompletedOrderStatusCommandHandler.cs b/src/Services/Ordering/Ordering.API/Application/Commands/SetCompletedOrderStatusCommandHandler.cs new file mode 100644 index 000000000..ed1b27ecd --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/Commands/SetCompletedOrderStatusCommandHandler.cs @@ -0,0 +1,51 @@ +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; + +// Regular CommandHandler +public class SetCompletedOrderStatusCommandHandler : IRequestHandler +{ + private readonly IOrderRepository _orderRepository; + + public SetCompletedOrderStatusCommandHandler(IOrderRepository orderRepository) + { + _orderRepository = orderRepository; + } + + /// + /// Handler which processes the command when + /// Completed the order + /// + /// + /// + public async Task Handle(SetCompletedOrderStatusCommand command, CancellationToken cancellationToken) + { + // Simulate a work time for validating the completed + await Task.Delay(10000, 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 SetCompletedIdentifiedOrderStatusCommandHandler : IdentifiedCommandHandler +{ + public SetCompletedIdentifiedOrderStatusCommandHandler( + IMediator mediator, + IRequestManager requestManager, + ILogger> logger) + : base(mediator, requestManager, logger) + { + } + + protected override bool CreateResultForDuplicateRequest() + { + return true; // Ignore duplicate requests for processing order. + } +} diff --git a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderCompleted/OrderStatusChangedToCompletedDomainEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderCompleted/OrderStatusChangedToCompletedDomainEventHandler.cs new file mode 100644 index 000000000..43482b9a3 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderCompleted/OrderStatusChangedToCompletedDomainEventHandler.cs @@ -0,0 +1,44 @@ +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.DomainEventHandlers.OrderCompleted; + +public class OrderStatusChangedToCompletedDomainEventHandler + : INotificationHandler +{ + private readonly IOrderRepository _orderRepository; + private readonly ILoggerFactory _logger; + private readonly IBuyerRepository _buyerRepository; + private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; + + + public OrderStatusChangedToCompletedDomainEventHandler( + IOrderRepository orderRepository, ILoggerFactory 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 ?? throw new ArgumentNullException(nameof(orderingIntegrationEventService)); + } + + public async Task Handle(OrderStatusChangedToCompletedDomainEvent orderStatusChangedToCompletedDomainEvent, CancellationToken cancellationToken) + { + _logger.CreateLogger() + .LogTrace("Order with Id: {OrderId} has been successfully updated to status {Status} ({Id})", + orderStatusChangedToCompletedDomainEvent.OrderId, nameof(OrderStatus.Complete), OrderStatus.Complete.Id); + + var order = await _orderRepository.GetAsync(orderStatusChangedToCompletedDomainEvent.OrderId); + var buyer = await _buyerRepository.FindByIdAsync(order.GetBuyerId.Value.ToString()); + + var orderStockList = orderStatusChangedToCompletedDomainEvent.OrderItems + .Select(orderItem => new OrderStockItem(orderItem.ProductId, orderItem.GetUnits())); + + var orderStatusChangedToCompletedIntegrationEvent = new OrderStatusChangedToCompletedIntegrationEvent( + orderStatusChangedToCompletedDomainEvent.OrderId, + order.OrderStatus.Name, + buyer.Name, + orderStockList); + + await _orderingIntegrationEventService.AddAndSaveEventAsync(orderStatusChangedToCompletedIntegrationEvent); + } +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderCompletedFailedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderCompletedFailedIntegrationEventHandler.cs new file mode 100644 index 000000000..5229cee50 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderCompletedFailedIntegrationEventHandler.cs @@ -0,0 +1,35 @@ +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.EventHandling; + +public class OrderCompletedFailedIntegrationEventHandler : + IIntegrationEventHandler +{ + private readonly IMediator _mediator; + private readonly ILogger _logger; + + public OrderCompletedFailedIntegrationEventHandler( + IMediator mediator, + ILogger logger) + { + _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + + public async Task Handle(OrderCompletedFailedIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) + { + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); + + var command = new CancelOrderCommand(@event.OrderId); + + _logger.LogInformation( + "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", + command.GetGenericTypeName(), + nameof(command.OrderNumber), + command.OrderNumber, + command); + + await _mediator.Send(command); + } + } +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderCompletedSucceededIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderCompletedSucceededIntegrationEventHandler.cs new file mode 100644 index 000000000..fcc6d8a91 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderCompletedSucceededIntegrationEventHandler.cs @@ -0,0 +1,35 @@ +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.EventHandling; + +public class OrderCompletedSucceededIntegrationEventHandler : + IIntegrationEventHandler +{ + private readonly IMediator _mediator; + private readonly ILogger _logger; + + public OrderCompletedSucceededIntegrationEventHandler( + IMediator mediator, + ILogger logger) + { + _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + + public async Task Handle(OrderCompletedSucceededIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) + { + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); + + var command = new SetCompletedOrderStatusCommand(@event.OrderId); + + _logger.LogInformation( + "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", + command.GetGenericTypeName(), + nameof(command.OrderNumber), + command.OrderNumber, + command); + + await _mediator.Send(command); + } + } +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderCompletedFailedIntegrationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderCompletedFailedIntegrationEvent.cs new file mode 100644 index 000000000..bc038d276 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderCompletedFailedIntegrationEvent.cs @@ -0,0 +1,8 @@ +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.Events; + +public record OrderCompletedFailedIntegrationEvent : IntegrationEvent +{ + public int OrderId { get; } + + public OrderCompletedFailedIntegrationEvent(int orderId) => OrderId = orderId; +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderCompletedSucceededIntegrationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderCompletedSucceededIntegrationEvent.cs new file mode 100644 index 000000000..5c9bd1be3 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderCompletedSucceededIntegrationEvent.cs @@ -0,0 +1,8 @@ +namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.IntegrationEvents.Events; + +public record OrderCompletedSucceededIntegrationEvent : IntegrationEvent +{ + public int OrderId { get; } + + public OrderCompletedSucceededIntegrationEvent(int orderId) => OrderId = orderId; +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToCompletedIntegrationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToCompletedIntegrationEvent.cs new file mode 100644 index 000000000..fbce83dbb --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStatusChangedToCompletedIntegrationEvent.cs @@ -0,0 +1,21 @@ +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 IEnumerable OrderStockItems { get; } + + public OrderStatusChangedToCompletedIntegrationEvent(int orderId, + string orderStatus, + string buyerName, + IEnumerable orderStockItems) + { + OrderId = orderId; + OrderStockItems = orderStockItems; + OrderStatus = orderStatus; + BuyerName = buyerName; + } +} + diff --git a/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs b/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs index 2cfd4063f..7a02453a3 100644 --- a/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs +++ b/src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs @@ -140,4 +140,29 @@ public class OrdersController : ControllerBase return await _mediator.Send(createOrderDraftCommand); } + + + [Route("completed")] + [HttpPut] + [ProducesResponseType((int)HttpStatusCode.OK)] + [ProducesResponseType((int)HttpStatusCode.BadRequest)] + public async Task CompletedOrderAsync([FromBody] SetCompletedOrderStatusCommand setCompletedOrderStatusCommand, [FromHeader(Name = "x-requestid")] string requestId) + { + bool commandResult = false; + _logger.LogInformation( + "----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})", + setCompletedOrderStatusCommand.GetGenericTypeName(), + nameof(setCompletedOrderStatusCommand.OrderNumber), + setCompletedOrderStatusCommand.OrderNumber, + setCompletedOrderStatusCommand); + commandResult = await _mediator.Send(setCompletedOrderStatusCommand); + if (!commandResult) + { + return BadRequest(); + } + + + return Ok(); + + } } diff --git a/src/Services/Ordering/Ordering.API/Startup.cs b/src/Services/Ordering/Ordering.API/Startup.cs index 501a55361..415c31813 100644 --- a/src/Services/Ordering/Ordering.API/Startup.cs +++ b/src/Services/Ordering/Ordering.API/Startup.cs @@ -105,7 +105,9 @@ public class Startup eventBus.Subscribe>(); eventBus.Subscribe>(); eventBus.Subscribe>(); + eventBus.Subscribe>(); eventBus.Subscribe>(); + eventBus.Subscribe>(); } 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 81a67324b..6818c6121 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs @@ -132,6 +132,16 @@ public class Order _description = "The payment was performed at a simulated \"American Bank checking bank account ending on XX35071\""; } } + public void SetCompletedStatus() + { + if (_orderStatusId == OrderStatus.Paid.Id) + { + AddDomainEvent(new OrderStatusChangedToCompletedDomainEvent(Id, OrderItems)); + + _orderStatusId = OrderStatus.Complete.Id; + _description = "completed \"Yurt içi cargo ending on XX35071\""; + } + } public void SetShippedStatus() { diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderStatus.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderStatus.cs index aae09bc6a..349bf3ed4 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderStatus.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderStatus.cs @@ -11,6 +11,7 @@ public class OrderStatus 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()); + public static OrderStatus Complete = new OrderStatus(7, nameof(Complete).ToLowerInvariant()); public OrderStatus(int id, string name) : base(id, name) @@ -18,7 +19,7 @@ public class OrderStatus } public static IEnumerable List() => - new[] { Submitted, AwaitingValidation, StockConfirmed, Paid, Shipped, Cancelled }; + new[] { Submitted, AwaitingValidation, StockConfirmed, Paid, Shipped, Cancelled, Complete }; public static OrderStatus FromName(string name) { diff --git a/src/Services/Ordering/Ordering.Domain/Events/OrderStatusChangedToCompletedDomainEvent.cs b/src/Services/Ordering/Ordering.Domain/Events/OrderStatusChangedToCompletedDomainEvent.cs new file mode 100644 index 000000000..3f1374061 --- /dev/null +++ b/src/Services/Ordering/Ordering.Domain/Events/OrderStatusChangedToCompletedDomainEvent.cs @@ -0,0 +1,18 @@ +namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Events; + +/// +/// Event used when the order is completed +/// +public class OrderStatusChangedToCompletedDomainEvent + : INotification +{ + public int OrderId { get; } + public IEnumerable OrderItems { get; } + + public OrderStatusChangedToCompletedDomainEvent(int orderId, + IEnumerable orderItems) + { + OrderId = orderId; + OrderItems = orderItems; + } +} diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToCompletedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToCompletedIntegrationEventHandler.cs new file mode 100644 index 000000000..93b26cf27 --- /dev/null +++ b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/EventHandling/OrderStatusChangedToCompletedIntegrationEventHandler.cs @@ -0,0 +1,28 @@ +namespace Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.EventHandling; + +public class OrderStatusChangedToCompletedIntegrationEventHandler : IIntegrationEventHandler +{ + private readonly IHubContext _hubContext; + private readonly ILogger _logger; + + public OrderStatusChangedToCompletedIntegrationEventHandler( + IHubContext hubContext, + ILogger logger) + { + _hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + + + public async Task Handle(OrderStatusChangedToCompletedIntegrationEvent @event) + { + using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) + { + _logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); + + await _hubContext.Clients + .Group(@event.BuyerName) + .SendAsync("UpdatedOrderState", new { OrderId = @event.OrderId, Status = @event.OrderStatus }); + } + } +} diff --git a/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToCompletedIntegrationEvent.cs b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToCompletedIntegrationEvent.cs new file mode 100644 index 000000000..3dddbc6cd --- /dev/null +++ b/src/Services/Ordering/Ordering.SignalrHub/IntegrationEvents/Events/OrderStatusChangedToCompletedIntegrationEvent.cs @@ -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; + } +} diff --git a/src/Services/Ordering/Ordering.SignalrHub/Startup.cs b/src/Services/Ordering/Ordering.SignalrHub/Startup.cs index b57f4477e..6968dddaf 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/Startup.cs +++ b/src/Services/Ordering/Ordering.SignalrHub/Startup.cs @@ -138,6 +138,7 @@ public class Startup eventBus.Subscribe(); eventBus.Subscribe(); + eventBus.Subscribe(); eventBus.Subscribe(); eventBus.Subscribe(); eventBus.Subscribe(); diff --git a/src/Services/Ordering/Ordering.UnitTests/Application/OrdersWebApiTest.cs b/src/Services/Ordering/Ordering.UnitTests/Application/OrdersWebApiTest.cs index cfa14a3ec..005b6ea34 100644 --- a/src/Services/Ordering/Ordering.UnitTests/Application/OrdersWebApiTest.cs +++ b/src/Services/Ordering/Ordering.UnitTests/Application/OrdersWebApiTest.cs @@ -131,4 +131,20 @@ public class OrdersWebApiTest //Assert Assert.Equal((actionResult.Result as OkObjectResult).StatusCode, (int)System.Net.HttpStatusCode.OK); } + + [Fact] + public async Task Completed_order_status_requestId_change() + { + //Arrange + _mediatorMock.Setup(x => x.Send(It.IsAny(), default(CancellationToken))) + .Returns(Task.FromResult(true)); + + //Act + var orderController = new OrdersController(_mediatorMock.Object, _orderQueriesMock.Object, _identityServiceMock.Object, _loggerMock.Object); + var actionResult = await orderController.CompletedOrderAsync(new SetCompletedOrderStatusCommand(22),Guid.NewGuid().ToString()) as OkResult; + + //Assert + Assert.Equal(actionResult.StatusCode, (int)System.Net.HttpStatusCode.OK); + + } } diff --git a/src/Web/WebMVC/Controllers/OrderController.cs b/src/Web/WebMVC/Controllers/OrderController.cs index a80d54072..8d79e9c95 100644 --- a/src/Web/WebMVC/Controllers/OrderController.cs +++ b/src/Web/WebMVC/Controllers/OrderController.cs @@ -65,6 +65,13 @@ public class OrderController : Controller var order = await _orderSvc.GetOrder(user, orderId); return View(order); } + [HttpPost] + public async Task Completed(string orderId) + { + + await _orderSvc.CompleteOrder(orderId); + + } public async Task Index(Order item) { diff --git a/src/Web/WebMVC/Infrastructure/API.cs b/src/Web/WebMVC/Infrastructure/API.cs index 6e5ca68a2..63156f0bc 100644 --- a/src/Web/WebMVC/Infrastructure/API.cs +++ b/src/Web/WebMVC/Infrastructure/API.cs @@ -45,6 +45,14 @@ public static class API { return $"{baseUri}/ship"; } + public static string CompleteOrder(string baseUri) + { + return $"{baseUri}/completed"; + + ///o/api/v1/orders/complated + } + + } public static class Catalog diff --git a/src/Web/WebMVC/Services/IOrderingService.cs b/src/Web/WebMVC/Services/IOrderingService.cs index 2c34b7d01..add85a2cb 100644 --- a/src/Web/WebMVC/Services/IOrderingService.cs +++ b/src/Web/WebMVC/Services/IOrderingService.cs @@ -10,4 +10,6 @@ public interface IOrderingService Order MapUserInfoIntoOrder(ApplicationUser user, Order order); BasketDTO MapOrderToBasket(Order order); void OverrideUserInfoIntoOrder(Order original, Order destination); + Task CompleteOrder(string orderId); + } diff --git a/src/Web/WebMVC/Services/OrderingService.cs b/src/Web/WebMVC/Services/OrderingService.cs index f1422c51f..cf6d7ea35 100644 --- a/src/Web/WebMVC/Services/OrderingService.cs +++ b/src/Web/WebMVC/Services/OrderingService.cs @@ -137,4 +137,24 @@ public class OrderingService : IOrderingService RequestId = order.RequestId }; } + + async public Task CompleteOrder(string orderId) + { + var order = new OrderDTO() + { + OrderNumber = orderId + }; + + var uri = API.Order.CompleteOrder(_remoteServiceBaseUrl); + var orderContent = new StringContent(JsonSerializer.Serialize(order), System.Text.Encoding.UTF8, "application/json"); + + var response = await _httpClient.PutAsync(uri, orderContent); + + if (response.StatusCode == System.Net.HttpStatusCode.InternalServerError) + { + throw new Exception("Error completeng order, try later."); + } + + response.EnsureSuccessStatusCode(); + } } diff --git a/src/Web/WebMVC/Views/Order/Index.cshtml b/src/Web/WebMVC/Views/Order/Index.cshtml index d3247433c..3e374a61f 100644 --- a/src/Web/WebMVC/Views/Order/Index.cshtml +++ b/src/Web/WebMVC/Views/Order/Index.cshtml @@ -3,45 +3,66 @@ @model IEnumerable @{ - ViewData["Title"] = "My Orders"; - var headerList= new List
() { + ViewData["Title"] = "My Orders"; + var headerList = new List
() { new Header() { Controller = "Catalog", Text = "Back to catalog" }, new Header() { Text = " / " }, new Header() { Controller = "OrderManagement", Text = "Orders Management" } }; }
- +
-
-
Order number
-
Date
-
Total
-
Status
-
-
- @if (Model != null && Model.Any()) - { - foreach (var item in Model) - { -
-
@Html.DisplayFor(modelItem => item.OrderNumber)
-
@Html.DisplayFor(modelItem => item.Date)
-
$ @Html.DisplayFor(modelItem => item.Total)
-
@Html.DisplayFor(modelItem => item.Status)
-
- Detail -
-
- @if (item.Status.ToLower() == "submitted") - { - Cancel - } -
-
- } - } + + + + + + + + + + + + + + + + + @if (Model != null && Model.Any()) + { + foreach (var item in Model) + { + + + + + + + + + + + + + + } + + } + +
#Order numberDateTotalStatus
1@Html.DisplayFor(modelItem => item.OrderNumber)$ @Html.DisplayFor(modelItem => item.Total)@Html.DisplayFor(modelItem => item.Status) Detail + @if (item.Status.ToLower() == "submitted") + { + Cancel + } + + @if (item.Status.ToLower() == "paid") + { + + @*Completed*@ + } +
diff --git a/src/Web/WebMVC/Views/Shared/_Layout.cshtml b/src/Web/WebMVC/Views/Shared/_Layout.cshtml index 9a634b78a..f6150c040 100644 --- a/src/Web/WebMVC/Views/Shared/_Layout.cshtml +++ b/src/Web/WebMVC/Views/Shared/_Layout.cshtml @@ -94,11 +94,12 @@ diff --git a/src/Web/WebMVC/WebMVC.csproj b/src/Web/WebMVC/WebMVC.csproj index 08b08a103..0368df064 100644 --- a/src/Web/WebMVC/WebMVC.csproj +++ b/src/Web/WebMVC/WebMVC.csproj @@ -34,7 +34,11 @@ - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/Web/WebStatus/WebStatus.csproj b/src/Web/WebStatus/WebStatus.csproj index 38de7ff9e..50abc266d 100644 --- a/src/Web/WebStatus/WebStatus.csproj +++ b/src/Web/WebStatus/WebStatus.csproj @@ -18,7 +18,11 @@ - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/src/eShopOnContainers-ServicesAndWebApps.sln b/src/eShopOnContainers-ServicesAndWebApps.sln index 446614fc0..6f7626dfa 100644 --- a/src/eShopOnContainers-ServicesAndWebApps.sln +++ b/src/eShopOnContainers-ServicesAndWebApps.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29020.237 +# Visual Studio Version 17 +VisualStudioVersion = 17.2.32630.192 MinimumVisualStudioVersion = 10.0.40219.1 Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{FEA0C318-FFED-4D39-8781-265718CA43DD}" EndProject @@ -450,8 +450,8 @@ Global {F16E3C6A-1C94-4EAB-BE91-099618060B68}.AppStore|x64.Build.0 = Release|Any CPU {F16E3C6A-1C94-4EAB-BE91-099618060B68}.AppStore|x86.ActiveCfg = Release|Any CPU {F16E3C6A-1C94-4EAB-BE91-099618060B68}.AppStore|x86.Build.0 = Release|Any CPU - {F16E3C6A-1C94-4EAB-BE91-099618060B68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F16E3C6A-1C94-4EAB-BE91-099618060B68}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F16E3C6A-1C94-4EAB-BE91-099618060B68}.Debug|Any CPU.ActiveCfg = Release|Any CPU + {F16E3C6A-1C94-4EAB-BE91-099618060B68}.Debug|Any CPU.Build.0 = Release|Any CPU {F16E3C6A-1C94-4EAB-BE91-099618060B68}.Debug|ARM.ActiveCfg = Debug|Any CPU {F16E3C6A-1C94-4EAB-BE91-099618060B68}.Debug|ARM.Build.0 = Debug|Any CPU {F16E3C6A-1C94-4EAB-BE91-099618060B68}.Debug|iPhone.ActiveCfg = Debug|Any CPU