diff --git a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/BuyerAndPaymentMethodVerified/UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/BuyerAndPaymentMethodVerified/UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler.cs index 657552810..6a0159115 100644 --- a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/BuyerAndPaymentMethodVerified/UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/BuyerAndPaymentMethodVerified/UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler.cs @@ -36,12 +36,9 @@ namespace Ordering.API.Application.DomainEventHandlers.BuyerAndPaymentMethodVeri var orderStartedIntegrationEvent = new OrderStartedIntegrationEvent(buyerPaymentMethodVerifiedEvent.Buyer.IdentityGuid); - // Using a local transaction to achieve atomicity between original Ordering database operation and - // the IntegrationEventLog. Only saving event if order has been successfully persisted to db await _orderingIntegrationEventService .SaveEventAndOrderingContextChangesAsync(orderStartedIntegrationEvent); - // Publish ordering integration event and mark it as published await _orderingIntegrationEventService .PublishThroughEventBusAsync(orderStartedIntegrationEvent); diff --git a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStockConfirmation/UpdateOrderWhenOrderStockMethodVerifiedDomainEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStockConfirmation/UpdateOrderWhenOrderStockMethodVerifiedDomainEventHandler.cs index abea5e0da..40b2fa865 100644 --- a/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStockConfirmation/UpdateOrderWhenOrderStockMethodVerifiedDomainEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStockConfirmation/UpdateOrderWhenOrderStockMethodVerifiedDomainEventHandler.cs @@ -6,23 +6,25 @@ using Domain.Events; using System; using System.Threading.Tasks; + using Ordering.API.Application.IntegrationCommands.Commands; + using Ordering.API.Application.IntegrationEvents; public class UpdateOrderWhenOrderStockMethodVerifiedDomainEventHandler : IAsyncNotificationHandler { private readonly IOrderRepository _orderRepository; - private readonly ILoggerFactory _logger; + private readonly ILoggerFactory _logger; + private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; public UpdateOrderWhenOrderStockMethodVerifiedDomainEventHandler( - IOrderRepository orderRepository, ILoggerFactory logger) + IOrderRepository orderRepository, ILoggerFactory logger, + IOrderingIntegrationEventService orderingIntegrationEventService) { _orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _orderingIntegrationEventService = orderingIntegrationEventService; } - // Domain Logic comment: - // When the Order Stock items method have been validate and confirmed, - // then we can update the original Order with the new order status public async Task Handle(OrderStockMethodVerifiedDomainEvent orderStockMethodVerifiedDomainEvent) { var orderToUpdate = await _orderRepository.GetAsync(orderStockMethodVerifiedDomainEvent.OrderId); @@ -37,14 +39,9 @@ .LogTrace($"Order with Id: {orderStockMethodVerifiedDomainEvent.OrderId} has been successfully updated with " + $"a status order id: { orderStockMethodVerifiedDomainEvent.OrderStatus.Id }"); - - //var payOrderCommandMsg = new PayOrderCommandMsg(order.Id); - - //// Achieving atomicity between original Catalog database operation and the IntegrationEventLog thanks to a local transaction - //await _orderingIntegrationEventService.SaveEventAndOrderingContextChangesAsync(payOrderCommandMsg); - - //// Publish through the Event Bus and mark the saved event as published - //await _orderingIntegrationEventService.PublishThroughEventBusAsync(payOrderCommandMsg); + var payOrderCommandMsg = new PayOrderCommandMsg(orderToUpdate.Id); + await _orderingIntegrationEventService.SaveEventAndOrderingContextChangesAsync(payOrderCommandMsg); + await _orderingIntegrationEventService.PublishThroughEventBusAsync(payOrderCommandMsg); } } } \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentFailedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentFailedIntegrationEventHandler.cs new file mode 100644 index 000000000..485cf750f --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentFailedIntegrationEventHandler.cs @@ -0,0 +1,14 @@ +namespace Ordering.API.Application.IntegrationEvents.EventHandling +{ + using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; + using Ordering.API.Application.IntegrationEvents.Events; + using System.Threading.Tasks; + + public class OrderPaymentFailedIntegrationEventHandler : + IIntegrationEventHandler + { + public async Task Handle(OrderPaymentFailedIntegrationEvent @event) + { + } + } +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentSuccededIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentSuccededIntegrationEventHandler.cs new file mode 100644 index 000000000..86e3d5482 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentSuccededIntegrationEventHandler.cs @@ -0,0 +1,14 @@ +namespace Ordering.API.Application.IntegrationEvents.EventHandling +{ + using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; + using Ordering.API.Application.IntegrationEvents.Events; + using System.Threading.Tasks; + + public class OrderPaymentSuccededIntegrationEventHandler : + IIntegrationEventHandler + { + public async Task Handle(OrderPaymentSuccededIntegrationEvent @event) + { + } + } +} 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 34dec2351..cfc2fdbe0 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockConfirmedIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockConfirmedIntegrationEventHandler.cs @@ -7,7 +7,8 @@ using Ordering.API.Application.IntegrationCommands.Commands; using Ordering.Domain.Exceptions; - public class OrderStockConfirmedIntegrationEventHandler : IIntegrationEventHandler + public class OrderStockConfirmedIntegrationEventHandler : + IIntegrationEventHandler { private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; private readonly IOrderRepository _orderRepository; @@ -25,7 +26,7 @@ var order = await _orderRepository.GetAsync(@event.OrderId); CheckValidSagaId(order); - order.SetOrderStockConfirmed(true); + order.SetOrderStockConfirmed(); //Create Integration Event to be published through the Event Bus var payOrderCommandMsg = new PayOrderCommandMsg(order.Id); diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockNotConfirmedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockNotConfirmedIntegrationEventHandler.cs index c5b7e6b01..dfcb1d480 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockNotConfirmedIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockNotConfirmedIntegrationEventHandler.cs @@ -1,4 +1,6 @@ -namespace Ordering.API.Application.IntegrationEvents.EventHandling +using System.Linq; + +namespace Ordering.API.Application.IntegrationEvents.EventHandling { using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using System; @@ -27,14 +29,11 @@ var order = await _orderRepository.GetAsync(@event.OrderId); CheckValidSagaId(order); - order.SetOrderStockConfirmed(false); - - var orderStockNotConfirmedItems = @event.OrderStockItems.FindAll(c => !c.Confirmed); + var orderStockNotConfirmedItems = @event.OrderStockItems + .FindAll(c => !c.Confirmed) + .Select(c => c.ProductId); - foreach (var orderStockNotConfirmedItem in orderStockNotConfirmedItems) - { - //TODO: Add messages - } + order.SetOrderStockConfirmed(orderStockNotConfirmedItems); } private void CheckValidSagaId(Order orderSaga) diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs index 7a5961cdd..720d7a8d4 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs @@ -1,10 +1,10 @@ -using MediatR; +using System; +using MediatR; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +using System.Threading.Tasks; using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; using Microsoft.Extensions.Logging; using Ordering.API.Application.IntegrationEvents.Events; -using System; -using System.Threading.Tasks; namespace Ordering.API.Application.IntegrationEvents.EventHandling { diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderPaymentFailedIntegrationEvent .cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderPaymentFailedIntegrationEvent .cs new file mode 100644 index 000000000..337fcd351 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderPaymentFailedIntegrationEvent .cs @@ -0,0 +1,11 @@ +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; + +namespace Ordering.API.Application.IntegrationEvents.Events +{ + public class OrderPaymentFailedIntegrationEvent : IntegrationEvent + { + public int OrderId { get; } + + public OrderPaymentFailedIntegrationEvent(int orderId) => OrderId = orderId; + } +} diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderPaymentSuccededIntegrationEvent.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderPaymentSuccededIntegrationEvent.cs new file mode 100644 index 000000000..525da09db --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderPaymentSuccededIntegrationEvent.cs @@ -0,0 +1,11 @@ +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; + +namespace Ordering.API.Application.IntegrationEvents.Events +{ + public class OrderPaymentSuccededIntegrationEvent : IntegrationEvent + { + public int OrderId { get; } + + public OrderPaymentSuccededIntegrationEvent(int orderId) => OrderId = orderId; + } +} diff --git a/src/Services/Ordering/Ordering.API/Application/Queries/OrderQueries.cs b/src/Services/Ordering/Ordering.API/Application/Queries/OrderQueries.cs index e51cf04ce..e6f964fed 100644 --- a/src/Services/Ordering/Ordering.API/Application/Queries/OrderQueries.cs +++ b/src/Services/Ordering/Ordering.API/Application/Queries/OrderQueries.cs @@ -26,7 +26,7 @@ connection.Open(); var result = await connection.QueryAsync( - @"select o.[Id] as ordernumber,o.OrderDate as date, os.Name as status, + @"select o.[Id] as ordernumber,o.OrderDate as date, o.Description as description, os.Name as status, oi.ProductName as productname, oi.Units as units, oi.UnitPrice as unitprice, oi.PictureUrl as pictureurl, a.Street as street, a.City as city, a.Country as country, a.State as state, a.ZipCode as zipcode FROM ordering.Orders o @@ -75,6 +75,7 @@ order.ordernumber = result[0].ordernumber; order.date = result[0].date; order.status = result[0].status; + order.description = result[0].description; order.street = result[0].street; order.city = result[0].city; order.zipcode = result[0].zipcode; diff --git a/src/Services/Ordering/Ordering.API/Application/Sagas/OrderProcessSaga.cs b/src/Services/Ordering/Ordering.API/Application/Sagas/OrderProcessSaga.cs index cdc75a589..8a4c51795 100644 --- a/src/Services/Ordering/Ordering.API/Application/Sagas/OrderProcessSaga.cs +++ b/src/Services/Ordering/Ordering.API/Application/Sagas/OrderProcessSaga.cs @@ -50,7 +50,7 @@ namespace Ordering.API.Application.Sagas /// has been completed and order has not been cancelled. /// If so, the process continues for validation. /// - /// + /// /// Integration command message which is sent by a saga /// scheduler which provides the sagas that its grace /// period has completed. @@ -69,10 +69,10 @@ namespace Ordering.API.Application.Sagas var orderStockList = orderSaga.OrderItems .Select(orderItem => new OrderStockItem(orderItem.ProductId, orderItem.GetUnits())); - //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.SaveEventAndOrderingContextChangesAsync(confirmOrderStockEvent); + await _orderingIntegrationEventService.PublishThroughEventBusAsync(confirmOrderStockEvent); } } diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/Migrations/20170511112333_AddOrderDescription.Designer.cs b/src/Services/Ordering/Ordering.API/Infrastructure/Migrations/20170511112333_AddOrderDescription.Designer.cs new file mode 100644 index 000000000..5f0a3d7a0 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Infrastructure/Migrations/20170511112333_AddOrderDescription.Designer.cs @@ -0,0 +1,246 @@ +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; + +namespace Ordering.API.Migrations +{ + [DbContext(typeof(OrderingContext))] + [Migration("20170511112333_AddOrderDescription")] + partial class AddOrderDescription + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { + modelBuilder + .HasAnnotation("ProductVersion", "1.1.1") + .HasAnnotation("SqlServer:Sequence:.orderitemseq", "'orderitemseq', '', '1', '10', '', '', 'Int64', 'False'") + .HasAnnotation("SqlServer:Sequence:ordering.buyerseq", "'buyerseq', 'ordering', '1', '10', '', '', 'Int64', 'False'") + .HasAnnotation("SqlServer:Sequence:ordering.orderseq", "'orderseq', 'ordering', '1', '10', '', '', 'Int64', 'False'") + .HasAnnotation("SqlServer:Sequence:ordering.paymentseq", "'paymentseq', 'ordering', '1', '10', '', '', 'Int64', 'False'") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.Buyer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:HiLoSequenceName", "buyerseq") + .HasAnnotation("SqlServer:HiLoSequenceSchema", "ordering") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); + + b.Property("IdentityGuid") + .IsRequired() + .HasMaxLength(200); + + b.HasKey("Id"); + + b.HasIndex("IdentityGuid") + .IsUnique(); + + b.ToTable("buyers","ordering"); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.CardType", b => + { + b.Property("Id") + .HasDefaultValue(1); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200); + + b.HasKey("Id"); + + b.ToTable("cardtypes","ordering"); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.PaymentMethod", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:HiLoSequenceName", "paymentseq") + .HasAnnotation("SqlServer:HiLoSequenceSchema", "ordering") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); + + b.Property("Alias") + .IsRequired() + .HasMaxLength(200); + + b.Property("BuyerId"); + + b.Property("CardHolderName") + .IsRequired() + .HasMaxLength(200); + + b.Property("CardNumber") + .IsRequired() + .HasMaxLength(25); + + b.Property("CardTypeId"); + + b.Property("Expiration"); + + b.HasKey("Id"); + + b.HasIndex("BuyerId"); + + b.HasIndex("CardTypeId"); + + b.ToTable("paymentmethods","ordering"); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Address", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("City"); + + b.Property("Country"); + + b.Property("State"); + + b.Property("Street"); + + b.Property("ZipCode"); + + b.HasKey("Id"); + + b.ToTable("address","ordering"); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:HiLoSequenceName", "orderseq") + .HasAnnotation("SqlServer:HiLoSequenceSchema", "ordering") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); + + b.Property("AddressId"); + + b.Property("BuyerId"); + + b.Property("Description"); + + b.Property("OrderDate"); + + b.Property("OrderStatusId"); + + b.Property("PaymentMethodId"); + + b.HasKey("Id"); + + b.HasIndex("AddressId"); + + b.HasIndex("BuyerId"); + + b.HasIndex("OrderStatusId"); + + b.HasIndex("PaymentMethodId"); + + b.ToTable("orders","ordering"); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("SqlServer:HiLoSequenceName", "orderitemseq") + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); + + b.Property("Discount"); + + b.Property("OrderId"); + + b.Property("PictureUrl"); + + b.Property("ProductId"); + + b.Property("ProductName") + .IsRequired(); + + b.Property("UnitPrice"); + + b.Property("Units"); + + b.HasKey("Id"); + + b.HasIndex("OrderId"); + + b.ToTable("orderItems","ordering"); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderStatus", b => + { + b.Property("Id") + .HasDefaultValue(1); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200); + + b.HasKey("Id"); + + b.ToTable("orderstatus","ordering"); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency.ClientRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Name") + .IsRequired(); + + b.Property("Time"); + + b.HasKey("Id"); + + b.ToTable("requests","ordering"); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.PaymentMethod", b => + { + b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.Buyer") + .WithMany("PaymentMethods") + .HasForeignKey("BuyerId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.CardType", "CardType") + .WithMany() + .HasForeignKey("CardTypeId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Order", b => + { + b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Address", "Address") + .WithMany() + .HasForeignKey("AddressId"); + + b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.Buyer") + .WithMany() + .HasForeignKey("BuyerId"); + + b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderStatus", "OrderStatus") + .WithMany() + .HasForeignKey("OrderStatusId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.PaymentMethod") + .WithMany() + .HasForeignKey("PaymentMethodId"); + }); + + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderItem", b => + { + b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Order") + .WithMany("OrderItems") + .HasForeignKey("OrderId") + .OnDelete(DeleteBehavior.Cascade); + }); + } + } +} diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/Migrations/20170511112333_AddOrderDescription.cs b/src/Services/Ordering/Ordering.API/Infrastructure/Migrations/20170511112333_AddOrderDescription.cs new file mode 100644 index 000000000..028babb96 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Infrastructure/Migrations/20170511112333_AddOrderDescription.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ordering.API.Migrations +{ + public partial class AddOrderDescription : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Description", + schema: "ordering", + table: "orders", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Description", + schema: "ordering", + table: "orders"); + } + } +} diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/Migrations/OrderingContextModelSnapshot.cs b/src/Services/Ordering/Ordering.API/Infrastructure/Migrations/OrderingContextModelSnapshot.cs index f73f1bd04..fa342cf31 100644 --- a/src/Services/Ordering/Ordering.API/Infrastructure/Migrations/OrderingContextModelSnapshot.cs +++ b/src/Services/Ordering/Ordering.API/Infrastructure/Migrations/OrderingContextModelSnapshot.cs @@ -121,6 +121,8 @@ namespace Ordering.API.Migrations b.Property("BuyerId"); + b.Property("Description"); + b.Property("OrderDate"); b.Property("OrderStatusId"); @@ -183,7 +185,7 @@ namespace Ordering.API.Migrations b.ToTable("orderstatus","ordering"); }); - modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.ClientRequest", b => + modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency.ClientRequest", b => { b.Property("Id") .ValueGeneratedOnAdd(); diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs index 0d8ef6b92..9cc8c06bd 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs @@ -1,6 +1,4 @@ -using MediatR; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; -using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; +using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; using Ordering.Domain.Events; using System; using System.Collections.Generic; @@ -23,6 +21,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O public OrderStatus OrderStatus { get; private set; } private int _orderStatusId; + private string _description; // DDD Patterns comment // Using a private collection field, better for DDD Aggregate's encapsulation @@ -99,17 +98,25 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O _orderStatusId = id; } - public void SetOrderStockConfirmed(bool confirmed) + public void SetOrderStockConfirmed(IEnumerable orderStockNotConfirmedItems = null) { - if(confirmed) + if(orderStockNotConfirmedItems is null) { OrderStatus = OrderStatus.StockValidated; - AddDomainEvent(new OrderStockMethodVerifiedDomainEvent(Id, OrderStatus.StockValidated)); + _description = "All the items were confirmed with available stock."; + //AddDomainEvent(new OrderStockMethodVerifiedDomainEvent(Id, OrderStatus.StockValidated)); } else { + var itemsStockNotConfirmedProductNames = OrderItems + .Where(c => orderStockNotConfirmedItems.Contains(c.ProductId)) + .Select(c => c.GetOrderItemProductName()); + + var itemsStockNotConfirmedDescription = string.Join(", ", itemsStockNotConfirmedProductNames); + OrderStatus = OrderStatus.Cancelled; - AddDomainEvent(new OrderStockMethodVerifiedDomainEvent(Id, OrderStatus.Cancelled)); + _description = $"The product items don't have stock: ({itemsStockNotConfirmedDescription})."; + //AddDomainEvent(new OrderStockMethodVerifiedDomainEvent(Id, OrderStatus.Cancelled)); } } @@ -124,3 +131,4 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O } } } + diff --git a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderItem.cs b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderItem.cs index 991fb8730..fd65fb3ca 100644 --- a/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderItem.cs +++ b/src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderItem.cs @@ -59,6 +59,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O return _units; } + public string GetOrderItemProductName() => _productName; + public void SetNewDiscount(decimal discount) { if (discount < 0) diff --git a/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs b/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs index a160558ef..0c69fe566 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs @@ -156,6 +156,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure orderConfiguration.Property("BuyerId").IsRequired(false); orderConfiguration.Property("OrderStatusId").IsRequired(); orderConfiguration.Property("PaymentMethodId").IsRequired(false); + orderConfiguration.Property("Description").IsRequired(false); var navigation = orderConfiguration.Metadata.FindNavigation(nameof(Order.OrderItems)); // DDD Patterns comment: diff --git a/src/Services/SagaManager/SagaManager/Program.cs b/src/Services/SagaManager/SagaManager/Program.cs index 7de0704ea..0e5e1dc5a 100644 --- a/src/Services/SagaManager/SagaManager/Program.cs +++ b/src/Services/SagaManager/SagaManager/Program.cs @@ -80,8 +80,6 @@ namespace SagaManager var container = new ContainerBuilder(); container.Populate(services); return new AutofacServiceProvider(container.Build()); - - return services.BuildServiceProvider(); } public static void Configure(ILoggerFactory loggerFactory) diff --git a/src/Web/WebMVC/ViewModels/Order.cs b/src/Web/WebMVC/ViewModels/Order.cs index 785b29119..213914208 100644 --- a/src/Web/WebMVC/ViewModels/Order.cs +++ b/src/Web/WebMVC/ViewModels/Order.cs @@ -19,6 +19,8 @@ namespace Microsoft.eShopOnContainers.WebMVC.ViewModels public decimal Total {get;set;} + public string Description { get; set; } + [Required] public string City { get; set; } [Required] diff --git a/src/Web/WebMVC/Views/Order/Detail.cshtml b/src/Web/WebMVC/Views/Order/Detail.cshtml index c3a371275..ef112a1c2 100644 --- a/src/Web/WebMVC/Views/Order/Detail.cshtml +++ b/src/Web/WebMVC/Views/Order/Detail.cshtml @@ -21,8 +21,18 @@
@Model.OrderNumber
@Model.Date
-
$ @Model.Total
-
@Model.Status
+
$@Model.Total
+
@Model.Status
+
+ + +
+
+
Description
+
+ +
+
@Model.Description
diff --git a/src/Web/WebSPA/Client/modules/orders/orders-detail/orders-detail.component.html b/src/Web/WebSPA/Client/modules/orders/orders-detail/orders-detail.component.html index 62f6c8431..db88ed7a3 100644 --- a/src/Web/WebSPA/Client/modules/orders/orders-detail/orders-detail.component.html +++ b/src/Web/WebSPA/Client/modules/orders/orders-detail/orders-detail.component.html @@ -17,6 +17,16 @@
{{order.status}}
+ +
+
+
Description
+
+ +
+
{{order.description}}
+
+
diff --git a/src/Web/WebSPA/Client/modules/shared/models/order-detail.model.ts b/src/Web/WebSPA/Client/modules/shared/models/order-detail.model.ts index 25a869f9c..5631d8807 100644 --- a/src/Web/WebSPA/Client/modules/shared/models/order-detail.model.ts +++ b/src/Web/WebSPA/Client/modules/shared/models/order-detail.model.ts @@ -3,6 +3,7 @@ import {IOrderItem} from './orderItem.model'; export interface IOrderDetail { ordernumber: string; status: string; + description: string; street: string; date: Date; city: number;