Browse Source

Merge branch 'order-processflow-redesign' of https://github.com/dotnet-architecture/eShopOnContainers into order-processflow-redesign

pull/223/head
Ramón Tomás 7 years ago
parent
commit
8045d6302b
22 changed files with 396 additions and 45 deletions
  1. +0
    -3
      src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/BuyerAndPaymentMethodVerified/UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler.cs
  2. +10
    -13
      src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStockConfirmation/UpdateOrderWhenOrderStockMethodVerifiedDomainEventHandler.cs
  3. +14
    -0
      src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentFailedIntegrationEventHandler.cs
  4. +14
    -0
      src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentSuccededIntegrationEventHandler.cs
  5. +3
    -2
      src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockConfirmedIntegrationEventHandler.cs
  6. +7
    -8
      src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockNotConfirmedIntegrationEventHandler.cs
  7. +3
    -3
      src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs
  8. +11
    -0
      src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderPaymentFailedIntegrationEvent .cs
  9. +11
    -0
      src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderPaymentSuccededIntegrationEvent.cs
  10. +2
    -1
      src/Services/Ordering/Ordering.API/Application/Queries/OrderQueries.cs
  11. +3
    -3
      src/Services/Ordering/Ordering.API/Application/Sagas/OrderProcessSaga.cs
  12. +246
    -0
      src/Services/Ordering/Ordering.API/Infrastructure/Migrations/20170511112333_AddOrderDescription.Designer.cs
  13. +26
    -0
      src/Services/Ordering/Ordering.API/Infrastructure/Migrations/20170511112333_AddOrderDescription.cs
  14. +3
    -1
      src/Services/Ordering/Ordering.API/Infrastructure/Migrations/OrderingContextModelSnapshot.cs
  15. +15
    -7
      src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs
  16. +2
    -0
      src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderItem.cs
  17. +1
    -0
      src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs
  18. +0
    -2
      src/Services/SagaManager/SagaManager/Program.cs
  19. +2
    -0
      src/Web/WebMVC/ViewModels/Order.cs
  20. +12
    -2
      src/Web/WebMVC/Views/Order/Detail.cshtml
  21. +10
    -0
      src/Web/WebSPA/Client/modules/orders/orders-detail/orders-detail.component.html
  22. +1
    -0
      src/Web/WebSPA/Client/modules/shared/models/order-detail.model.ts

+ 0
- 3
src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/BuyerAndPaymentMethodVerified/UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler.cs View File

@ -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);


+ 10
- 13
src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderStockConfirmation/UpdateOrderWhenOrderStockMethodVerifiedDomainEventHandler.cs View File

@ -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<OrderStockMethodVerifiedDomainEvent>
{
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);
}
}
}

+ 14
- 0
src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentFailedIntegrationEventHandler.cs View File

@ -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<OrderPaymentFailedIntegrationEvent>
{
public async Task Handle(OrderPaymentFailedIntegrationEvent @event)
{
}
}
}

+ 14
- 0
src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderPaymentSuccededIntegrationEventHandler.cs View File

@ -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<OrderPaymentSuccededIntegrationEvent>
{
public async Task Handle(OrderPaymentSuccededIntegrationEvent @event)
{
}
}
}

+ 3
- 2
src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockConfirmedIntegrationEventHandler.cs View File

@ -7,7 +7,8 @@
using Ordering.API.Application.IntegrationCommands.Commands;
using Ordering.Domain.Exceptions;
public class OrderStockConfirmedIntegrationEventHandler : IIntegrationEventHandler<OrderStockConfirmedIntegrationEvent>
public class OrderStockConfirmedIntegrationEventHandler :
IIntegrationEventHandler<OrderStockConfirmedIntegrationEvent>
{
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);


+ 7
- 8
src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/OrderStockNotConfirmedIntegrationEventHandler.cs View File

@ -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)


+ 3
- 3
src/Services/Ordering/Ordering.API/Application/IntegrationEvents/EventHandling/UserCheckoutAcceptedIntegrationEventHandler.cs View File

@ -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
{


+ 11
- 0
src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderPaymentFailedIntegrationEvent .cs View File

@ -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;
}
}

+ 11
- 0
src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderPaymentSuccededIntegrationEvent.cs View File

@ -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;
}
}

+ 2
- 1
src/Services/Ordering/Ordering.API/Application/Queries/OrderQueries.cs View File

@ -26,7 +26,7 @@
connection.Open();
var result = await connection.QueryAsync<dynamic>(
@"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;


+ 3
- 3
src/Services/Ordering/Ordering.API/Application/Sagas/OrderProcessSaga.cs View File

@ -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.
/// </summary>
/// <param name="command">
/// <param name="event">
/// 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);
}
}


+ 246
- 0
src/Services/Ordering/Ordering.API/Infrastructure/Migrations/20170511112333_AddOrderDescription.Designer.cs View File

@ -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<int>("Id")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:HiLoSequenceName", "buyerseq")
.HasAnnotation("SqlServer:HiLoSequenceSchema", "ordering")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
b.Property<string>("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<int>("Id")
.HasDefaultValue(1);
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200);
b.HasKey("Id");
b.ToTable("cardtypes","ordering");
});
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.PaymentMethod", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:HiLoSequenceName", "paymentseq")
.HasAnnotation("SqlServer:HiLoSequenceSchema", "ordering")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
b.Property<string>("Alias")
.IsRequired()
.HasMaxLength(200);
b.Property<int>("BuyerId");
b.Property<string>("CardHolderName")
.IsRequired()
.HasMaxLength(200);
b.Property<string>("CardNumber")
.IsRequired()
.HasMaxLength(25);
b.Property<int>("CardTypeId");
b.Property<DateTime>("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<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("City");
b.Property<string>("Country");
b.Property<string>("State");
b.Property<string>("Street");
b.Property<string>("ZipCode");
b.HasKey("Id");
b.ToTable("address","ordering");
});
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.Order", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:HiLoSequenceName", "orderseq")
.HasAnnotation("SqlServer:HiLoSequenceSchema", "ordering")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
b.Property<int?>("AddressId");
b.Property<int?>("BuyerId");
b.Property<string>("Description");
b.Property<DateTime>("OrderDate");
b.Property<int>("OrderStatusId");
b.Property<int?>("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<int>("Id")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:HiLoSequenceName", "orderitemseq")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
b.Property<decimal>("Discount");
b.Property<int>("OrderId");
b.Property<string>("PictureUrl");
b.Property<int>("ProductId");
b.Property<string>("ProductName")
.IsRequired();
b.Property<decimal>("UnitPrice");
b.Property<int>("Units");
b.HasKey("Id");
b.HasIndex("OrderId");
b.ToTable("orderItems","ordering");
});
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderStatus", b =>
{
b.Property<int>("Id")
.HasDefaultValue(1);
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200);
b.HasKey("Id");
b.ToTable("orderstatus","ordering");
});
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency.ClientRequest", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Name")
.IsRequired();
b.Property<DateTime>("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);
});
}
}
}

+ 26
- 0
src/Services/Ordering/Ordering.API/Infrastructure/Migrations/20170511112333_AddOrderDescription.cs View File

@ -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<string>(
name: "Description",
schema: "ordering",
table: "orders",
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Description",
schema: "ordering",
table: "orders");
}
}
}

+ 3
- 1
src/Services/Ordering/Ordering.API/Infrastructure/Migrations/OrderingContextModelSnapshot.cs View File

@ -121,6 +121,8 @@ namespace Ordering.API.Migrations
b.Property<int?>("BuyerId");
b.Property<string>("Description");
b.Property<DateTime>("OrderDate");
b.Property<int>("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<Guid>("Id")
.ValueGeneratedOnAdd();


+ 15
- 7
src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs View File

@ -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<int> 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
}
}
}

+ 2
- 0
src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/OrderItem.cs View File

@ -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)


+ 1
- 0
src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs View File

@ -156,6 +156,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
orderConfiguration.Property<int?>("BuyerId").IsRequired(false);
orderConfiguration.Property<int>("OrderStatusId").IsRequired();
orderConfiguration.Property<int?>("PaymentMethodId").IsRequired(false);
orderConfiguration.Property<string>("Description").IsRequired(false);
var navigation = orderConfiguration.Metadata.FindNavigation(nameof(Order.OrderItems));
// DDD Patterns comment:


+ 0
- 2
src/Services/SagaManager/SagaManager/Program.cs View File

@ -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)


+ 2
- 0
src/Web/WebMVC/ViewModels/Order.cs View File

@ -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]


+ 12
- 2
src/Web/WebMVC/Views/Order/Detail.cshtml View File

@ -21,8 +21,18 @@
<article class="esh-orders_detail-items row">
<section class="esh-orders_detail-item col-xs-3">@Model.OrderNumber</section>
<section class="esh-orders_detail-item col-xs-3">@Model.Date</section>
<section class="esh-orders_detail-item col-xs-3">$ @Model.Total</section>
<section class="esh-orders_detail-item col-xs-3">@Model.Status</section>
<section class="esh-orders_detail-item col-xs-3">$@Model.Total</section>
<section class="esh-orders_detail-title col-xs-3">@Model.Status</section>
</article>
</section>
<section class="esh-orders_detail-section">
<article class="esh-orders_detail-titles row">
<section class="esh-orders_detail-title col-xs-12">Description</section>
</article>
<article class="esh-orders_detail-items row">
<section class="esh-orders_detail-item col-xs-12">@Model.Description</section>
</article>
</section>


+ 10
- 0
src/Web/WebSPA/Client/modules/orders/orders-detail/orders-detail.component.html View File

@ -17,6 +17,16 @@
<section class="esh-orders_detail-item col-xs-3">{{order.status}}</section>
</article>
</section>
<section class="esh-orders_detail-section">
<article class="esh-orders_detail-titles row">
<section class="esh-orders_detail-title col-xs-12">Description</section>
</article>
<article class="esh-orders_detail-items row">
<section class="esh-orders_detail-item col-xs-12">{{order.description}}</section>
</article>
</section>
<section class="esh-orders_detail-section">
<article class="esh-orders_detail-titles row">


+ 1
- 0
src/Web/WebSPA/Client/modules/shared/models/order-detail.model.ts View File

@ -3,6 +3,7 @@ import {IOrderItem} from './orderItem.model';
export interface IOrderDetail {
ordernumber: string;
status: string;
description: string;
street: string;
date: Date;
city: number;


Loading…
Cancel
Save