Merge branch 'dev' of https://github.com/dotnet/eShopOnContainers into dev
This commit is contained in:
commit
6bd17ead80
@ -39,6 +39,12 @@ EndProject
|
|||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ordering.Infrastructure", "src\Services\Ordering\Ordering.Infrastructure\Ordering.Infrastructure.csproj", "{95F1F07C-4D92-4742-BD07-E5B805AAB651}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ordering.Infrastructure", "src\Services\Ordering\Ordering.Infrastructure\Ordering.Infrastructure.csproj", "{95F1F07C-4D92-4742-BD07-E5B805AAB651}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTest", "test\Services\UnitTest\UnitTest.csproj", "{7796F5D8-31FC-45A4-B673-19DE5BA194CF}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTest", "test\Services\UnitTest\UnitTest.csproj", "{7796F5D8-31FC-45A4-B673-19DE5BA194CF}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{A579E108-5445-403D-A407-339AC4D1611B} = {A579E108-5445-403D-A407-339AC4D1611B}
|
||||||
|
{621E7211-58D0-45FD-9600-1CB490BD930E} = {621E7211-58D0-45FD-9600-1CB490BD930E}
|
||||||
|
{FEA0C318-FFED-4D39-8781-265718CA43DD} = {FEA0C318-FFED-4D39-8781-265718CA43DD}
|
||||||
|
{F16E3C6A-1C94-4EAB-BE91-099618060B68} = {F16E3C6A-1C94-4EAB-BE91-099618060B68}
|
||||||
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Identity.API", "src\Services\Identity\Identity.API\Identity.API.csproj", "{A579E108-5445-403D-A407-339AC4D1611B}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Identity.API", "src\Services\Identity\Identity.API\Identity.API.csproj", "{A579E108-5445-403D-A407-339AC4D1611B}"
|
||||||
EndProject
|
EndProject
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using MediatR;
|
using MediatR;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands
|
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands
|
||||||
{
|
{
|
||||||
@ -51,6 +52,12 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands
|
|||||||
[DataMember]
|
[DataMember]
|
||||||
public int CardTypeId { get; private set; }
|
public int CardTypeId { get; private set; }
|
||||||
|
|
||||||
|
[DataMember]
|
||||||
|
public int PaymentId { get; private set; }
|
||||||
|
|
||||||
|
[DataMember]
|
||||||
|
public int BuyerId { get; private set; }
|
||||||
|
|
||||||
[DataMember]
|
[DataMember]
|
||||||
public IEnumerable<OrderItemDTO> OrderItems => _orderItems;
|
public IEnumerable<OrderItemDTO> OrderItems => _orderItems;
|
||||||
|
|
||||||
@ -66,7 +73,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands
|
|||||||
|
|
||||||
public CreateOrderCommand(string city, string street, string state, string country, string zipcode,
|
public CreateOrderCommand(string city, string street, string state, string country, string zipcode,
|
||||||
string cardNumber, string cardHolderName, DateTime cardExpiration,
|
string cardNumber, string cardHolderName, DateTime cardExpiration,
|
||||||
string cardSecurityNumber, int cardTypeId) : this()
|
string cardSecurityNumber, int cardTypeId, int paymentId, int buyerId) : this()
|
||||||
{
|
{
|
||||||
City = city;
|
City = city;
|
||||||
Street = street;
|
Street = street;
|
||||||
@ -75,12 +82,14 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands
|
|||||||
ZipCode = zipcode;
|
ZipCode = zipcode;
|
||||||
CardNumber = cardNumber;
|
CardNumber = cardNumber;
|
||||||
CardHolderName = cardHolderName;
|
CardHolderName = cardHolderName;
|
||||||
|
CardExpiration = cardExpiration;
|
||||||
CardSecurityNumber = cardSecurityNumber;
|
CardSecurityNumber = cardSecurityNumber;
|
||||||
CardTypeId = cardTypeId;
|
CardTypeId = cardTypeId;
|
||||||
CardExpiration = cardExpiration;
|
CardExpiration = cardExpiration;
|
||||||
|
PaymentId = paymentId;
|
||||||
|
BuyerId = buyerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class OrderItemDTO
|
public class OrderItemDTO
|
||||||
{
|
{
|
||||||
public int ProductId { get; set; }
|
public int ProductId { get; set; }
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands
|
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands
|
||||||
{
|
{
|
||||||
using Domain.AggregatesModel.BuyerAggregate;
|
|
||||||
using Domain.AggregatesModel.OrderAggregate;
|
using Domain.AggregatesModel.OrderAggregate;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services;
|
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services;
|
||||||
@ -24,16 +23,16 @@
|
|||||||
public class CreateOrderCommandHandler
|
public class CreateOrderCommandHandler
|
||||||
: IAsyncRequestHandler<CreateOrderCommand, bool>
|
: IAsyncRequestHandler<CreateOrderCommand, bool>
|
||||||
{
|
{
|
||||||
private readonly IBuyerRepository<Buyer> _buyerRepository;
|
|
||||||
private readonly IOrderRepository<Order> _orderRepository;
|
private readonly IOrderRepository<Order> _orderRepository;
|
||||||
private readonly IIdentityService _identityService;
|
private readonly IIdentityService _identityService;
|
||||||
|
private readonly IMediator _mediator;
|
||||||
|
|
||||||
// Using DI to inject infrastructure persistence Repositories
|
// Using DI to inject infrastructure persistence Repositories
|
||||||
public CreateOrderCommandHandler(IBuyerRepository<Buyer> buyerRepository, IOrderRepository<Order> orderRepository, IIdentityService identityService)
|
public CreateOrderCommandHandler(IMediator mediator, IOrderRepository<Order> orderRepository, IIdentityService identityService)
|
||||||
{
|
{
|
||||||
_buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository));
|
|
||||||
_orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
|
_orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
|
||||||
_identityService = identityService ?? throw new ArgumentNullException(nameof(identityService));
|
_identityService = identityService ?? throw new ArgumentNullException(nameof(identityService));
|
||||||
|
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> Handle(CreateOrderCommand message)
|
public async Task<bool> Handle(CreateOrderCommand message)
|
||||||
@ -42,45 +41,18 @@
|
|||||||
// DDD patterns comment: Add child entities and value-objects through the Order Aggregate-Root
|
// DDD patterns comment: Add child entities and value-objects through the Order Aggregate-Root
|
||||||
// methods and constructor so validations, invariants and business logic
|
// methods and constructor so validations, invariants and business logic
|
||||||
// make sure that consistency is preserved across the whole aggregate
|
// make sure that consistency is preserved across the whole aggregate
|
||||||
|
var address = new Address(message.Street, message.City, message.State, message.Country, message.ZipCode);
|
||||||
var cardTypeId = message.CardTypeId != 0 ? message.CardTypeId : 1;
|
var order = new Order(address , message.CardTypeId, message.CardNumber, message.CardSecurityNumber, message.CardHolderName, message.CardExpiration);
|
||||||
|
|
||||||
var buyerGuid = _identityService.GetUserIdentity();
|
|
||||||
var buyer = await _buyerRepository.FindAsync(buyerGuid);
|
|
||||||
|
|
||||||
if (buyer == null)
|
|
||||||
{
|
|
||||||
buyer = new Buyer(buyerGuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
var payment = buyer.AddPaymentMethod(cardTypeId,
|
|
||||||
$"Payment Method on {DateTime.UtcNow}",
|
|
||||||
message.CardNumber,
|
|
||||||
message.CardSecurityNumber,
|
|
||||||
message.CardHolderName,
|
|
||||||
message.CardExpiration);
|
|
||||||
|
|
||||||
_buyerRepository.Add(buyer);
|
|
||||||
|
|
||||||
await _buyerRepository.UnitOfWork
|
|
||||||
.SaveChangesAsync();
|
|
||||||
|
|
||||||
// Create the Order AggregateRoot
|
|
||||||
// DDD patterns comment: Add child entities and value-objects through the Order Aggregate-Root
|
|
||||||
// methods and constructor so validations, invariants and business logic
|
|
||||||
// make sure that consistency is preserved across the whole aggregate
|
|
||||||
|
|
||||||
var order = new Order(buyer.Id, payment.Id, new Address(message.Street, message.City, message.State, message.Country, message.ZipCode));
|
|
||||||
|
|
||||||
foreach (var item in message.OrderItems)
|
foreach (var item in message.OrderItems)
|
||||||
{
|
{
|
||||||
order.AddOrderItem(item.ProductId, item.ProductName, item.UnitPrice, item.Discount, item.PictureUrl, item.Units);
|
order.AddOrderItem(item.ProductId, item.ProductName, item.UnitPrice, item.Discount, item.PictureUrl, item.Units);
|
||||||
}
|
}
|
||||||
|
|
||||||
_orderRepository.Add(order);
|
_orderRepository.Add(order);
|
||||||
|
|
||||||
var result = await _orderRepository.UnitOfWork
|
var result = await _orderRepository.UnitOfWork
|
||||||
.SaveChangesAsync();
|
.SaveEntitiesAsync();
|
||||||
|
|
||||||
return result > 0;
|
return result > 0;
|
||||||
|
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
using MediatR;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Ordering.Domain.Events;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Ordering.API.Application.EventHandlers
|
||||||
|
{
|
||||||
|
public class OrderCreatedEventHandler : IAsyncNotificationHandler<OrderCreated>
|
||||||
|
{
|
||||||
|
private readonly ILoggerFactory _logger;
|
||||||
|
private readonly IBuyerRepository<Buyer> _buyerRepository;
|
||||||
|
private readonly IIdentityService _identityService;
|
||||||
|
|
||||||
|
public OrderCreatedEventHandler(ILoggerFactory logger, IBuyerRepository<Buyer> buyerRepository, IIdentityService identityService)
|
||||||
|
{
|
||||||
|
_buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository));
|
||||||
|
_identityService = identityService ?? throw new ArgumentNullException(nameof(identityService));
|
||||||
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Handle(OrderCreated orderNotification)
|
||||||
|
{
|
||||||
|
var cardTypeId = orderNotification.CardTypeId != 0 ? orderNotification.CardTypeId : 1;
|
||||||
|
|
||||||
|
var buyerGuid = _identityService.GetUserIdentity();
|
||||||
|
var buyer = await _buyerRepository.FindAsync(buyerGuid);
|
||||||
|
|
||||||
|
if (buyer == null)
|
||||||
|
{
|
||||||
|
buyer = new Buyer(buyerGuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
var payment = buyer.AddPaymentMethod(cardTypeId,
|
||||||
|
$"Payment Method on {DateTime.UtcNow}",
|
||||||
|
orderNotification.CardNumber,
|
||||||
|
orderNotification.CardSecurityNumber,
|
||||||
|
orderNotification.CardHolderName,
|
||||||
|
orderNotification.CardExpiration,
|
||||||
|
orderNotification.Order.Id);
|
||||||
|
|
||||||
|
_buyerRepository.Add(buyer);
|
||||||
|
|
||||||
|
await _buyerRepository.UnitOfWork
|
||||||
|
.SaveEntitiesAsync();
|
||||||
|
|
||||||
|
_logger.CreateLogger(nameof(OrderCreatedEventHandler)).LogTrace($"A new payment method has been successfully added for orderId: {orderNotification.Order.Id}.");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
using MediatR;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Ordering.Domain.Events;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Ordering.API.Application.EventHandlers
|
||||||
|
{
|
||||||
|
public class PaymentMethodCheckedEventHandler : IAsyncNotificationHandler<PaymentMethodChecked>
|
||||||
|
{
|
||||||
|
private readonly IOrderRepository<Order> _orderRepository;
|
||||||
|
private readonly ILoggerFactory _logger;
|
||||||
|
public PaymentMethodCheckedEventHandler(IOrderRepository<Order> orderRepository, ILoggerFactory logger)
|
||||||
|
{
|
||||||
|
_orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
|
||||||
|
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Handle(PaymentMethodChecked paymentMethodNotification)
|
||||||
|
{
|
||||||
|
var orderToUpdate = await _orderRepository.GetAsync(paymentMethodNotification.OrderId);
|
||||||
|
orderToUpdate.SetBuyerId(paymentMethodNotification.Buyer.Id);
|
||||||
|
orderToUpdate.SetPaymentId(paymentMethodNotification.Payment.Id);
|
||||||
|
|
||||||
|
await _orderRepository.UnitOfWork
|
||||||
|
.SaveEntitiesAsync();
|
||||||
|
|
||||||
|
_logger.CreateLogger(nameof(PaymentMethodCheckedEventHandler))
|
||||||
|
.LogTrace($"Order with Id: {paymentMethodNotification.OrderId} has been successfully updated with a new payment method id: { paymentMethodNotification.Payment.Id }");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,4 @@
|
|||||||
using MediatR;
|
using MediatR;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
|
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
|
||||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries;
|
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries;
|
||||||
@ -28,19 +27,19 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers
|
|||||||
|
|
||||||
[Route("new")]
|
[Route("new")]
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> CreateOrder([FromBody]CreateOrderCommand createOrderCommand, [FromHeader(Name = "x-requestid")] string requestId)
|
public async Task<IActionResult> CreateOrder([FromBody]CreateOrderCommand command, [FromHeader(Name = "x-requestid")] string requestId)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty)
|
if (Guid.TryParse(requestId, out Guid guid) && guid != Guid.Empty)
|
||||||
{
|
{
|
||||||
var requestCreateOrder = new IdentifiedCommand<CreateOrderCommand, bool>(createOrderCommand, guid);
|
var requestCreateOrder = new IdentifiedCommand<CreateOrderCommand, bool>(command, guid);
|
||||||
result = await _mediator.SendAsync(requestCreateOrder);
|
result = await _mediator.SendAsync(requestCreateOrder);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If no x-requestid header is found we process the order anyway. This is just temporary to not break existing clients
|
// If no x-requestid header is found we process the order anyway. This is just temporary to not break existing clients
|
||||||
// that aren't still updated. When all clients were updated this could be removed.
|
// that aren't still updated. When all clients were updated this could be removed.
|
||||||
result = await _mediator.SendAsync(createOrderCommand);
|
result = await _mediator.SendAsync(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
@ -82,7 +81,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers
|
|||||||
var cardTypes = await _orderQueries.GetCardTypes();
|
var cardTypes = await _orderQueries.GetCardTypes();
|
||||||
|
|
||||||
return Ok(cardTypes);
|
return Ok(cardTypes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@ using Autofac.Core;
|
|||||||
using MediatR;
|
using MediatR;
|
||||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
|
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
|
||||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Decorators;
|
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Decorators;
|
||||||
|
using Ordering.API.Application.EventHandlers;
|
||||||
|
using Ordering.Domain.Events;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
@ -14,12 +16,17 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Autof
|
|||||||
protected override void Load(ContainerBuilder builder)
|
protected override void Load(ContainerBuilder builder)
|
||||||
{
|
{
|
||||||
builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly)
|
builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly)
|
||||||
.AsImplementedInterfaces();
|
.AsImplementedInterfaces();
|
||||||
|
|
||||||
builder.RegisterAssemblyTypes(typeof(CreateOrderCommand).GetTypeInfo().Assembly)
|
builder.RegisterAssemblyTypes(typeof(CreateOrderCommand).GetTypeInfo().Assembly)
|
||||||
.As(o => o.GetInterfaces()
|
.As(o => o.GetInterfaces()
|
||||||
.Where(i => i.IsClosedTypeOf(typeof(IAsyncRequestHandler<,>)))
|
.Where(i => i.IsClosedTypeOf(typeof(IAsyncRequestHandler<,>)))
|
||||||
.Select(i => new KeyedService("IAsyncRequestHandler", i)));
|
.Select(i => new KeyedService("IAsyncRequestHandler", i)));
|
||||||
|
|
||||||
|
builder
|
||||||
|
.RegisterAssemblyTypes(typeof(OrderCreatedEventHandler).GetTypeInfo().Assembly)
|
||||||
|
.Where(t => t.IsClosedTypeOf(typeof(IAsyncNotificationHandler<>)))
|
||||||
|
.AsImplementedInterfaces();
|
||||||
|
|
||||||
builder.Register<SingleInstanceFactory>(context =>
|
builder.Register<SingleInstanceFactory>(context =>
|
||||||
{
|
{
|
||||||
@ -37,7 +44,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Autof
|
|||||||
|
|
||||||
builder.RegisterGenericDecorator(typeof(LogDecorator<,>),
|
builder.RegisterGenericDecorator(typeof(LogDecorator<,>),
|
||||||
typeof(IAsyncRequestHandler<,>),
|
typeof(IAsyncRequestHandler<,>),
|
||||||
"IAsyncRequestHandler");
|
"IAsyncRequestHandler");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
244
src/Services/Ordering/Ordering.API/Infrastructure/Migrations/20170313100034_Domain_events.Designer.cs
generated
Normal file
244
src/Services/Ordering/Ordering.API/Infrastructure/Migrations/20170313100034_Domain_events.Designer.cs
generated
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
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("20170313100034_Domain_events")]
|
||||||
|
partial class Domain_events
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "1.1.0-rtm-22752")
|
||||||
|
.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<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.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", "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", "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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace Ordering.API.Migrations
|
||||||
|
{
|
||||||
|
public partial class Domain_events : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_orders_buyers_BuyerId",
|
||||||
|
schema: "ordering",
|
||||||
|
table: "orders");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<int>(
|
||||||
|
name: "PaymentMethodId",
|
||||||
|
schema: "ordering",
|
||||||
|
table: "orders",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(int));
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<int>(
|
||||||
|
name: "BuyerId",
|
||||||
|
schema: "ordering",
|
||||||
|
table: "orders",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(int));
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_orders_buyers_BuyerId",
|
||||||
|
schema: "ordering",
|
||||||
|
table: "orders",
|
||||||
|
column: "BuyerId",
|
||||||
|
principalSchema: "ordering",
|
||||||
|
principalTable: "buyers",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_orders_buyers_BuyerId",
|
||||||
|
schema: "ordering",
|
||||||
|
table: "orders");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<int>(
|
||||||
|
name: "PaymentMethodId",
|
||||||
|
schema: "ordering",
|
||||||
|
table: "orders",
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(int),
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<int>(
|
||||||
|
name: "BuyerId",
|
||||||
|
schema: "ordering",
|
||||||
|
table: "orders",
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(int),
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_orders_buyers_BuyerId",
|
||||||
|
schema: "ordering",
|
||||||
|
table: "orders",
|
||||||
|
column: "BuyerId",
|
||||||
|
principalSchema: "ordering",
|
||||||
|
principalTable: "buyers",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -119,13 +119,13 @@ namespace Ordering.API.Migrations
|
|||||||
|
|
||||||
b.Property<int?>("AddressId");
|
b.Property<int?>("AddressId");
|
||||||
|
|
||||||
b.Property<int>("BuyerId");
|
b.Property<int?>("BuyerId");
|
||||||
|
|
||||||
b.Property<DateTime>("OrderDate");
|
b.Property<DateTime>("OrderDate");
|
||||||
|
|
||||||
b.Property<int>("OrderStatusId");
|
b.Property<int>("OrderStatusId");
|
||||||
|
|
||||||
b.Property<int>("PaymentMethodId");
|
b.Property<int?>("PaymentMethodId");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
@ -183,7 +183,7 @@ namespace Ordering.API.Migrations
|
|||||||
b.ToTable("orderstatus","ordering");
|
b.ToTable("orderstatus","ordering");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Ordering.Infrastructure.ClientRequest", b =>
|
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.ClientRequest", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
.ValueGeneratedOnAdd();
|
.ValueGeneratedOnAdd();
|
||||||
@ -219,8 +219,7 @@ namespace Ordering.API.Migrations
|
|||||||
|
|
||||||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.Buyer", "Buyer")
|
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate.Buyer", "Buyer")
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("BuyerId")
|
.HasForeignKey("BuyerId");
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
|
||||||
|
|
||||||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderStatus", "OrderStatus")
|
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate.OrderStatus", "OrderStatus")
|
||||||
.WithMany()
|
.WithMany()
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork;
|
using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork;
|
||||||
|
using Ordering.Domain.Events;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B
|
|||||||
{
|
{
|
||||||
public string IdentityGuid { get; private set; }
|
public string IdentityGuid { get; private set; }
|
||||||
|
|
||||||
private List<PaymentMethod> _paymentMethods;
|
private List<PaymentMethod> _paymentMethods;
|
||||||
|
|
||||||
public IEnumerable<PaymentMethod> PaymentMethods => _paymentMethods.AsReadOnly();
|
public IEnumerable<PaymentMethod> PaymentMethods => _paymentMethods.AsReadOnly();
|
||||||
|
|
||||||
@ -22,16 +22,18 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B
|
|||||||
public Buyer(string identity) : this()
|
public Buyer(string identity) : this()
|
||||||
{
|
{
|
||||||
IdentityGuid = !string.IsNullOrWhiteSpace(identity) ? identity : throw new ArgumentNullException(nameof(identity));
|
IdentityGuid = !string.IsNullOrWhiteSpace(identity) ? identity : throw new ArgumentNullException(nameof(identity));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public PaymentMethod AddPaymentMethod(int cardTypeId, string alias, string cardNumber, string securityNumber, string cardHolderName, DateTime expiration)
|
public PaymentMethod AddPaymentMethod(
|
||||||
|
int cardTypeId, string alias, string cardNumber,
|
||||||
|
string securityNumber, string cardHolderName, DateTime expiration, int orderId)
|
||||||
{
|
{
|
||||||
var existingPayment = _paymentMethods.Where(p => p.IsEqualTo(cardTypeId, cardNumber, expiration))
|
var existingPayment = _paymentMethods.Where(p => p.IsEqualTo(cardTypeId, cardNumber, expiration))
|
||||||
.SingleOrDefault();
|
.SingleOrDefault();
|
||||||
|
|
||||||
if (existingPayment != null)
|
if (existingPayment != null)
|
||||||
{
|
{
|
||||||
|
AddEvent(new PaymentMethodChecked(this, existingPayment, orderId));
|
||||||
return existingPayment;
|
return existingPayment;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -39,9 +41,9 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B
|
|||||||
var payment = new PaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration);
|
var payment = new PaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration);
|
||||||
|
|
||||||
_paymentMethods.Add(payment);
|
_paymentMethods.Add(payment);
|
||||||
|
AddEvent(new PaymentMethodChecked(this, payment, orderId));
|
||||||
return payment;
|
return payment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork;
|
using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate
|
namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate
|
||||||
{
|
{
|
||||||
@ -8,5 +9,9 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
|
|||||||
public interface IOrderRepository<T> : IRepository<T> where T : IAggregateRoot
|
public interface IOrderRepository<T> : IRepository<T> where T : IAggregateRoot
|
||||||
{
|
{
|
||||||
Order Add(Order order);
|
Order Add(Order order);
|
||||||
|
|
||||||
|
Task<Order> GetAsync(int orderId);
|
||||||
|
|
||||||
|
void Update(Order order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate;
|
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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -17,7 +19,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
|
|||||||
public Address Address { get; private set; }
|
public Address Address { get; private set; }
|
||||||
|
|
||||||
public Buyer Buyer { get; private set; }
|
public Buyer Buyer { get; private set; }
|
||||||
private int _buyerId;
|
private int? _buyerId;
|
||||||
|
|
||||||
public OrderStatus OrderStatus { get; private set; }
|
public OrderStatus OrderStatus { get; private set; }
|
||||||
private int _orderStatusId;
|
private int _orderStatusId;
|
||||||
@ -36,11 +38,12 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
|
|||||||
//https://msdn.microsoft.com/en-us/library/e78dcd75(v=vs.110).aspx
|
//https://msdn.microsoft.com/en-us/library/e78dcd75(v=vs.110).aspx
|
||||||
|
|
||||||
public PaymentMethod PaymentMethod { get; private set; }
|
public PaymentMethod PaymentMethod { get; private set; }
|
||||||
private int _paymentMethodId;
|
private int? _paymentMethodId;
|
||||||
|
|
||||||
protected Order() { }
|
protected Order() { }
|
||||||
|
|
||||||
public Order(int buyerId, int paymentMethodId, Address address)
|
public Order(Address address, int cardTypeId, string cardNumber, string cardSecurityNumber,
|
||||||
|
string cardHolderName, DateTime cardExpiration, int? buyerId = null, int? paymentMethodId = null)
|
||||||
{
|
{
|
||||||
_orderItems = new List<OrderItem>();
|
_orderItems = new List<OrderItem>();
|
||||||
_buyerId = buyerId;
|
_buyerId = buyerId;
|
||||||
@ -48,6 +51,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
|
|||||||
_orderStatusId = OrderStatus.InProcess.Id;
|
_orderStatusId = OrderStatus.InProcess.Id;
|
||||||
_orderDate = DateTime.UtcNow;
|
_orderDate = DateTime.UtcNow;
|
||||||
Address = address;
|
Address = address;
|
||||||
|
AddCreatedOrderEvent(cardTypeId, cardNumber,
|
||||||
|
cardSecurityNumber, cardHolderName, cardExpiration);
|
||||||
}
|
}
|
||||||
|
|
||||||
// DDD Patterns comment
|
// DDD Patterns comment
|
||||||
@ -74,9 +79,28 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
|
|||||||
//add validated new order item
|
//add validated new order item
|
||||||
|
|
||||||
var orderItem = new OrderItem(productId, productName, unitPrice, discount, pictureUrl, units);
|
var orderItem = new OrderItem(productId, productName, unitPrice, discount, pictureUrl, units);
|
||||||
|
|
||||||
_orderItems.Add(orderItem);
|
_orderItems.Add(orderItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetPaymentId(int id)
|
||||||
|
{
|
||||||
|
_paymentMethodId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetBuyerId(int id)
|
||||||
|
{
|
||||||
|
_buyerId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddCreatedOrderEvent(int cardTypeId, string cardNumber,
|
||||||
|
string cardSecurityNumber, string cardHolderName, DateTime cardExpiration)
|
||||||
|
{
|
||||||
|
var @orderCreatedEvent = new OrderCreated(
|
||||||
|
this, cardTypeId, cardNumber, cardSecurityNumber,
|
||||||
|
cardHolderName, cardExpiration);
|
||||||
|
|
||||||
|
AddEvent(@orderCreatedEvent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
35
src/Services/Ordering/Ordering.Domain/Events/OrderCreated.cs
Normal file
35
src/Services/Ordering/Ordering.Domain/Events/OrderCreated.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
using MediatR;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Ordering.Domain.Events
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Event used when an order is created
|
||||||
|
/// </summary>
|
||||||
|
public class OrderCreated
|
||||||
|
: IAsyncNotification
|
||||||
|
{
|
||||||
|
public int CardTypeId { get; private set; }
|
||||||
|
public string CardNumber { get; private set; }
|
||||||
|
public string CardSecurityNumber { get; private set; }
|
||||||
|
public string CardHolderName { get; private set; }
|
||||||
|
public DateTime CardExpiration { get; private set; }
|
||||||
|
public Order Order { get; private set; }
|
||||||
|
|
||||||
|
public OrderCreated(Order order,
|
||||||
|
int cardTypeId, string cardNumber,
|
||||||
|
string cardSecurityNumber, string cardHolderName,
|
||||||
|
DateTime cardExpiration)
|
||||||
|
{
|
||||||
|
Order = order;
|
||||||
|
CardTypeId = cardTypeId;
|
||||||
|
CardNumber = cardNumber;
|
||||||
|
CardSecurityNumber = cardSecurityNumber;
|
||||||
|
CardHolderName = cardHolderName;
|
||||||
|
CardExpiration = cardExpiration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
using MediatR;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Ordering.Domain.Events
|
||||||
|
{
|
||||||
|
public class PaymentMethodChecked
|
||||||
|
: IAsyncNotification
|
||||||
|
{
|
||||||
|
public Buyer Buyer { get; private set; }
|
||||||
|
public PaymentMethod Payment { get; private set; }
|
||||||
|
public int OrderId { get; private set; }
|
||||||
|
|
||||||
|
public PaymentMethodChecked(Buyer buyer, PaymentMethod payment, int orderId)
|
||||||
|
{
|
||||||
|
Buyer = buyer;
|
||||||
|
Payment = payment;
|
||||||
|
OrderId = orderId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,4 +11,9 @@
|
|||||||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MediatR" Version="2.1.0" />
|
||||||
|
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="1.1.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork
|
namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork
|
||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
|
using MediatR;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
public abstract class Entity
|
public abstract class Entity
|
||||||
{
|
{
|
||||||
@ -9,6 +10,8 @@
|
|||||||
int? _requestedHashCode;
|
int? _requestedHashCode;
|
||||||
int _Id;
|
int _Id;
|
||||||
|
|
||||||
|
private List<IAsyncNotification> _events;
|
||||||
|
|
||||||
public virtual int Id
|
public virtual int Id
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -21,6 +24,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<IAsyncNotification> Events => _events;
|
||||||
|
public void AddEvent(IAsyncNotification eventItem)
|
||||||
|
{
|
||||||
|
_events = _events ?? new List<IAsyncNotification>();
|
||||||
|
_events.Add(eventItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveEvent(IAsyncNotification eventItem)
|
||||||
|
{
|
||||||
|
if (_events is null) return;
|
||||||
|
_events.Remove(eventItem);
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsTransient()
|
public bool IsTransient()
|
||||||
{
|
{
|
||||||
return this.Id == default(Int32);
|
return this.Id == default(Int32);
|
||||||
|
@ -5,7 +5,8 @@ using System.Threading.Tasks;
|
|||||||
namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork
|
namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork
|
||||||
{
|
{
|
||||||
public interface IUnitOfWork : IDisposable
|
public interface IUnitOfWork : IDisposable
|
||||||
{
|
{
|
||||||
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken));
|
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken));
|
||||||
|
Task<int> SaveEntitiesAsync(CancellationToken cancellationToken = default(CancellationToken));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
using MediatR;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Ordering.Infrastructure
|
||||||
|
{
|
||||||
|
public static class MediatorExtension
|
||||||
|
{
|
||||||
|
public static async Task RaiseDomainEventsAsync(this IMediator mediator, OrderingContext ctx)
|
||||||
|
{
|
||||||
|
var domainEntities = ctx.ChangeTracker.Entries<Entity>().Where(x => x.Entity.Events != null && x.Entity.Events.Any());
|
||||||
|
var domainEvents = domainEntities.SelectMany(x => x.Entity.Events).ToList();
|
||||||
|
domainEntities.ToList().ForEach(entity => entity.Entity.Events.Clear());
|
||||||
|
|
||||||
|
var tasks = domainEvents
|
||||||
|
.Select(async (domainEvent) => {
|
||||||
|
await mediator.PublishAsync(domainEvent);
|
||||||
|
});
|
||||||
|
|
||||||
|
await Task.WhenAll(tasks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,14 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using MediatR;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate;
|
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate;
|
||||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
|
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
|
||||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork;
|
using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork;
|
||||||
|
using Ordering.Infrastructure;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
|
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
|
||||||
{
|
{
|
||||||
@ -26,7 +30,12 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
|
|||||||
|
|
||||||
public DbSet<OrderStatus> OrderStatus { get; set; }
|
public DbSet<OrderStatus> OrderStatus { get; set; }
|
||||||
|
|
||||||
public OrderingContext(DbContextOptions options) : base(options) { }
|
private readonly IMediator _mediator;
|
||||||
|
|
||||||
|
public OrderingContext(DbContextOptions options, IMediator mediator) : base(options)
|
||||||
|
{
|
||||||
|
_mediator = mediator;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
@ -38,7 +47,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
|
|||||||
modelBuilder.Entity<OrderItem>(ConfigureOrderItems);
|
modelBuilder.Entity<OrderItem>(ConfigureOrderItems);
|
||||||
modelBuilder.Entity<CardType>(ConfigureCardTypes);
|
modelBuilder.Entity<CardType>(ConfigureCardTypes);
|
||||||
modelBuilder.Entity<OrderStatus>(ConfigureOrderStatus);
|
modelBuilder.Entity<OrderStatus>(ConfigureOrderStatus);
|
||||||
modelBuilder.Entity<Buyer>(ConfigureBuyer);
|
modelBuilder.Entity<Buyer>(ConfigureBuyer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ConfigureRequests(EntityTypeBuilder<ClientRequest> requestConfiguration)
|
private void ConfigureRequests(EntityTypeBuilder<ClientRequest> requestConfiguration)
|
||||||
@ -65,6 +74,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
|
|||||||
|
|
||||||
buyerConfiguration.HasKey(b => b.Id);
|
buyerConfiguration.HasKey(b => b.Id);
|
||||||
|
|
||||||
|
buyerConfiguration.Ignore(b => b.Events);
|
||||||
|
|
||||||
buyerConfiguration.Property(b => b.Id)
|
buyerConfiguration.Property(b => b.Id)
|
||||||
.ForSqlServerUseSequenceHiLo("buyerseq", DEFAULT_SCHEMA);
|
.ForSqlServerUseSequenceHiLo("buyerseq", DEFAULT_SCHEMA);
|
||||||
|
|
||||||
@ -91,6 +102,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
|
|||||||
|
|
||||||
paymentConfiguration.HasKey(b => b.Id);
|
paymentConfiguration.HasKey(b => b.Id);
|
||||||
|
|
||||||
|
paymentConfiguration.Ignore(b => b.Events);
|
||||||
|
|
||||||
paymentConfiguration.Property(b => b.Id)
|
paymentConfiguration.Property(b => b.Id)
|
||||||
.ForSqlServerUseSequenceHiLo("paymentseq", DEFAULT_SCHEMA);
|
.ForSqlServerUseSequenceHiLo("paymentseq", DEFAULT_SCHEMA);
|
||||||
|
|
||||||
@ -126,13 +139,15 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
|
|||||||
|
|
||||||
orderConfiguration.HasKey(o => o.Id);
|
orderConfiguration.HasKey(o => o.Id);
|
||||||
|
|
||||||
|
orderConfiguration.Ignore(b => b.Events);
|
||||||
|
|
||||||
orderConfiguration.Property(o => o.Id)
|
orderConfiguration.Property(o => o.Id)
|
||||||
.ForSqlServerUseSequenceHiLo("orderseq", DEFAULT_SCHEMA);
|
.ForSqlServerUseSequenceHiLo("orderseq", DEFAULT_SCHEMA);
|
||||||
|
|
||||||
orderConfiguration.Property<DateTime>("OrderDate").IsRequired();
|
orderConfiguration.Property<DateTime>("OrderDate").IsRequired();
|
||||||
orderConfiguration.Property<int>("BuyerId").IsRequired();
|
orderConfiguration.Property<int?>("BuyerId").IsRequired(false);
|
||||||
orderConfiguration.Property<int>("OrderStatusId").IsRequired();
|
orderConfiguration.Property<int>("OrderStatusId").IsRequired();
|
||||||
orderConfiguration.Property<int>("PaymentMethodId").IsRequired();
|
orderConfiguration.Property<int?>("PaymentMethodId").IsRequired(false);
|
||||||
|
|
||||||
var navigation = orderConfiguration.Metadata.FindNavigation(nameof(Order.OrderItems));
|
var navigation = orderConfiguration.Metadata.FindNavigation(nameof(Order.OrderItems));
|
||||||
// DDD Patterns comment:
|
// DDD Patterns comment:
|
||||||
@ -142,10 +157,12 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
|
|||||||
orderConfiguration.HasOne(o => o.PaymentMethod)
|
orderConfiguration.HasOne(o => o.PaymentMethod)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("PaymentMethodId")
|
.HasForeignKey("PaymentMethodId")
|
||||||
|
.IsRequired(false)
|
||||||
.OnDelete(DeleteBehavior.Restrict);
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
orderConfiguration.HasOne(o => o.Buyer)
|
orderConfiguration.HasOne(o => o.Buyer)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
|
.IsRequired(false)
|
||||||
.HasForeignKey("BuyerId");
|
.HasForeignKey("BuyerId");
|
||||||
|
|
||||||
orderConfiguration.HasOne(o => o.OrderStatus)
|
orderConfiguration.HasOne(o => o.OrderStatus)
|
||||||
@ -159,6 +176,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
|
|||||||
|
|
||||||
orderItemConfiguration.HasKey(o => o.Id);
|
orderItemConfiguration.HasKey(o => o.Id);
|
||||||
|
|
||||||
|
orderItemConfiguration.Ignore(b => b.Events);
|
||||||
|
|
||||||
orderItemConfiguration.Property(o => o.Id)
|
orderItemConfiguration.Property(o => o.Id)
|
||||||
.ForSqlServerUseSequenceHiLo("orderitemseq");
|
.ForSqlServerUseSequenceHiLo("orderitemseq");
|
||||||
|
|
||||||
@ -215,5 +234,12 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
|
|||||||
.HasMaxLength(200)
|
.HasMaxLength(200)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<int> SaveEntitiesAsync(CancellationToken cancellationToken = default(CancellationToken))
|
||||||
|
{
|
||||||
|
var result = await base.SaveChangesAsync();
|
||||||
|
await _mediator.RaiseDomainEventsAsync(this);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
|
||||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork;
|
using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Repositories
|
namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Repositories
|
||||||
{
|
{
|
||||||
@ -24,8 +26,18 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Repositor
|
|||||||
|
|
||||||
public Order Add(Order order)
|
public Order Add(Order order)
|
||||||
{
|
{
|
||||||
return _context.Orders.Add(order)
|
return _context.Orders.Add(order).Entity;
|
||||||
.Entity;
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Order> GetAsync(int orderId)
|
||||||
|
{
|
||||||
|
return await _context.Orders.FindAsync(orderId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(Order order)
|
||||||
|
{
|
||||||
|
_context.Entry(order).State = EntityState.Modified;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,9 @@ namespace FunctionalTests.Services.Ordering
|
|||||||
country: "USA",
|
country: "USA",
|
||||||
state: "WA",
|
state: "WA",
|
||||||
street: "One way",
|
street: "One way",
|
||||||
zipcode: "zipcode"
|
zipcode: "zipcode",
|
||||||
|
paymentId: 1,
|
||||||
|
buyerId: 3
|
||||||
);
|
);
|
||||||
|
|
||||||
order.AddOrderItem(new OrderItemDTO()
|
order.AddOrderItem(new OrderItemDTO()
|
||||||
@ -68,6 +70,6 @@ namespace FunctionalTests.Services.Ordering
|
|||||||
});
|
});
|
||||||
|
|
||||||
return JsonConvert.SerializeObject(order);
|
return JsonConvert.SerializeObject(order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,9 @@ namespace UnitTest.Ordering.Application
|
|||||||
cardExpiration: args != null && args.ContainsKey("cardExpiration") ? (DateTime)args["cardExpiration"] : DateTime.MinValue,
|
cardExpiration: args != null && args.ContainsKey("cardExpiration") ? (DateTime)args["cardExpiration"] : DateTime.MinValue,
|
||||||
cardSecurityNumber: args != null && args.ContainsKey("cardSecurityNumber") ? (string)args["cardSecurityNumber"] : "123",
|
cardSecurityNumber: args != null && args.ContainsKey("cardSecurityNumber") ? (string)args["cardSecurityNumber"] : "123",
|
||||||
cardHolderName: args != null && args.ContainsKey("cardHolderName") ? (string)args["cardHolderName"] : "XXX",
|
cardHolderName: args != null && args.ContainsKey("cardHolderName") ? (string)args["cardHolderName"] : "XXX",
|
||||||
cardTypeId: args != null && args.ContainsKey("cardTypeId") ? (int)args["cardTypeId"] : 0);
|
cardTypeId: args != null && args.ContainsKey("cardTypeId") ? (int)args["cardTypeId"] : 0,
|
||||||
|
paymentId: args != null && args.ContainsKey("paymentId") ? (int)args["paymentId"] : 0,
|
||||||
|
buyerId: args != null && args.ContainsKey("buyerId") ? (int)args["buyerId"] : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,21 +10,22 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace UnitTest.Ordering.Application
|
namespace UnitTest.Ordering.Application
|
||||||
{
|
{
|
||||||
|
using MediatR;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
public class NewOrderRequestHandlerTest
|
public class NewOrderRequestHandlerTest
|
||||||
{
|
{
|
||||||
private readonly Mock<IBuyerRepository<Buyer>> _buyerRepositoryMock;
|
|
||||||
private readonly Mock<IOrderRepository<Order>> _orderRepositoryMock;
|
private readonly Mock<IOrderRepository<Order>> _orderRepositoryMock;
|
||||||
private readonly Mock<IIdentityService> _identityServiceMock;
|
private readonly Mock<IIdentityService> _identityServiceMock;
|
||||||
|
private readonly Mock<IMediator> _mediator;
|
||||||
|
|
||||||
public NewOrderRequestHandlerTest()
|
public NewOrderRequestHandlerTest()
|
||||||
{
|
{
|
||||||
|
|
||||||
_buyerRepositoryMock = new Mock<IBuyerRepository<Buyer>>();
|
|
||||||
_orderRepositoryMock = new Mock<IOrderRepository<Order>>();
|
_orderRepositoryMock = new Mock<IOrderRepository<Order>>();
|
||||||
_identityServiceMock = new Mock<IIdentityService>();
|
_identityServiceMock = new Mock<IIdentityService>();
|
||||||
|
_mediator = new Mock<IMediator>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@ -37,21 +38,15 @@ namespace UnitTest.Ordering.Application
|
|||||||
{ ["cardExpiration"] = DateTime.Now.AddYears(1) });
|
{ ["cardExpiration"] = DateTime.Now.AddYears(1) });
|
||||||
|
|
||||||
// Arrange
|
// Arrange
|
||||||
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.FindAsync(buyerId))
|
_orderRepositoryMock.Setup(orderRepo => orderRepo.GetAsync(It.IsAny<int>()))
|
||||||
.Returns(Task.FromResult<Buyer>(FakeBuyer()));
|
.Returns(Task.FromResult<Order>(FakeOrder()));
|
||||||
|
|
||||||
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
|
_orderRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
|
||||||
.Returns(Task.FromResult(1));
|
|
||||||
|
|
||||||
_orderRepositoryMock.Setup(or => or.Add(FakeOrder()))
|
|
||||||
.Returns(FakeOrder());
|
|
||||||
|
|
||||||
_orderRepositoryMock.Setup(or => or.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
|
|
||||||
.Returns(Task.FromResult(1));
|
.Returns(Task.FromResult(1));
|
||||||
|
|
||||||
_identityServiceMock.Setup(svc => svc.GetUserIdentity()).Returns(buyerId);
|
_identityServiceMock.Setup(svc => svc.GetUserIdentity()).Returns(buyerId);
|
||||||
//Act
|
//Act
|
||||||
var handler = new CreateOrderCommandHandler(_buyerRepositoryMock.Object, _orderRepositoryMock.Object, _identityServiceMock.Object);
|
var handler = new CreateOrderCommandHandler(_mediator.Object, _orderRepositoryMock.Object, _identityServiceMock.Object);
|
||||||
var result = await handler.Handle(fakeOrderCmd);
|
var result = await handler.Handle(fakeOrderCmd);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
@ -66,19 +61,16 @@ namespace UnitTest.Ordering.Application
|
|||||||
var fakeOrderCmd = FakeOrderRequestWithBuyer(new Dictionary<string, object>
|
var fakeOrderCmd = FakeOrderRequestWithBuyer(new Dictionary<string, object>
|
||||||
{ ["cardExpiration"] = DateTime.Now.AddYears(1) });
|
{ ["cardExpiration"] = DateTime.Now.AddYears(1) });
|
||||||
|
|
||||||
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.FindAsync(buyerId))
|
_orderRepositoryMock.Setup(orderRepo => orderRepo.GetAsync(It.IsAny<int>()))
|
||||||
.Returns(Task.FromResult<Buyer>(FakeBuyer()));
|
.Returns(Task.FromResult<Order>(FakeOrder()));
|
||||||
|
|
||||||
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
|
_orderRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
|
||||||
.Returns(Task.FromResult(1));
|
.Returns(Task.FromResult(1));
|
||||||
|
|
||||||
_orderRepositoryMock.Setup(or => or.Add(FakeOrder())).Returns(FakeOrder());
|
|
||||||
_orderRepositoryMock.Setup(or => or.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
|
|
||||||
.Returns(Task.FromResult(0));
|
|
||||||
_identityServiceMock.Setup(svc => svc.GetUserIdentity()).Returns(buyerId);
|
_identityServiceMock.Setup(svc => svc.GetUserIdentity()).Returns(buyerId);
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
var handler = new CreateOrderCommandHandler(_buyerRepositoryMock.Object, _orderRepositoryMock.Object, _identityServiceMock.Object);
|
var handler = new CreateOrderCommandHandler(_mediator.Object, _orderRepositoryMock.Object, _identityServiceMock.Object);
|
||||||
var result = await handler.Handle(fakeOrderCmd);
|
var result = await handler.Handle(fakeOrderCmd);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
@ -95,21 +87,15 @@ namespace UnitTest.Ordering.Application
|
|||||||
{ ["cardExpiration"] = DateTime.Now.AddYears(-1) });
|
{ ["cardExpiration"] = DateTime.Now.AddYears(-1) });
|
||||||
|
|
||||||
// Arrange
|
// Arrange
|
||||||
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.FindAsync(buyerId))
|
_orderRepositoryMock.Setup(orderRepo => orderRepo.GetAsync(It.IsAny<int>()))
|
||||||
.Returns(Task.FromResult<Buyer>(FakeBuyer()));
|
.Returns(Task.FromResult<Order>(FakeOrder()));
|
||||||
|
|
||||||
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
|
_orderRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
|
||||||
.Returns(Task.FromResult(1));
|
|
||||||
|
|
||||||
_orderRepositoryMock.Setup(or => or.Add(FakeOrder()))
|
|
||||||
.Returns(FakeOrder());
|
|
||||||
|
|
||||||
_orderRepositoryMock.Setup(or => or.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
|
|
||||||
.Returns(Task.FromResult(1));
|
.Returns(Task.FromResult(1));
|
||||||
|
|
||||||
_identityServiceMock.Setup(svc => svc.GetUserIdentity()).Returns(buyerId);
|
_identityServiceMock.Setup(svc => svc.GetUserIdentity()).Returns(buyerId);
|
||||||
//Act
|
//Act
|
||||||
var handler = new CreateOrderCommandHandler(_buyerRepositoryMock.Object, _orderRepositoryMock.Object, _identityServiceMock.Object);
|
var handler = new CreateOrderCommandHandler(_mediator.Object, _orderRepositoryMock.Object, _identityServiceMock.Object);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
await Assert.ThrowsAsync<ArgumentException>(async () => await handler.Handle(fakeOrderCmd));
|
await Assert.ThrowsAsync<ArgumentException>(async () => await handler.Handle(fakeOrderCmd));
|
||||||
@ -128,21 +114,15 @@ namespace UnitTest.Ordering.Application
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Arrange
|
// Arrange
|
||||||
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.FindAsync(buyerId))
|
_orderRepositoryMock.Setup(orderRepo => orderRepo.GetAsync(It.IsAny<int>()))
|
||||||
.Returns(Task.FromResult<Buyer>(FakeBuyer()));
|
.Returns(Task.FromResult<Order>(FakeOrder()));
|
||||||
|
|
||||||
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
|
_orderRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
|
||||||
.Returns(Task.FromResult(1));
|
|
||||||
|
|
||||||
_orderRepositoryMock.Setup(or => or.Add(FakeOrder()))
|
|
||||||
.Returns(FakeOrder());
|
|
||||||
|
|
||||||
_orderRepositoryMock.Setup(or => or.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
|
|
||||||
.Returns(Task.FromResult(1));
|
.Returns(Task.FromResult(1));
|
||||||
|
|
||||||
_identityServiceMock.Setup(svc => svc.GetUserIdentity()).Returns(buyerId);
|
_identityServiceMock.Setup(svc => svc.GetUserIdentity()).Returns(buyerId);
|
||||||
//Act
|
//Act
|
||||||
var handler = new CreateOrderCommandHandler(_buyerRepositoryMock.Object, _orderRepositoryMock.Object, _identityServiceMock.Object);
|
var handler = new CreateOrderCommandHandler(_mediator.Object, _orderRepositoryMock.Object, _identityServiceMock.Object);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
await Assert.ThrowsAsync<ArgumentException>(async () => await handler.Handle(fakeOrderCmd));
|
await Assert.ThrowsAsync<ArgumentException>(async () => await handler.Handle(fakeOrderCmd));
|
||||||
@ -161,21 +141,15 @@ namespace UnitTest.Ordering.Application
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Arrange
|
// Arrange
|
||||||
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.FindAsync(buyerId))
|
_orderRepositoryMock.Setup(orderRepo => orderRepo.GetAsync(It.IsAny<int>()))
|
||||||
.Returns(Task.FromResult<Buyer>(FakeBuyer()));
|
.Returns(Task.FromResult<Order>(FakeOrder()));
|
||||||
|
|
||||||
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
|
_orderRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
|
||||||
.Returns(Task.FromResult(1));
|
|
||||||
|
|
||||||
_orderRepositoryMock.Setup(or => or.Add(FakeOrder()))
|
|
||||||
.Returns(FakeOrder());
|
|
||||||
|
|
||||||
_orderRepositoryMock.Setup(or => or.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
|
|
||||||
.Returns(Task.FromResult(1));
|
.Returns(Task.FromResult(1));
|
||||||
|
|
||||||
_identityServiceMock.Setup(svc => svc.GetUserIdentity()).Returns(buyerId);
|
_identityServiceMock.Setup(svc => svc.GetUserIdentity()).Returns(buyerId);
|
||||||
//Act
|
//Act
|
||||||
var handler = new CreateOrderCommandHandler(_buyerRepositoryMock.Object, _orderRepositoryMock.Object, _identityServiceMock.Object);
|
var handler = new CreateOrderCommandHandler(_mediator.Object, _orderRepositoryMock.Object, _identityServiceMock.Object);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
await Assert.ThrowsAsync<ArgumentException>(async () => await handler.Handle(fakeOrderCmd));
|
await Assert.ThrowsAsync<ArgumentException>(async () => await handler.Handle(fakeOrderCmd));
|
||||||
@ -185,7 +159,7 @@ namespace UnitTest.Ordering.Application
|
|||||||
public async Task Handle_throws_exception_when_no_cardNumber()
|
public async Task Handle_throws_exception_when_no_cardNumber()
|
||||||
{
|
{
|
||||||
|
|
||||||
var buyerId = "1234";
|
var orderId = "1234";
|
||||||
|
|
||||||
var fakeOrderCmd = FakeOrderRequestWithBuyer(new Dictionary<string, object>
|
var fakeOrderCmd = FakeOrderRequestWithBuyer(new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
@ -194,21 +168,15 @@ namespace UnitTest.Ordering.Application
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Arrange
|
// Arrange
|
||||||
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.FindAsync(buyerId))
|
_orderRepositoryMock.Setup(orderRepo => orderRepo.GetAsync(It.IsAny<int>()))
|
||||||
.Returns(Task.FromResult<Buyer>(FakeBuyer()));
|
.Returns(Task.FromResult<Order>(FakeOrder()));
|
||||||
|
|
||||||
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
|
_orderRepositoryMock.Setup(orderRepo => orderRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
|
||||||
.Returns(Task.FromResult(1));
|
.Returns(Task.FromResult(1));
|
||||||
|
|
||||||
_orderRepositoryMock.Setup(or => or.Add(FakeOrder()))
|
_identityServiceMock.Setup(svc => svc.GetUserIdentity()).Returns(orderId);
|
||||||
.Returns(FakeOrder());
|
|
||||||
|
|
||||||
_orderRepositoryMock.Setup(or => or.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
|
|
||||||
.Returns(Task.FromResult(1));
|
|
||||||
|
|
||||||
_identityServiceMock.Setup(svc => svc.GetUserIdentity()).Returns(buyerId);
|
|
||||||
//Act
|
//Act
|
||||||
var handler = new CreateOrderCommandHandler(_buyerRepositoryMock.Object, _orderRepositoryMock.Object, _identityServiceMock.Object);
|
var handler = new CreateOrderCommandHandler(_mediator.Object, _orderRepositoryMock.Object, _identityServiceMock.Object);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
await Assert.ThrowsAsync<ArgumentException>(async () => await handler.Handle(fakeOrderCmd));
|
await Assert.ThrowsAsync<ArgumentException>(async () => await handler.Handle(fakeOrderCmd));
|
||||||
@ -228,7 +196,7 @@ namespace UnitTest.Ordering.Application
|
|||||||
|
|
||||||
private Order FakeOrder()
|
private Order FakeOrder()
|
||||||
{
|
{
|
||||||
return new Order(1, 1, new Address("street", "city", "state", "country", "zipcode"));
|
return new Order(new Address("street", "city", "state", "country", "zipcode"), 1, "12", "111", "fakeName", DateTime.Now.AddYears(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
private CreateOrderCommand FakeOrderRequestWithBuyer(Dictionary<string, object> args = null)
|
private CreateOrderCommand FakeOrderRequestWithBuyer(Dictionary<string, object> args = null)
|
||||||
@ -243,7 +211,9 @@ namespace UnitTest.Ordering.Application
|
|||||||
cardExpiration: args != null && args.ContainsKey("cardExpiration") ? (DateTime)args["cardExpiration"] : DateTime.MinValue,
|
cardExpiration: args != null && args.ContainsKey("cardExpiration") ? (DateTime)args["cardExpiration"] : DateTime.MinValue,
|
||||||
cardSecurityNumber: args != null && args.ContainsKey("cardSecurityNumber") ? (string)args["cardSecurityNumber"] : "123",
|
cardSecurityNumber: args != null && args.ContainsKey("cardSecurityNumber") ? (string)args["cardSecurityNumber"] : "123",
|
||||||
cardHolderName: args != null && args.ContainsKey("cardHolderName") ? (string)args["cardHolderName"] : "XXX",
|
cardHolderName: args != null && args.ContainsKey("cardHolderName") ? (string)args["cardHolderName"] : "XXX",
|
||||||
cardTypeId: args != null && args.ContainsKey("cardTypeId") ? (int)args["cardTypeId"] : 0);
|
cardTypeId: args != null && args.ContainsKey("cardTypeId") ? (int)args["cardTypeId"] : 0,
|
||||||
|
paymentId: args != null && args.ContainsKey("paymentId") ? (int)args["paymentId"] : 0,
|
||||||
|
buyerId: args != null && args.ContainsKey("buyerId") ? (int)args["buyerId"] : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,11 +40,12 @@ public class BuyerAggregateTest
|
|||||||
var securityNumber = "1234";
|
var securityNumber = "1234";
|
||||||
var cardHolderName = "FakeHolderNAme";
|
var cardHolderName = "FakeHolderNAme";
|
||||||
var expiration = DateTime.Now.AddYears(1);
|
var expiration = DateTime.Now.AddYears(1);
|
||||||
|
var orderId = 1;
|
||||||
var identity = new Guid().ToString();
|
var identity = new Guid().ToString();
|
||||||
var fakeBuyerItem = new Buyer(identity);
|
var fakeBuyerItem = new Buyer(identity);
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
var result = fakeBuyerItem.AddPaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration);
|
var result = fakeBuyerItem.AddPaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration, orderId);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
Assert.NotNull(result);
|
Assert.NotNull(result);
|
||||||
@ -102,4 +103,25 @@ public class BuyerAggregateTest
|
|||||||
//Assert
|
//Assert
|
||||||
Assert.True(result);
|
Assert.True(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Add_new_PaymentMethod_raises_new_event()
|
||||||
|
{
|
||||||
|
//Arrange
|
||||||
|
var alias = "fakeAlias";
|
||||||
|
var orderId = 1;
|
||||||
|
var cardTypeId = 5;
|
||||||
|
var cardNumber = "12";
|
||||||
|
var cardSecurityNumber = "123";
|
||||||
|
var cardHolderName = "FakeName";
|
||||||
|
var cardExpiration = DateTime.Now.AddYears(1);
|
||||||
|
var expectedResult = 1;
|
||||||
|
|
||||||
|
//Act
|
||||||
|
var fakeBuyer = new Buyer(Guid.NewGuid().ToString());
|
||||||
|
fakeBuyer.AddPaymentMethod(cardTypeId, alias, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration, orderId);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
Assert.Equal(fakeBuyer.Events.Count, expectedResult);
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
|
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
|
||||||
|
using Ordering.Domain.Events;
|
||||||
using System;
|
using System;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
@ -90,4 +91,75 @@ public class OrderAggregateTest
|
|||||||
//Assert
|
//Assert
|
||||||
Assert.Throws<ArgumentException>(() => fakeOrderItem.AddUnits(-1));
|
Assert.Throws<ArgumentException>(() => fakeOrderItem.AddUnits(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Add_new_Order_raises_new_event()
|
||||||
|
{
|
||||||
|
//Arrange
|
||||||
|
var street = "fakeStreet";
|
||||||
|
var city = "FakeCity";
|
||||||
|
var state = "fakeState";
|
||||||
|
var country = "fakeCountry";
|
||||||
|
var zipcode = "FakeZipCode";
|
||||||
|
var cardTypeId = 5;
|
||||||
|
var cardNumber = "12";
|
||||||
|
var cardSecurityNumber = "123";
|
||||||
|
var cardHolderName = "FakeName";
|
||||||
|
var cardExpiration = DateTime.Now.AddYears(1);
|
||||||
|
var expectedResult = 1;
|
||||||
|
|
||||||
|
//Act
|
||||||
|
var fakeOrder = new Order(new Address(street, city, state, country, zipcode), cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
Assert.Equal(fakeOrder.Events.Count, expectedResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Add_event_Order_explicitly_raises_new_event()
|
||||||
|
{
|
||||||
|
//Arrange
|
||||||
|
var street = "fakeStreet";
|
||||||
|
var city = "FakeCity";
|
||||||
|
var state = "fakeState";
|
||||||
|
var country = "fakeCountry";
|
||||||
|
var zipcode = "FakeZipCode";
|
||||||
|
var cardTypeId = 5;
|
||||||
|
var cardNumber = "12";
|
||||||
|
var cardSecurityNumber = "123";
|
||||||
|
var cardHolderName = "FakeName";
|
||||||
|
var cardExpiration = DateTime.Now.AddYears(1);
|
||||||
|
var expectedResult = 2;
|
||||||
|
|
||||||
|
//Act
|
||||||
|
var fakeOrder = new Order(new Address(street, city, state, country, zipcode), cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration);
|
||||||
|
fakeOrder.AddEvent(new OrderCreated(fakeOrder,cardTypeId,cardNumber,cardSecurityNumber,cardHolderName,cardExpiration));
|
||||||
|
//Assert
|
||||||
|
Assert.Equal(fakeOrder.Events.Count, expectedResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Remove_event_Order_explicitly()
|
||||||
|
{
|
||||||
|
//Arrange
|
||||||
|
var street = "fakeStreet";
|
||||||
|
var city = "FakeCity";
|
||||||
|
var state = "fakeState";
|
||||||
|
var country = "fakeCountry";
|
||||||
|
var zipcode = "FakeZipCode";
|
||||||
|
var cardTypeId = 5;
|
||||||
|
var cardNumber = "12";
|
||||||
|
var cardSecurityNumber = "123";
|
||||||
|
var cardHolderName = "FakeName";
|
||||||
|
var cardExpiration = DateTime.Now.AddYears(1);
|
||||||
|
var fakeOrder = new Order(new Address(street, city, state, country, zipcode), cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration);
|
||||||
|
var @fakeEvent = new OrderCreated(fakeOrder, cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration);
|
||||||
|
var expectedResult = 1;
|
||||||
|
|
||||||
|
//Act
|
||||||
|
fakeOrder.AddEvent(@fakeEvent);
|
||||||
|
fakeOrder.RemoveEvent(@fakeEvent);
|
||||||
|
//Assert
|
||||||
|
Assert.Equal(fakeOrder.Events.Count, expectedResult);
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user