Merge branch 'order-processflow-redesign' of https://github.com/dotnet-architecture/eShopOnContainers into order-processflow-redesign
This commit is contained in:
commit
8abf1e36a5
@ -11,7 +11,6 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word
|
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word
|
||||||
- EventBusConnection=rabbitmq
|
- EventBusConnection=rabbitmq
|
||||||
- GracePeriod=15 #In minutes
|
|
||||||
|
|
||||||
basket.api:
|
basket.api:
|
||||||
environment:
|
environment:
|
||||||
|
@ -53,16 +53,16 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers
|
|||||||
|
|
||||||
[Route("checkout")]
|
[Route("checkout")]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> Checkout([FromBody]BasketCheckout value, [FromHeader(Name = "x-requestid")] string requestId)
|
public async Task<IActionResult> Checkout([FromBody]BasketCheckout basketCheckout, [FromHeader(Name = "x-requestid")] string requestId)
|
||||||
{
|
{
|
||||||
var userId = _identitySvc.GetUserIdentity();
|
var userId = _identitySvc.GetUserIdentity();
|
||||||
value.RequestId = (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty) ?
|
basketCheckout.RequestId = (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty) ?
|
||||||
guid : value.RequestId;
|
guid : basketCheckout.RequestId;
|
||||||
|
|
||||||
var basket = await _repository.GetBasketAsync(userId);
|
var basket = await _repository.GetBasketAsync(userId);
|
||||||
var eventMessage = new UserCheckoutAcceptedIntegrationEvent(userId, value.City, value.Street,
|
var eventMessage = new UserCheckoutAcceptedIntegrationEvent(userId, basketCheckout.City, basketCheckout.Street,
|
||||||
value.State, value.Country, value.ZipCode, value.CardNumber, value.CardHolderName,
|
basketCheckout.State, basketCheckout.Country, basketCheckout.ZipCode, basketCheckout.CardNumber, basketCheckout.CardHolderName,
|
||||||
value.CardExpiration, value.CardSecurityNumber, value.CardTypeId, value.Buyer, value.RequestId, basket);
|
basketCheckout.CardExpiration, basketCheckout.CardSecurityNumber, basketCheckout.CardTypeId, basketCheckout.Buyer, basketCheckout.RequestId, basket);
|
||||||
|
|
||||||
// Once basket is checkout, sends an integration event to
|
// Once basket is checkout, sends an integration event to
|
||||||
// ordering.api to convert basket to order and proceeds with
|
// ordering.api to convert basket to order and proceeds with
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationCommands.CommandHandlers
|
namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.EventHandling
|
||||||
{
|
{
|
||||||
using BuildingBlocks.EventBus.Abstractions;
|
using BuildingBlocks.EventBus.Abstractions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -6,53 +6,41 @@
|
|||||||
using Infrastructure;
|
using Infrastructure;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using global::Catalog.API.Infrastructure.Exceptions;
|
|
||||||
using global::Catalog.API.IntegrationEvents;
|
using global::Catalog.API.IntegrationEvents;
|
||||||
using Model;
|
|
||||||
using Commands;
|
|
||||||
using IntegrationEvents.Events;
|
using IntegrationEvents.Events;
|
||||||
|
|
||||||
public class ConfirmOrderStockCommandHandler : IIntegrationEventHandler<ConfirmOrderStockCommand>
|
public class OrderStatusChangedToAwaitingValidationIntegrationEventHandler :
|
||||||
|
IIntegrationEventHandler<OrderStatusChangedToAwaitingValidationIntegrationEvent>
|
||||||
{
|
{
|
||||||
private readonly CatalogContext _catalogContext;
|
private readonly CatalogContext _catalogContext;
|
||||||
private readonly ICatalogIntegrationEventService _catalogIntegrationEventService;
|
private readonly ICatalogIntegrationEventService _catalogIntegrationEventService;
|
||||||
|
|
||||||
public ConfirmOrderStockCommandHandler(CatalogContext catalogContext,
|
public OrderStatusChangedToAwaitingValidationIntegrationEventHandler(CatalogContext catalogContext,
|
||||||
ICatalogIntegrationEventService catalogIntegrationEventService)
|
ICatalogIntegrationEventService catalogIntegrationEventService)
|
||||||
{
|
{
|
||||||
_catalogContext = catalogContext;
|
_catalogContext = catalogContext;
|
||||||
_catalogIntegrationEventService = catalogIntegrationEventService;
|
_catalogIntegrationEventService = catalogIntegrationEventService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Handle(ConfirmOrderStockCommand command)
|
public async Task Handle(OrderStatusChangedToAwaitingValidationIntegrationEvent command)
|
||||||
{
|
{
|
||||||
var confirmedOrderStockItems = new List<ConfirmedOrderStockItem>();
|
var confirmedOrderStockItems = new List<ConfirmedOrderStockItem>();
|
||||||
|
|
||||||
foreach (var orderStockItem in command.OrderStockItems)
|
foreach (var orderStockItem in command.OrderStockItems)
|
||||||
{
|
{
|
||||||
var catalogItem = _catalogContext.CatalogItems.Find(orderStockItem.ProductId);
|
var catalogItem = _catalogContext.CatalogItems.Find(orderStockItem.ProductId);
|
||||||
CheckValidcatalogItemId(catalogItem);
|
var hasStock = catalogItem.AvailableStock >= orderStockItem.Units;
|
||||||
|
var confirmedOrderStockItem = new ConfirmedOrderStockItem(catalogItem.Id, hasStock);
|
||||||
var confirmedOrderStockItem = new ConfirmedOrderStockItem(catalogItem.Id,
|
|
||||||
catalogItem.AvailableStock >= orderStockItem.Units);
|
|
||||||
|
|
||||||
confirmedOrderStockItems.Add(confirmedOrderStockItem);
|
confirmedOrderStockItems.Add(confirmedOrderStockItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
var confirmedIntegrationEvent = confirmedOrderStockItems.Any(c => !c.HasStock)
|
var confirmedIntegrationEvent = confirmedOrderStockItems.Any(c => !c.HasStock)
|
||||||
? (IntegrationEvent) new OrderStockNotConfirmedIntegrationEvent(command.OrderId, confirmedOrderStockItems)
|
? (IntegrationEvent) new OrderStockRejectedIntegrationEvent(command.OrderId, confirmedOrderStockItems)
|
||||||
: new OrderStockConfirmedIntegrationEvent(command.OrderId);
|
: new OrderStockConfirmedIntegrationEvent(command.OrderId);
|
||||||
|
|
||||||
await _catalogIntegrationEventService.SaveEventAndCatalogContextChangesAsync(confirmedIntegrationEvent);
|
await _catalogIntegrationEventService.SaveEventAndCatalogContextChangesAsync(confirmedIntegrationEvent);
|
||||||
await _catalogIntegrationEventService.PublishThroughEventBusAsync(confirmedIntegrationEvent);
|
await _catalogIntegrationEventService.PublishThroughEventBusAsync(confirmedIntegrationEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CheckValidcatalogItemId(CatalogItem catalogItem)
|
|
||||||
{
|
|
||||||
if (catalogItem is null)
|
|
||||||
{
|
|
||||||
throw new CatalogDomainException("Not able to process catalog event. Reason: no valid catalogItemId");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,20 +1,21 @@
|
|||||||
namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationCommands.CommandHandlers
|
namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.EventHandling
|
||||||
{
|
{
|
||||||
using BuildingBlocks.EventBus.Abstractions;
|
using BuildingBlocks.EventBus.Abstractions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Infrastructure;
|
using Infrastructure;
|
||||||
using Commands;
|
using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events;
|
||||||
|
|
||||||
public class DecrementOrderStockCommandHandler : IIntegrationEventHandler<DecrementOrderStockCommand>
|
public class OrderStatusChangedToPaidIntegrationEventHandler :
|
||||||
|
IIntegrationEventHandler<OrderStatusChangedToPaidIntegrationEvent>
|
||||||
{
|
{
|
||||||
private readonly CatalogContext _catalogContext;
|
private readonly CatalogContext _catalogContext;
|
||||||
|
|
||||||
public DecrementOrderStockCommandHandler(CatalogContext catalogContext)
|
public OrderStatusChangedToPaidIntegrationEventHandler(CatalogContext catalogContext)
|
||||||
{
|
{
|
||||||
_catalogContext = catalogContext;
|
_catalogContext = catalogContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Handle(DecrementOrderStockCommand command)
|
public async Task Handle(OrderStatusChangedToPaidIntegrationEvent command)
|
||||||
{
|
{
|
||||||
//we're not blocking stock/inventory
|
//we're not blocking stock/inventory
|
||||||
foreach (var orderStockItem in command.OrderStockItems)
|
foreach (var orderStockItem in command.OrderStockItems)
|
@ -1,14 +1,14 @@
|
|||||||
namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationCommands.Commands
|
namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events
|
||||||
{
|
{
|
||||||
using BuildingBlocks.EventBus.Events;
|
using BuildingBlocks.EventBus.Events;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
public class ConfirmOrderStockCommand : IntegrationEvent
|
public class OrderStatusChangedToAwaitingValidationIntegrationEvent : IntegrationEvent
|
||||||
{
|
{
|
||||||
public int OrderId { get; }
|
public int OrderId { get; }
|
||||||
public IEnumerable<OrderStockItem> OrderStockItems { get; }
|
public IEnumerable<OrderStockItem> OrderStockItems { get; }
|
||||||
|
|
||||||
public ConfirmOrderStockCommand(int orderId,
|
public OrderStatusChangedToAwaitingValidationIntegrationEvent(int orderId,
|
||||||
IEnumerable<OrderStockItem> orderStockItems)
|
IEnumerable<OrderStockItem> orderStockItems)
|
||||||
{
|
{
|
||||||
OrderId = orderId;
|
OrderId = orderId;
|
@ -1,14 +1,14 @@
|
|||||||
namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationCommands.Commands
|
namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events
|
||||||
{
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
|
||||||
public class DecrementOrderStockCommand : IntegrationEvent
|
public class OrderStatusChangedToPaidIntegrationEvent : IntegrationEvent
|
||||||
{
|
{
|
||||||
public int OrderId { get; }
|
public int OrderId { get; }
|
||||||
public IEnumerable<OrderStockItem> OrderStockItems { get; }
|
public IEnumerable<OrderStockItem> OrderStockItems { get; }
|
||||||
|
|
||||||
public DecrementOrderStockCommand(int orderId,
|
public OrderStatusChangedToPaidIntegrationEvent(int orderId,
|
||||||
IEnumerable<OrderStockItem> orderStockItems)
|
IEnumerable<OrderStockItem> orderStockItems)
|
||||||
{
|
{
|
||||||
OrderId = orderId;
|
OrderId = orderId;
|
@ -3,13 +3,13 @@
|
|||||||
using BuildingBlocks.EventBus.Events;
|
using BuildingBlocks.EventBus.Events;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
public class OrderStockNotConfirmedIntegrationEvent : IntegrationEvent
|
public class OrderStockRejectedIntegrationEvent : IntegrationEvent
|
||||||
{
|
{
|
||||||
public int OrderId { get; }
|
public int OrderId { get; }
|
||||||
|
|
||||||
public List<ConfirmedOrderStockItem> OrderStockItems { get; }
|
public List<ConfirmedOrderStockItem> OrderStockItems { get; }
|
||||||
|
|
||||||
public OrderStockNotConfirmedIntegrationEvent(int orderId,
|
public OrderStockRejectedIntegrationEvent(int orderId,
|
||||||
List<ConfirmedOrderStockItem> orderStockItems)
|
List<ConfirmedOrderStockItem> orderStockItems)
|
||||||
{
|
{
|
||||||
OrderId = orderId;
|
OrderId = orderId;
|
@ -14,9 +14,8 @@
|
|||||||
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
|
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services;
|
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services;
|
||||||
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
|
||||||
using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationCommands.Commands;
|
using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.EventHandling;
|
||||||
using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents;
|
using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events;
|
||||||
using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationCommands.CommandHandlers;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.HealthChecks;
|
using Microsoft.Extensions.HealthChecks;
|
||||||
@ -27,7 +26,7 @@
|
|||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
using System.Data.SqlClient;
|
using System.Data.SqlClient;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
public class Startup
|
public class Startup
|
||||||
{
|
{
|
||||||
public IConfigurationRoot Configuration { get; }
|
public IConfigurationRoot Configuration { get; }
|
||||||
@ -190,19 +189,20 @@
|
|||||||
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();
|
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();
|
||||||
services.AddSingleton<IEventBus, EventBusRabbitMQ>();
|
services.AddSingleton<IEventBus, EventBusRabbitMQ>();
|
||||||
|
|
||||||
services.AddTransient<IIntegrationEventHandler<ConfirmOrderStockCommand>,
|
services.AddTransient<IIntegrationEventHandler<OrderStatusChangedToAwaitingValidationIntegrationEvent>,
|
||||||
ConfirmOrderStockCommandHandler>();
|
OrderStatusChangedToAwaitingValidationIntegrationEventHandler>();
|
||||||
services.AddTransient<IIntegrationEventHandler<DecrementOrderStockCommand>,
|
services.AddTransient<IIntegrationEventHandler<OrderStatusChangedToPaidIntegrationEvent>,
|
||||||
DecrementOrderStockCommandHandler>();
|
OrderStatusChangedToPaidIntegrationEventHandler>();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ConfigureEventBus(IApplicationBuilder app)
|
private void ConfigureEventBus(IApplicationBuilder app)
|
||||||
{
|
{
|
||||||
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();
|
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();
|
||||||
|
|
||||||
eventBus.Subscribe<ConfirmOrderStockCommand, IIntegrationEventHandler<ConfirmOrderStockCommand>>();
|
eventBus.Subscribe<OrderStatusChangedToAwaitingValidationIntegrationEvent,
|
||||||
eventBus.Subscribe<DecrementOrderStockCommand, IIntegrationEventHandler<DecrementOrderStockCommand>>();
|
IIntegrationEventHandler<OrderStatusChangedToAwaitingValidationIntegrationEvent>>();
|
||||||
|
eventBus.Subscribe<OrderStatusChangedToPaidIntegrationEvent,
|
||||||
|
IIntegrationEventHandler<OrderStatusChangedToPaidIntegrationEvent>>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,11 +36,7 @@ namespace Ordering.API.Application.DomainEventHandlers.BuyerAndPaymentMethodVeri
|
|||||||
|
|
||||||
var orderStartedIntegrationEvent = new OrderStartedIntegrationEvent(buyerPaymentMethodVerifiedEvent.Buyer.IdentityGuid);
|
var orderStartedIntegrationEvent = new OrderStartedIntegrationEvent(buyerPaymentMethodVerifiedEvent.Buyer.IdentityGuid);
|
||||||
|
|
||||||
await _orderingIntegrationEventService
|
await _orderingIntegrationEventService.PublishThroughEventBusAsync(orderStartedIntegrationEvent);
|
||||||
.SaveEventAndOrderingContextChangesAsync(orderStartedIntegrationEvent);
|
|
||||||
|
|
||||||
await _orderingIntegrationEventService
|
|
||||||
.PublishThroughEventBusAsync(orderStartedIntegrationEvent);
|
|
||||||
|
|
||||||
_logger.CreateLogger(nameof(UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler))
|
_logger.CreateLogger(nameof(UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler))
|
||||||
.LogTrace($"Order with Id: {buyerPaymentMethodVerifiedEvent.OrderId} has been successfully updated with a payment method id: { buyerPaymentMethodVerifiedEvent.Payment.Id }");
|
.LogTrace($"Order with Id: {buyerPaymentMethodVerifiedEvent.OrderId} has been successfully updated with a payment method id: { buyerPaymentMethodVerifiedEvent.Payment.Id }");
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
using Domain.Events;
|
using Domain.Events;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ordering.API.Application.IntegrationCommands.Commands;
|
|
||||||
using Ordering.API.Application.IntegrationEvents;
|
using Ordering.API.Application.IntegrationEvents;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Ordering.API.Application.IntegrationEvents.Events;
|
||||||
|
|
||||||
public class OrderStatusChangedToAwaitingValidationDomainEventHandler
|
public class OrderStatusChangedToAwaitingValidationDomainEventHandler
|
||||||
: IAsyncNotificationHandler<OrderStatusChangedToAwaitingValidationDomainEvent>
|
: IAsyncNotificationHandler<OrderStatusChangedToAwaitingValidationDomainEvent>
|
||||||
@ -35,10 +35,9 @@
|
|||||||
var orderStockList = orderStatusChangedToAwaitingValidationDomainEvent.OrderItems
|
var orderStockList = orderStatusChangedToAwaitingValidationDomainEvent.OrderItems
|
||||||
.Select(orderItem => new OrderStockItem(orderItem.ProductId, orderItem.GetUnits()));
|
.Select(orderItem => new OrderStockItem(orderItem.ProductId, orderItem.GetUnits()));
|
||||||
|
|
||||||
var confirmOrderStockCommand = new ConfirmOrderStockCommand(orderStatusChangedToAwaitingValidationDomainEvent.OrderId,
|
var orderStatusChangedToAwaitingValidationIntegrationEvent = new OrderStatusChangedToAwaitingValidationIntegrationEvent(
|
||||||
orderStockList);
|
orderStatusChangedToAwaitingValidationDomainEvent.OrderId, orderStockList);
|
||||||
await _orderingIntegrationEventService.SaveEventAndOrderingContextChangesAsync(confirmOrderStockCommand);
|
await _orderingIntegrationEventService.PublishThroughEventBusAsync(orderStatusChangedToAwaitingValidationIntegrationEvent);
|
||||||
await _orderingIntegrationEventService.PublishThroughEventBusAsync(confirmOrderStockCommand);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,9 +6,9 @@
|
|||||||
using Domain.Events;
|
using Domain.Events;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ordering.API.Application.IntegrationCommands.Commands;
|
|
||||||
using Ordering.API.Application.IntegrationEvents;
|
using Ordering.API.Application.IntegrationEvents;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Ordering.API.Application.IntegrationEvents.Events;
|
||||||
|
|
||||||
public class OrderStatusChangedToPaidDomainEventHandler
|
public class OrderStatusChangedToPaidDomainEventHandler
|
||||||
: IAsyncNotificationHandler<OrderStatusChangedToPaidDomainEvent>
|
: IAsyncNotificationHandler<OrderStatusChangedToPaidDomainEvent>
|
||||||
@ -35,10 +35,9 @@
|
|||||||
var orderStockList = orderStatusChangedToPaidDomainEvent.OrderItems
|
var orderStockList = orderStatusChangedToPaidDomainEvent.OrderItems
|
||||||
.Select(orderItem => new OrderStockItem(orderItem.ProductId, orderItem.GetUnits()));
|
.Select(orderItem => new OrderStockItem(orderItem.ProductId, orderItem.GetUnits()));
|
||||||
|
|
||||||
var decrementOrderStockCommand = new DecrementOrderStockCommand(orderStatusChangedToPaidDomainEvent.OrderId,
|
var orderStatusChangedToPaidIntegrationEvent = new OrderStatusChangedToPaidIntegrationEvent(orderStatusChangedToPaidDomainEvent.OrderId,
|
||||||
orderStockList);
|
orderStockList);
|
||||||
await _orderingIntegrationEventService.SaveEventAndOrderingContextChangesAsync(decrementOrderStockCommand);
|
await _orderingIntegrationEventService.PublishThroughEventBusAsync(orderStatusChangedToPaidIntegrationEvent);
|
||||||
await _orderingIntegrationEventService.PublishThroughEventBusAsync(decrementOrderStockCommand);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,8 +6,8 @@
|
|||||||
using Domain.Events;
|
using Domain.Events;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ordering.API.Application.IntegrationCommands.Commands;
|
|
||||||
using Ordering.API.Application.IntegrationEvents;
|
using Ordering.API.Application.IntegrationEvents;
|
||||||
|
using Ordering.API.Application.IntegrationEvents.Events;
|
||||||
|
|
||||||
public class OrderStatusChangedToStockConfirmedDomainEventHandler
|
public class OrderStatusChangedToStockConfirmedDomainEventHandler
|
||||||
: IAsyncNotificationHandler<OrderStatusChangedToStockConfirmedDomainEvent>
|
: IAsyncNotificationHandler<OrderStatusChangedToStockConfirmedDomainEvent>
|
||||||
@ -31,9 +31,8 @@
|
|||||||
.LogTrace($"Order with Id: {orderStatusChangedToStockConfirmedDomainEvent.OrderId} has been successfully updated with " +
|
.LogTrace($"Order with Id: {orderStatusChangedToStockConfirmedDomainEvent.OrderId} has been successfully updated with " +
|
||||||
$"a status order id: {OrderStatus.StockConfirmed.Id}");
|
$"a status order id: {OrderStatus.StockConfirmed.Id}");
|
||||||
|
|
||||||
var payOrderCommand = new PayOrderCommand(orderStatusChangedToStockConfirmedDomainEvent.OrderId);
|
var orderStatusChangedToStockConfirmedIntegrationEvent = new OrderStatusChangedToStockConfirmedIntegrationEvent(orderStatusChangedToStockConfirmedDomainEvent.OrderId);
|
||||||
await _orderingIntegrationEventService.SaveEventAndOrderingContextChangesAsync(payOrderCommand);
|
await _orderingIntegrationEventService.PublishThroughEventBusAsync(orderStatusChangedToStockConfirmedIntegrationEvent);
|
||||||
await _orderingIntegrationEventService.PublishThroughEventBusAsync(payOrderCommand);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,12 +0,0 @@
|
|||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
|
||||||
|
|
||||||
namespace Ordering.API.Application.IntegrationCommands.Commands
|
|
||||||
{
|
|
||||||
public class ConfirmGracePeriodCommand : IntegrationEvent
|
|
||||||
{
|
|
||||||
public int OrderId { get; }
|
|
||||||
|
|
||||||
public ConfirmGracePeriodCommand(int orderId) =>
|
|
||||||
OrderId = orderId;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
namespace Ordering.API.Application.IntegrationCommands.Commands
|
|
||||||
{
|
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
|
||||||
|
|
||||||
public class PayOrderCommand : IntegrationEvent
|
|
||||||
{
|
|
||||||
public int OrderId { get; }
|
|
||||||
|
|
||||||
public PayOrderCommand(int orderId)
|
|
||||||
{
|
|
||||||
OrderId = orderId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
public async Task Handle(OrderPaymentFailedIntegrationEvent @event)
|
public async Task Handle(OrderPaymentFailedIntegrationEvent @event)
|
||||||
{
|
{
|
||||||
var orderToUpdate = await _orderRepository.GetWithDependenciesAsync(@event.OrderId);
|
var orderToUpdate = await _orderRepository.GetAsync(@event.OrderId);
|
||||||
|
|
||||||
orderToUpdate.SetCancelledStatus();
|
orderToUpdate.SetCancelledStatus();
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
public async Task Handle(OrderPaymentSuccededIntegrationEvent @event)
|
public async Task Handle(OrderPaymentSuccededIntegrationEvent @event)
|
||||||
{
|
{
|
||||||
var orderToUpdate = await _orderRepository.GetWithDependenciesAsync(@event.OrderId);
|
var orderToUpdate = await _orderRepository.GetAsync(@event.OrderId);
|
||||||
|
|
||||||
orderToUpdate.SetPaidStatus();
|
orderToUpdate.SetPaidStatus();
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
public async Task Handle(OrderStockConfirmedIntegrationEvent @event)
|
public async Task Handle(OrderStockConfirmedIntegrationEvent @event)
|
||||||
{
|
{
|
||||||
var orderToUpdate = await _orderRepository.GetWithDependenciesAsync(@event.OrderId);
|
var orderToUpdate = await _orderRepository.GetAsync(@event.OrderId);
|
||||||
|
|
||||||
orderToUpdate.SetStockConfirmedStatus();
|
orderToUpdate.SetStockConfirmedStatus();
|
||||||
|
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
using System.Linq;
|
|
||||||
using Ordering.API.Application.IntegrationCommands.Commands;
|
|
||||||
|
|
||||||
namespace Ordering.API.Application.IntegrationEvents.EventHandling
|
|
||||||
{
|
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Events;
|
|
||||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
|
|
||||||
|
|
||||||
public class OrderStockNotConfirmedIntegrationEventHandler : IIntegrationEventHandler<OrderStockNotConfirmedIntegrationEvent>
|
|
||||||
{
|
|
||||||
private readonly IOrderRepository _orderRepository;
|
|
||||||
|
|
||||||
public OrderStockNotConfirmedIntegrationEventHandler(IOrderRepository orderRepository)
|
|
||||||
{
|
|
||||||
_orderRepository = orderRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Handle(OrderStockNotConfirmedIntegrationEvent @event)
|
|
||||||
{
|
|
||||||
var orderToUpdate = await _orderRepository.GetWithDependenciesAsync(@event.OrderId);
|
|
||||||
|
|
||||||
var orderStockNotConfirmedItems = @event.OrderStockItems
|
|
||||||
.FindAll(c => !c.HasStock)
|
|
||||||
.Select(c => c.ProductId);
|
|
||||||
|
|
||||||
orderToUpdate.SetStockConfirmedStatus(orderStockNotConfirmedItems);
|
|
||||||
|
|
||||||
await _orderRepository.UnitOfWork.SaveEntitiesAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,31 @@
|
|||||||
|
namespace Ordering.API.Application.IntegrationEvents.EventHandling
|
||||||
|
{
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Events;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
|
||||||
|
|
||||||
|
public class OrderStockRejectedIntegrationEventHandler : IIntegrationEventHandler<OrderStockRejectedIntegrationEvent>
|
||||||
|
{
|
||||||
|
private readonly IOrderRepository _orderRepository;
|
||||||
|
|
||||||
|
public OrderStockRejectedIntegrationEventHandler(IOrderRepository orderRepository)
|
||||||
|
{
|
||||||
|
_orderRepository = orderRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Handle(OrderStockRejectedIntegrationEvent @event)
|
||||||
|
{
|
||||||
|
var orderToUpdate = await _orderRepository.GetAsync(@event.OrderId);
|
||||||
|
|
||||||
|
var orderStockRejectedItems = @event.OrderStockItems
|
||||||
|
.FindAll(c => !c.HasStock)
|
||||||
|
.Select(c => c.ProductId);
|
||||||
|
|
||||||
|
orderToUpdate.SetCancelledStatusWhenStockIsRejected(orderStockRejectedItems);
|
||||||
|
|
||||||
|
await _orderRepository.UnitOfWork.SaveEntitiesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
namespace Ordering.API.Application.IntegrationEvents.Events
|
||||||
|
{
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
|
||||||
|
public class GracePeriodConfirmedIntegrationEvent : IntegrationEvent
|
||||||
|
{
|
||||||
|
public int OrderId { get; }
|
||||||
|
|
||||||
|
public GracePeriodConfirmedIntegrationEvent(int orderId) =>
|
||||||
|
OrderId = orderId;
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,11 @@
|
|||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
namespace Ordering.API.Application.IntegrationEvents.Events
|
||||||
|
|
||||||
namespace Ordering.API.Application.IntegrationEvents.Events
|
|
||||||
{
|
{
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
|
||||||
public class OrderPaymentFailedIntegrationEvent : IntegrationEvent
|
public class OrderPaymentFailedIntegrationEvent : IntegrationEvent
|
||||||
{
|
{
|
||||||
public int OrderId { get; }
|
public int OrderId { get; }
|
||||||
|
|
||||||
public OrderPaymentFailedIntegrationEvent(int orderId) => OrderId = orderId;
|
public OrderPaymentFailedIntegrationEvent(int orderId) => OrderId = orderId;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,11 +1,11 @@
|
|||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
namespace Ordering.API.Application.IntegrationEvents.Events
|
||||||
|
|
||||||
namespace Ordering.API.Application.IntegrationEvents.Events
|
|
||||||
{
|
{
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
|
||||||
public class OrderPaymentSuccededIntegrationEvent : IntegrationEvent
|
public class OrderPaymentSuccededIntegrationEvent : IntegrationEvent
|
||||||
{
|
{
|
||||||
public int OrderId { get; }
|
public int OrderId { get; }
|
||||||
|
|
||||||
public OrderPaymentSuccededIntegrationEvent(int orderId) => OrderId = orderId;
|
public OrderPaymentSuccededIntegrationEvent(int orderId) => OrderId = orderId;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,14 +1,14 @@
|
|||||||
namespace Ordering.API.Application.IntegrationCommands.Commands
|
namespace Ordering.API.Application.IntegrationEvents.Events
|
||||||
{
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
|
||||||
public class ConfirmOrderStockCommand : IntegrationEvent
|
public class OrderStatusChangedToAwaitingValidationIntegrationEvent : IntegrationEvent
|
||||||
{
|
{
|
||||||
public int OrderId { get; }
|
public int OrderId { get; }
|
||||||
public IEnumerable<OrderStockItem> OrderStockItems { get; }
|
public IEnumerable<OrderStockItem> OrderStockItems { get; }
|
||||||
|
|
||||||
public ConfirmOrderStockCommand(int orderId,
|
public OrderStatusChangedToAwaitingValidationIntegrationEvent(int orderId,
|
||||||
IEnumerable<OrderStockItem> orderStockItems)
|
IEnumerable<OrderStockItem> orderStockItems)
|
||||||
{
|
{
|
||||||
OrderId = orderId;
|
OrderId = orderId;
|
@ -1,14 +1,14 @@
|
|||||||
namespace Ordering.API.Application.IntegrationCommands.Commands
|
namespace Ordering.API.Application.IntegrationEvents.Events
|
||||||
{
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
|
||||||
public class DecrementOrderStockCommand : IntegrationEvent
|
public class OrderStatusChangedToPaidIntegrationEvent : IntegrationEvent
|
||||||
{
|
{
|
||||||
public int OrderId { get; }
|
public int OrderId { get; }
|
||||||
public IEnumerable<OrderStockItem> OrderStockItems { get; }
|
public IEnumerable<OrderStockItem> OrderStockItems { get; }
|
||||||
|
|
||||||
public DecrementOrderStockCommand(int orderId,
|
public OrderStatusChangedToPaidIntegrationEvent(int orderId,
|
||||||
IEnumerable<OrderStockItem> orderStockItems)
|
IEnumerable<OrderStockItem> orderStockItems)
|
||||||
{
|
{
|
||||||
OrderId = orderId;
|
OrderId = orderId;
|
@ -0,0 +1,12 @@
|
|||||||
|
namespace Ordering.API.Application.IntegrationEvents.Events
|
||||||
|
{
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
|
||||||
|
public class OrderStatusChangedToStockConfirmedIntegrationEvent : IntegrationEvent
|
||||||
|
{
|
||||||
|
public int OrderId { get; }
|
||||||
|
|
||||||
|
public OrderStatusChangedToStockConfirmedIntegrationEvent(int orderId)
|
||||||
|
=> OrderId = orderId;
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,15 @@
|
|||||||
using System.Collections.Generic;
|
namespace Ordering.API.Application.IntegrationEvents.Events
|
||||||
|
|
||||||
namespace Ordering.API.Application.IntegrationEvents.Events
|
|
||||||
{
|
{
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
public class OrderStockNotConfirmedIntegrationEvent : IntegrationEvent
|
public class OrderStockRejectedIntegrationEvent : IntegrationEvent
|
||||||
{
|
{
|
||||||
public int OrderId { get; }
|
public int OrderId { get; }
|
||||||
|
|
||||||
public List<ConfirmedOrderStockItem> OrderStockItems { get; }
|
public List<ConfirmedOrderStockItem> OrderStockItems { get; }
|
||||||
|
|
||||||
public OrderStockNotConfirmedIntegrationEvent(int orderId,
|
public OrderStockRejectedIntegrationEvent(int orderId,
|
||||||
List<ConfirmedOrderStockItem> orderStockItems)
|
List<ConfirmedOrderStockItem> orderStockItems)
|
||||||
{
|
{
|
||||||
OrderId = orderId;
|
OrderId = orderId;
|
@ -5,7 +5,6 @@ namespace Ordering.API.Application.IntegrationEvents
|
|||||||
{
|
{
|
||||||
public interface IOrderingIntegrationEventService
|
public interface IOrderingIntegrationEventService
|
||||||
{
|
{
|
||||||
Task SaveEventAndOrderingContextChangesAsync(IntegrationEvent evt);
|
|
||||||
Task PublishThroughEventBusAsync(IntegrationEvent evt);
|
Task PublishThroughEventBusAsync(IntegrationEvent evt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,11 +30,12 @@ namespace Ordering.API.Application.IntegrationEvents
|
|||||||
|
|
||||||
public async Task PublishThroughEventBusAsync(IntegrationEvent evt)
|
public async Task PublishThroughEventBusAsync(IntegrationEvent evt)
|
||||||
{
|
{
|
||||||
|
await SaveEventAndOrderingContextChangesAsync(evt);
|
||||||
_eventBus.Publish(evt);
|
_eventBus.Publish(evt);
|
||||||
await _eventLogService.MarkEventAsPublishedAsync(evt);
|
await _eventLogService.MarkEventAsPublishedAsync(evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SaveEventAndOrderingContextChangesAsync(IntegrationEvent evt)
|
private async Task SaveEventAndOrderingContextChangesAsync(IntegrationEvent evt)
|
||||||
{
|
{
|
||||||
//Use of an EF Core resiliency strategy when using multiple DbContexts within an explicit BeginTransaction():
|
//Use of an EF Core resiliency strategy when using multiple DbContexts within an explicit BeginTransaction():
|
||||||
//See: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
|
//See: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
|
||||||
|
@ -5,8 +5,7 @@ using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.Order
|
|||||||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure;
|
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure;
|
||||||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency;
|
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency;
|
||||||
using Ordering.API.Application.Commands;
|
using Ordering.API.Application.Commands;
|
||||||
using Ordering.API.Application.IntegrationCommands.Commands;
|
using Ordering.API.Application.IntegrationEvents.Events;
|
||||||
using Ordering.API.Application.IntegrationEvents;
|
|
||||||
using Ordering.Domain.Exceptions;
|
using Ordering.Domain.Exceptions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -21,7 +20,7 @@ namespace Ordering.API.Application.Sagas
|
|||||||
/// with the validations.
|
/// with the validations.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class OrderProcessSaga : OrderSaga,
|
public class OrderProcessSaga : OrderSaga,
|
||||||
IIntegrationEventHandler<ConfirmGracePeriodCommand>,
|
IIntegrationEventHandler<GracePeriodConfirmedIntegrationEvent>,
|
||||||
IAsyncRequestHandler<CancelOrderCommand, bool>,
|
IAsyncRequestHandler<CancelOrderCommand, bool>,
|
||||||
IAsyncRequestHandler<ShipOrderCommand, bool>
|
IAsyncRequestHandler<ShipOrderCommand, bool>
|
||||||
{
|
{
|
||||||
@ -43,9 +42,9 @@ namespace Ordering.API.Application.Sagas
|
|||||||
/// period has completed.
|
/// period has completed.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task Handle(ConfirmGracePeriodCommand command)
|
public async Task Handle(GracePeriodConfirmedIntegrationEvent @event)
|
||||||
{
|
{
|
||||||
var orderSaga = FindSagaById(command.OrderId);
|
var orderSaga = FindSagaById(@event.OrderId);
|
||||||
CheckValidSagaId(orderSaga);
|
CheckValidSagaId(orderSaga);
|
||||||
|
|
||||||
orderSaga.SetAwaitingValidationStatus();
|
orderSaga.SetAwaitingValidationStatus();
|
||||||
@ -96,8 +95,6 @@ namespace Ordering.API.Application.Sagas
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#region CommandHandlerIdentifiers
|
|
||||||
|
|
||||||
public class CancelOrderCommandIdentifiedHandler : IdentifierCommandHandler<CancelOrderCommand, bool>
|
public class CancelOrderCommandIdentifiedHandler : IdentifierCommandHandler<CancelOrderCommand, bool>
|
||||||
{
|
{
|
||||||
public CancelOrderCommandIdentifiedHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager)
|
public CancelOrderCommandIdentifiedHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager)
|
||||||
@ -121,7 +118,5 @@ namespace Ordering.API.Application.Sagas
|
|||||||
return true; // Ignore duplicate requests for processing order.
|
return true; // Ignore duplicate requests for processing order.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,12 +17,11 @@ namespace Ordering.API.Application.Sagas
|
|||||||
|
|
||||||
public override Order FindSagaById(int id)
|
public override Order FindSagaById(int id)
|
||||||
{
|
{
|
||||||
var order = _orderingContext.Orders
|
return _orderingContext.Orders
|
||||||
.Include(c => c.OrderStatus)
|
.Include(c => c.OrderStatus)
|
||||||
.Include(c => c.OrderItems)
|
.Include(c => c.OrderItems)
|
||||||
|
.Include(c => c.Address)
|
||||||
.Single(c => c.Id == id);
|
.Single(c => c.Id == id);
|
||||||
|
|
||||||
return order;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<bool> SaveChangesAsync()
|
public override async Task<bool> SaveChangesAsync()
|
||||||
|
@ -79,7 +79,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Application\IntegrationCommands\CommandHandlers\" />
|
|
||||||
<Folder Include="Infrastructure\IntegrationEventMigrations\" />
|
<Folder Include="Infrastructure\IntegrationEventMigrations\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@ -3,11 +3,9 @@
|
|||||||
using AspNetCore.Http;
|
using AspNetCore.Http;
|
||||||
using Autofac;
|
using Autofac;
|
||||||
using Autofac.Extensions.DependencyInjection;
|
using Autofac.Extensions.DependencyInjection;
|
||||||
using global::Ordering.API.Application.IntegrationCommands.Commands;
|
|
||||||
using global::Ordering.API.Application.IntegrationEvents;
|
using global::Ordering.API.Application.IntegrationEvents;
|
||||||
using global::Ordering.API.Application.IntegrationEvents.EventHandling;
|
using global::Ordering.API.Application.IntegrationEvents.EventHandling;
|
||||||
using global::Ordering.API.Application.IntegrationEvents.Events;
|
using global::Ordering.API.Application.IntegrationEvents.Events;
|
||||||
using global::Ordering.API.Application.Sagas;
|
|
||||||
using global::Ordering.API.Infrastructure.Middlewares;
|
using global::Ordering.API.Infrastructure.Middlewares;
|
||||||
using Infrastructure;
|
using Infrastructure;
|
||||||
using Infrastructure.Auth;
|
using Infrastructure.Auth;
|
||||||
@ -169,24 +167,18 @@
|
|||||||
{
|
{
|
||||||
services.AddSingleton<IEventBus, EventBusRabbitMQ>();
|
services.AddSingleton<IEventBus, EventBusRabbitMQ>();
|
||||||
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();
|
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();
|
||||||
services.AddTransient<IIntegrationEventHandler<ConfirmGracePeriodCommand>, OrderProcessSaga>();
|
|
||||||
services.AddTransient<UserCheckoutAcceptedIntegrationEventHandler>();
|
|
||||||
services.AddTransient<OrderStockConfirmedIntegrationEventHandler>();
|
|
||||||
services.AddTransient<OrderStockNotConfirmedIntegrationEventHandler>();
|
|
||||||
services.AddTransient<OrderPaymentFailedIntegrationEventHandler>();
|
|
||||||
services.AddTransient<OrderPaymentSuccededIntegrationEventHandler>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ConfigureEventBus(IApplicationBuilder app)
|
private void ConfigureEventBus(IApplicationBuilder app)
|
||||||
{
|
{
|
||||||
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();
|
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();
|
||||||
|
|
||||||
eventBus.Subscribe<ConfirmGracePeriodCommand, IIntegrationEventHandler<ConfirmGracePeriodCommand>>();
|
eventBus.Subscribe<UserCheckoutAcceptedIntegrationEvent, IIntegrationEventHandler<UserCheckoutAcceptedIntegrationEvent>>();
|
||||||
eventBus.Subscribe<UserCheckoutAcceptedIntegrationEvent, UserCheckoutAcceptedIntegrationEventHandler>();
|
eventBus.Subscribe<GracePeriodConfirmedIntegrationEvent, IIntegrationEventHandler<GracePeriodConfirmedIntegrationEvent>>();
|
||||||
eventBus.Subscribe<OrderStockConfirmedIntegrationEvent, OrderStockConfirmedIntegrationEventHandler>();
|
eventBus.Subscribe<OrderStockConfirmedIntegrationEvent, IIntegrationEventHandler<OrderStockConfirmedIntegrationEvent>>();
|
||||||
eventBus.Subscribe<OrderStockNotConfirmedIntegrationEvent, OrderStockNotConfirmedIntegrationEventHandler>();
|
eventBus.Subscribe<OrderStockRejectedIntegrationEvent, IIntegrationEventHandler<OrderStockRejectedIntegrationEvent>>();
|
||||||
eventBus.Subscribe<OrderPaymentFailedIntegrationEvent, OrderPaymentFailedIntegrationEventHandler>();
|
eventBus.Subscribe<OrderPaymentFailedIntegrationEvent, IIntegrationEventHandler<OrderPaymentFailedIntegrationEvent>>();
|
||||||
eventBus.Subscribe<OrderPaymentSuccededIntegrationEvent, OrderPaymentSuccededIntegrationEventHandler>();
|
eventBus.Subscribe<OrderPaymentSuccededIntegrationEvent, IIntegrationEventHandler<OrderPaymentSuccededIntegrationEvent>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void ConfigureAuth(IApplicationBuilder app)
|
protected virtual void ConfigureAuth(IApplicationBuilder app)
|
||||||
|
@ -17,6 +17,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
|
|||||||
|
|
||||||
public String ZipCode { get; private set; }
|
public String ZipCode { get; private set; }
|
||||||
|
|
||||||
|
private Address() { }
|
||||||
|
|
||||||
public Address(string street, string city, string state, string country, string zipcode)
|
public Address(string street, string city, string state, string country, string zipcode)
|
||||||
{
|
{
|
||||||
Street = street;
|
Street = street;
|
||||||
|
@ -13,7 +13,5 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
|
|||||||
void Update(Order order);
|
void Update(Order order);
|
||||||
|
|
||||||
Task<Order> GetAsync(int orderId);
|
Task<Order> GetAsync(int orderId);
|
||||||
|
|
||||||
Task<Order> GetWithDependenciesAsync(int orderId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,14 +94,12 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
|
|||||||
_buyerId = id;
|
_buyerId = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Status Changes
|
|
||||||
|
|
||||||
public void SetAwaitingValidationStatus()
|
public void SetAwaitingValidationStatus()
|
||||||
{
|
{
|
||||||
if (_orderStatusId != OrderStatus.Submited.Id &&
|
if (_orderStatusId == OrderStatus.Cancelled.Id ||
|
||||||
_orderStatusId != OrderStatus.Cancelled.Id)
|
_orderStatusId != OrderStatus.Submited.Id)
|
||||||
{
|
{
|
||||||
StatusChangeException();
|
StatusChangeException(OrderStatus.AwaitingValidation);
|
||||||
}
|
}
|
||||||
|
|
||||||
AddDomainEvent(new OrderStatusChangedToAwaitingValidationDomainEvent(Id, _orderItems));
|
AddDomainEvent(new OrderStatusChangedToAwaitingValidationDomainEvent(Id, _orderItems));
|
||||||
@ -109,38 +107,24 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
|
|||||||
_orderStatusId = OrderStatus.AwaitingValidation.Id;
|
_orderStatusId = OrderStatus.AwaitingValidation.Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetStockConfirmedStatus(IEnumerable<int> orderStockNotConfirmedItems = null)
|
public void SetStockConfirmedStatus()
|
||||||
{
|
{
|
||||||
if (_orderStatusId != OrderStatus.AwaitingValidation.Id)
|
if (_orderStatusId != OrderStatus.AwaitingValidation.Id)
|
||||||
{
|
{
|
||||||
StatusChangeException();
|
StatusChangeException(OrderStatus.StockConfirmed);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (orderStockNotConfirmedItems is null)
|
AddDomainEvent(new OrderStatusChangedToStockConfirmedDomainEvent(Id));
|
||||||
{
|
|
||||||
AddDomainEvent(new OrderStatusChangedToStockConfirmedDomainEvent(Id));
|
|
||||||
|
|
||||||
_orderStatusId = OrderStatus.StockConfirmed.Id;
|
_orderStatusId = OrderStatus.StockConfirmed.Id;
|
||||||
_description = "All the items were confirmed with available stock.";
|
_description = "All the items were confirmed with available stock.";
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_orderStatusId = OrderStatus.Cancelled.Id;
|
|
||||||
|
|
||||||
var itemsStockNotConfirmedProductNames = OrderItems
|
|
||||||
.Where(c => orderStockNotConfirmedItems.Contains(c.ProductId))
|
|
||||||
.Select(c => c.GetOrderItemProductName());
|
|
||||||
|
|
||||||
var itemsStockNotConfirmedDescription = string.Join(", ", itemsStockNotConfirmedProductNames);
|
|
||||||
_description = $"The product items don't have stock: ({itemsStockNotConfirmedDescription}).";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetPaidStatus()
|
public void SetPaidStatus()
|
||||||
{
|
{
|
||||||
if (_orderStatusId != OrderStatus.StockConfirmed.Id)
|
if (_orderStatusId != OrderStatus.StockConfirmed.Id)
|
||||||
{
|
{
|
||||||
StatusChangeException();
|
StatusChangeException(OrderStatus.Paid);
|
||||||
}
|
}
|
||||||
|
|
||||||
AddDomainEvent(new OrderStatusChangedToPaidDomainEvent(Id, OrderItems));
|
AddDomainEvent(new OrderStatusChangedToPaidDomainEvent(Id, OrderItems));
|
||||||
@ -153,40 +137,41 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
|
|||||||
{
|
{
|
||||||
if (_orderStatusId != OrderStatus.Paid.Id)
|
if (_orderStatusId != OrderStatus.Paid.Id)
|
||||||
{
|
{
|
||||||
StatusChangeException();
|
StatusChangeException(OrderStatus.Shipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
_orderStatusId = OrderStatus.Shipped.Id;
|
_orderStatusId = OrderStatus.Shipped.Id;
|
||||||
_description = "";
|
_description = "The order was shipped.";
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetCancelledStatus()
|
public void SetCancelledStatus()
|
||||||
{
|
{
|
||||||
if (_orderStatusId == OrderStatus.Submited.Id)
|
if (_orderStatusId == OrderStatus.Paid.Id ||
|
||||||
|
_orderStatusId == OrderStatus.Shipped.Id)
|
||||||
{
|
{
|
||||||
_description = "The order was cancelled before the grace period was confirmed.";
|
StatusChangeException(OrderStatus.Cancelled);
|
||||||
}
|
|
||||||
else if (_orderStatusId == OrderStatus.AwaitingValidation.Id)
|
|
||||||
{
|
|
||||||
_description = "The order was cancelled before to check the order stock items.";
|
|
||||||
}
|
|
||||||
else if (_orderStatusId == OrderStatus.StockConfirmed.Id)
|
|
||||||
{
|
|
||||||
_description = "The order was cancelled before to pay the order.";
|
|
||||||
}
|
|
||||||
else if (_orderStatusId == OrderStatus.Paid.Id)
|
|
||||||
{
|
|
||||||
_description = "The order was cancelled before to ship the order.";
|
|
||||||
}
|
|
||||||
else if(_orderStatusId == OrderStatus.Shipped.Id)
|
|
||||||
{
|
|
||||||
throw new OrderingDomainException("Not possible to change order status. Reason: cannot cancel order it is already shipped.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_orderStatusId = OrderStatus.Cancelled.Id;
|
_orderStatusId = OrderStatus.Cancelled.Id;
|
||||||
|
_description = $"The order was cancelled.";
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
public void SetCancelledStatusWhenStockIsRejected(IEnumerable<int> orderStockRejectedItems)
|
||||||
|
{
|
||||||
|
if (_orderStatusId != OrderStatus.AwaitingValidation.Id)
|
||||||
|
{
|
||||||
|
StatusChangeException(OrderStatus.Cancelled);
|
||||||
|
}
|
||||||
|
|
||||||
|
_orderStatusId = OrderStatus.Cancelled.Id;
|
||||||
|
|
||||||
|
var itemsStockRejectedProductNames = OrderItems
|
||||||
|
.Where(c => orderStockRejectedItems.Contains(c.ProductId))
|
||||||
|
.Select(c => c.GetOrderItemProductName());
|
||||||
|
|
||||||
|
var itemsStockRejectedDescription = string.Join(", ", itemsStockRejectedProductNames);
|
||||||
|
_description = $"The product items don't have stock: ({itemsStockRejectedDescription}).";
|
||||||
|
}
|
||||||
|
|
||||||
private void AddOrderStartedDomainEvent(string userId, int cardTypeId, string cardNumber,
|
private void AddOrderStartedDomainEvent(string userId, int cardTypeId, string cardNumber,
|
||||||
string cardSecurityNumber, string cardHolderName, DateTime cardExpiration)
|
string cardSecurityNumber, string cardHolderName, DateTime cardExpiration)
|
||||||
@ -198,9 +183,9 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
|
|||||||
this.AddDomainEvent(orderStartedDomainEvent);
|
this.AddDomainEvent(orderStartedDomainEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StatusChangeException()
|
private void StatusChangeException(OrderStatus orderStatusToChange)
|
||||||
{
|
{
|
||||||
throw new OrderingDomainException("Not able to process order event. Reason: no valid order status change");
|
throw new OrderingDomainException($"Not possible to change order status from {OrderStatus.Name} to {orderStatusToChange.Name}.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,15 +33,18 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Repositor
|
|||||||
|
|
||||||
public async Task<Order> GetAsync(int orderId)
|
public async Task<Order> GetAsync(int orderId)
|
||||||
{
|
{
|
||||||
return await _context.Orders.FindAsync(orderId);
|
var order = await _context.Orders.FindAsync(orderId);
|
||||||
}
|
if (order != null)
|
||||||
|
{
|
||||||
|
await _context.Entry(order)
|
||||||
|
.Collection(i => i.OrderItems).LoadAsync();
|
||||||
|
await _context.Entry(order)
|
||||||
|
.Reference(i => i.OrderStatus).LoadAsync();
|
||||||
|
await _context.Entry(order)
|
||||||
|
.Reference(i => i.Address).LoadAsync();
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<Order> GetWithDependenciesAsync(int orderId)
|
return order;
|
||||||
{
|
|
||||||
return await _context.Orders
|
|
||||||
.Include(c => c.OrderStatus)
|
|
||||||
.Include(c => c.OrderItems)
|
|
||||||
.SingleAsync(c => c.Id == orderId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update(Order order)
|
public void Update(Order order)
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
namespace Payment.API.IntegrationCommands.CommandHandlers
|
|
||||||
{
|
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
|
||||||
using Payment.API.IntegrationCommands.Commands;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Payment.API.IntegrationEvents;
|
|
||||||
using Payment.API.IntegrationEvents.Events;
|
|
||||||
|
|
||||||
public class PayOrderCommandHandler : IIntegrationEventHandler<PayOrderCommand>
|
|
||||||
{
|
|
||||||
private readonly IPaymentIntegrationEventService _paymentIntegrationEventService;
|
|
||||||
|
|
||||||
public PayOrderCommandHandler(IPaymentIntegrationEventService paymentIntegrationEventService)
|
|
||||||
=> _paymentIntegrationEventService = paymentIntegrationEventService;
|
|
||||||
|
|
||||||
public async Task Handle(PayOrderCommand @event)
|
|
||||||
{
|
|
||||||
//PAYMENT SUCCESSED
|
|
||||||
var orderPaymentSuccededIntegrationEvent = new OrderPaymentSuccededIntegrationEvent(@event.OrderId);
|
|
||||||
_paymentIntegrationEventService.PublishThroughEventBus(orderPaymentSuccededIntegrationEvent);
|
|
||||||
|
|
||||||
//PAYMENT FAILED
|
|
||||||
//var orderPaymentFailedIntegrationEvent = new OrderPaymentFailedIntegrationEvent(@event.OrderId);
|
|
||||||
//_paymentIntegrationEventService.PublishThroughEventBus(orderPaymentFailedIntegrationEvent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
namespace Payment.API.IntegrationCommands.Commands
|
|
||||||
{
|
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
|
||||||
|
|
||||||
public class PayOrderCommand : IntegrationEvent
|
|
||||||
{
|
|
||||||
public int OrderId { get; }
|
|
||||||
|
|
||||||
public PayOrderCommand(int orderId) => OrderId = orderId;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,37 @@
|
|||||||
|
namespace Payment.API.IntegrationEvents.EventHandling
|
||||||
|
{
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Payment.API.IntegrationEvents.Events;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
|
||||||
|
public class OrderStatusChangedToStockConfirmedIntegrationEventHandler :
|
||||||
|
IIntegrationEventHandler<OrderStatusChangedToStockConfirmedIntegrationEvent>
|
||||||
|
{
|
||||||
|
private readonly IEventBus _eventBus;
|
||||||
|
private readonly PaymentSettings _settings;
|
||||||
|
|
||||||
|
public OrderStatusChangedToStockConfirmedIntegrationEventHandler(IEventBus eventBus,
|
||||||
|
IOptionsSnapshot<PaymentSettings> settings)
|
||||||
|
{
|
||||||
|
_eventBus = eventBus;
|
||||||
|
_settings = settings.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Handle(OrderStatusChangedToStockConfirmedIntegrationEvent @event)
|
||||||
|
{
|
||||||
|
IntegrationEvent orderPaymentIntegrationEvent;
|
||||||
|
if(_settings.SuccessPayment)
|
||||||
|
{
|
||||||
|
orderPaymentIntegrationEvent = new OrderPaymentSuccededIntegrationEvent(@event.OrderId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
orderPaymentIntegrationEvent = new OrderPaymentFailedIntegrationEvent(@event.OrderId);
|
||||||
|
}
|
||||||
|
|
||||||
|
_eventBus.Publish(orderPaymentIntegrationEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
namespace Payment.API.IntegrationEvents.Events
|
||||||
|
{
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
|
||||||
|
public class OrderStatusChangedToStockConfirmedIntegrationEvent : IntegrationEvent
|
||||||
|
{
|
||||||
|
public int OrderId { get; }
|
||||||
|
|
||||||
|
public OrderStatusChangedToStockConfirmedIntegrationEvent(int orderId)
|
||||||
|
=> OrderId = orderId;
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +0,0 @@
|
|||||||
namespace Payment.API.IntegrationEvents
|
|
||||||
{
|
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
|
||||||
|
|
||||||
public interface IPaymentIntegrationEventService
|
|
||||||
{
|
|
||||||
void PublishThroughEventBus(IntegrationEvent evt);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
namespace Payment.API.IntegrationEvents
|
|
||||||
{
|
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
public class PaymentIntegrationEventService : IPaymentIntegrationEventService
|
|
||||||
{
|
|
||||||
private readonly IEventBus _eventBus;
|
|
||||||
|
|
||||||
public PaymentIntegrationEventService(IEventBus eventBus)
|
|
||||||
{
|
|
||||||
_eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PublishThroughEventBus(IntegrationEvent evt)
|
|
||||||
{
|
|
||||||
_eventBus.Publish(evt); ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
8
src/Services/Payment/Payment.API/PaymentSettings.cs
Normal file
8
src/Services/Payment/Payment.API/PaymentSettings.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace Payment.API
|
||||||
|
{
|
||||||
|
public class PaymentSettings
|
||||||
|
{
|
||||||
|
public bool SuccessPayment { get; set; }
|
||||||
|
public string EventBusConnection { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -7,12 +7,11 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
||||||
using Payment.API.IntegrationCommands.Commands;
|
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ;
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ;
|
||||||
using RabbitMQ.Client;
|
using RabbitMQ.Client;
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus;
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus;
|
||||||
using Payment.API.IntegrationEvents;
|
using Payment.API.IntegrationEvents.Events;
|
||||||
using Payment.API.IntegrationCommands.CommandHandlers;
|
using Payment.API.IntegrationEvents.EventHandling;
|
||||||
|
|
||||||
namespace Payment.API
|
namespace Payment.API
|
||||||
{
|
{
|
||||||
@ -35,8 +34,7 @@ namespace Payment.API
|
|||||||
{
|
{
|
||||||
// Add framework services.
|
// Add framework services.
|
||||||
services.AddMvc();
|
services.AddMvc();
|
||||||
|
services.Configure<PaymentSettings>(Configuration);
|
||||||
services.AddTransient<IPaymentIntegrationEventService, PaymentIntegrationEventService>();
|
|
||||||
services.AddSingleton<IRabbitMQPersistentConnection>(sp =>
|
services.AddSingleton<IRabbitMQPersistentConnection>(sp =>
|
||||||
{
|
{
|
||||||
var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>();
|
var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>();
|
||||||
@ -88,13 +86,15 @@ namespace Payment.API
|
|||||||
services.AddSingleton<IEventBus, EventBusRabbitMQ>();
|
services.AddSingleton<IEventBus, EventBusRabbitMQ>();
|
||||||
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();
|
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();
|
||||||
|
|
||||||
services.AddTransient<IIntegrationEventHandler<PayOrderCommand>, PayOrderCommandHandler>();
|
services.AddTransient<IIntegrationEventHandler<OrderStatusChangedToStockConfirmedIntegrationEvent>,
|
||||||
|
OrderStatusChangedToStockConfirmedIntegrationEventHandler>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ConfigureEventBus(IApplicationBuilder app)
|
private void ConfigureEventBus(IApplicationBuilder app)
|
||||||
{
|
{
|
||||||
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();
|
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();
|
||||||
eventBus.Subscribe<PayOrderCommand, IIntegrationEventHandler<PayOrderCommand>>();
|
eventBus.Subscribe<OrderStatusChangedToStockConfirmedIntegrationEvent,
|
||||||
|
IIntegrationEventHandler<OrderStatusChangedToStockConfirmedIntegrationEvent>>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,5 +4,6 @@
|
|||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Warning"
|
"Default": "Warning"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"SuccessPayment": "true"
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
{
|
{
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
|
||||||
public class ConfirmGracePeriodCommand : IntegrationEvent
|
public class GracePeriodConfirmedIntegrationEvent : IntegrationEvent
|
||||||
{
|
{
|
||||||
public int OrderId { get;}
|
public int OrderId { get;}
|
||||||
|
|
||||||
public ConfirmGracePeriodCommand(int orderId) => OrderId = orderId;
|
public GracePeriodConfirmedIntegrationEvent(int orderId) => OrderId = orderId;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,9 +0,0 @@
|
|||||||
namespace SagaManager.IntegrationEvents
|
|
||||||
{
|
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
|
||||||
|
|
||||||
public interface ISagaManagerIntegrationEventService
|
|
||||||
{
|
|
||||||
void PublishThroughEventBus(IntegrationEvent evt);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
namespace SagaManager.IntegrationEvents
|
|
||||||
{
|
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
|
||||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
public class SagaManagerIntegrationEventService : ISagaManagerIntegrationEventService
|
|
||||||
{
|
|
||||||
private readonly IEventBus _eventBus;
|
|
||||||
|
|
||||||
public SagaManagerIntegrationEventService(IEventBus eventBus)
|
|
||||||
=> _eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus));
|
|
||||||
|
|
||||||
|
|
||||||
public void PublishThroughEventBus(IntegrationEvent evt) => _eventBus.Publish(evt);
|
|
||||||
}
|
|
||||||
}
|
|
@ -14,7 +14,6 @@
|
|||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using RabbitMQ.Client;
|
using RabbitMQ.Client;
|
||||||
using Services;
|
using Services;
|
||||||
using IntegrationEvents;
|
|
||||||
|
|
||||||
public class Program
|
public class Program
|
||||||
{
|
{
|
||||||
@ -34,11 +33,13 @@
|
|||||||
|
|
||||||
var sagaManagerService = serviceProvider
|
var sagaManagerService = serviceProvider
|
||||||
.GetRequiredService<ISagaManagerService>();
|
.GetRequiredService<ISagaManagerService>();
|
||||||
|
var checkUpdateTime = serviceProvider
|
||||||
|
.GetRequiredService<IOptions<SagaManagerSettings>>().Value.CheckUpdateTime;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
sagaManagerService.CheckConfirmedGracePeriodOrders();
|
sagaManagerService.CheckConfirmedGracePeriodOrders();
|
||||||
await Task.Delay(90000);
|
await Task.Delay(checkUpdateTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,8 +59,6 @@
|
|||||||
.AddOptions()
|
.AddOptions()
|
||||||
.Configure<SagaManagerSettings>(Configuration)
|
.Configure<SagaManagerSettings>(Configuration)
|
||||||
.AddSingleton<ISagaManagerService, SagaManagerService>()
|
.AddSingleton<ISagaManagerService, SagaManagerService>()
|
||||||
.AddSingleton<ISagaManagerIntegrationEventService, SagaManagerIntegrationEventService>()
|
|
||||||
|
|
||||||
.AddSingleton<IRabbitMQPersistentConnection>(sp =>
|
.AddSingleton<IRabbitMQPersistentConnection>(sp =>
|
||||||
{
|
{
|
||||||
var settings = sp.GetRequiredService<IOptions<SagaManagerSettings>>().Value;
|
var settings = sp.GetRequiredService<IOptions<SagaManagerSettings>>().Value;
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
public string EventBusConnection { get; set; }
|
public string EventBusConnection { get; set; }
|
||||||
|
|
||||||
public int GracePeriod { get; set; }
|
public int GracePeriodTime { get; set; }
|
||||||
|
|
||||||
|
public int CheckUpdateTime { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,21 +5,21 @@
|
|||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Dapper;
|
using Dapper;
|
||||||
using IntegrationEvents;
|
|
||||||
using IntegrationEvents.Events;
|
using IntegrationEvents.Events;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
||||||
|
|
||||||
public class SagaManagerService : ISagaManagerService
|
public class SagaManagerService : ISagaManagerService
|
||||||
{
|
{
|
||||||
private readonly SagaManagerSettings _settings;
|
private readonly SagaManagerSettings _settings;
|
||||||
private readonly ISagaManagerIntegrationEventService _sagaManagerIntegrationEventService;
|
private readonly IEventBus _eventBus;
|
||||||
private readonly ILogger<SagaManagerService> _logger;
|
private readonly ILogger<SagaManagerService> _logger;
|
||||||
|
|
||||||
public SagaManagerService(IOptions<SagaManagerSettings> settings,
|
public SagaManagerService(IOptions<SagaManagerSettings> settings,
|
||||||
ISagaManagerIntegrationEventService sagaManagerIntegrationEventService,
|
IEventBus eventBus,
|
||||||
ILogger<SagaManagerService> logger)
|
ILogger<SagaManagerService> logger)
|
||||||
{
|
{
|
||||||
_settings = settings.Value;
|
_settings = settings.Value;
|
||||||
_sagaManagerIntegrationEventService = sagaManagerIntegrationEventService;
|
_eventBus = eventBus;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,8 +29,8 @@
|
|||||||
|
|
||||||
foreach (var orderId in orderIds)
|
foreach (var orderId in orderIds)
|
||||||
{
|
{
|
||||||
var confirmGracePeriodEvent = new ConfirmGracePeriodCommand(orderId);
|
var confirmGracePeriodEvent = new GracePeriodConfirmedIntegrationEvent(orderId);
|
||||||
_sagaManagerIntegrationEventService.PublishThroughEventBus(confirmGracePeriodEvent);
|
_eventBus.Publish(confirmGracePeriodEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,9 +45,9 @@
|
|||||||
conn.Open();
|
conn.Open();
|
||||||
orderIds = conn.Query<int>(
|
orderIds = conn.Query<int>(
|
||||||
@"SELECT Id FROM [Microsoft.eShopOnContainers.Services.OrderingDb].[ordering].[orders]
|
@"SELECT Id FROM [Microsoft.eShopOnContainers.Services.OrderingDb].[ordering].[orders]
|
||||||
WHERE DATEDIFF(hour, [OrderDate], GETDATE()) >= @GracePeriod
|
WHERE DATEDIFF(hour, [OrderDate], GETDATE()) >= @GracePeriodTime
|
||||||
AND [OrderStatusId] = 1",
|
AND [OrderStatusId] = 1",
|
||||||
new { GracePeriod = _settings.GracePeriod });
|
new { GracePeriodTime = _settings.GracePeriodTime });
|
||||||
}
|
}
|
||||||
catch (SqlException exception)
|
catch (SqlException exception)
|
||||||
{
|
{
|
||||||
|
@ -7,5 +7,7 @@
|
|||||||
"Microsoft": "Information"
|
"Microsoft": "Information"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ConnectionString": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;"
|
"ConnectionString": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;",
|
||||||
|
"GracePeriodTime": "15",
|
||||||
|
"CheckUpdateTime": "30000"
|
||||||
}
|
}
|
||||||
|
@ -31,9 +31,9 @@
|
|||||||
<a class="esh-orders-link" asp-controller="Order" asp-action="Detail" asp-route-orderId="@item.OrderNumber">Detail</a>
|
<a class="esh-orders-link" asp-controller="Order" asp-action="Detail" asp-route-orderId="@item.OrderNumber">Detail</a>
|
||||||
</section>
|
</section>
|
||||||
<section class="esh-orders-item col-xs-1">
|
<section class="esh-orders-item col-xs-1">
|
||||||
@if ((item.Status.ToLower() != "shipped") && (item.Status.ToLower() != "cancelled"))
|
@if (item.Status.ToLower() == "submited")
|
||||||
{
|
{
|
||||||
<a class="esh-orders-link" asp-controller="Order" asp-action="Cancel" asp-route-orderId="@item.OrderNumber">Cancel</a>
|
<a class="esh-orders-link" asp-controller="Order" asp-action="cancel" asp-route-orderId="@item.OrderNumber">Cancel</a>
|
||||||
}
|
}
|
||||||
</section>
|
</section>
|
||||||
</article>
|
</article>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user