Browse Source

Refactored: From Buyer.FullName to Buyer.IdentityGuid.

Also similar changes at the CreateOrderCommand
Plus an update to the README.md for GitHub
pull/49/merge
CESARDL 8 years ago
parent
commit
8325ddbd30
11 changed files with 277 additions and 17 deletions
  1. +7
    -3
      README.md
  2. +1
    -1
      src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommand.cs
  3. +2
    -2
      src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommandHandler.cs
  4. +1
    -1
      src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs
  5. +217
    -0
      src/Services/Ordering/Ordering.API/Infrastructure/Migrations/20170208054757_RefactorBuyerWithIdentityGuid.Designer.cs
  6. +39
    -0
      src/Services/Ordering/Ordering.API/Infrastructure/Migrations/20170208054757_RefactorBuyerWithIdentityGuid.cs
  7. +2
    -2
      src/Services/Ordering/Ordering.API/Infrastructure/Migrations/OrderingContextModelSnapshot.cs
  8. +2
    -2
      src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/Buyer.cs
  9. +2
    -2
      src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs
  10. +1
    -1
      src/Services/Ordering/Ordering.Infrastructure/Repositories/BuyerRepository.cs
  11. +3
    -3
      test/Services/UnitTest/Ordering/Application/NewOrderCommandHandlerTest.cs

+ 7
- 3
README.md View File

@ -12,7 +12,11 @@ This reference application is cross-platform either in the server and client sid
<img src="img/eshop_logo.png">
<img src="img/eShopOnContainers_Architecture_Diagram.png">
<p>
<b>Important Note on Database Servers/Containers</b>: In this solution, the SQL databases are automatically deployed with sample data into a single SQL Server for Linux container (a single shared Docker container for SQL databases) so the whole solution can be up and running without any dependency in the cloud or server. A similar case is defined in regards Redis cache running as a container. However, in a real production environment it is recommended to have persistance (SQL Server and Redis) in HA services like Azure SQL Database, Redis as a service or any other clustering system. If you want to configure this solution like that, you'll just need to change the connection strings once you have set up the servers in the cloud or on-premises.
> ### Important Note on Database Servers/Containers
> In this solution's current configuration for a development environment, the SQL databases are automatically deployed with sample data into a single SQL Server for Linux container (a single shared Docker container for SQL databases) so the whole solution can be up and running without any dependency in the cloud or server. Each database could also be deployed as a single Docker container, but then you'd need more then 8GB or memory RAM in your development machine in order to be able to run 3 SQL Server Docker containers in your Docker Linux host in "Docker for Windows" or "Docker for Mac" development environments.
> <p> A similar case is defined in regards Redis cache running as a container for the development environment.
> <p> However, in a real production environment it is recommended to have persistance (SQL Server and Redis) in HA services like Azure SQL Database, Redis as a service or any other clustering system. If you want to change to a production configuration, you'll just need to change the connection strings once you have set up the servers in HA cloud or on-premises.
## Related documentation and guidance
While developing this reference application, we've been creating a reference Guide/eBook named <b>"Architecting and Developing Containerized and Microservice based .NET Applications"</b> which explains in detail how to develop this kind of architectural style (microservices, Docker containers, Domain-Driven Design for certain microservices) plus other simpler architectural styles, like monolithic that can also live as Docker containers.
@ -67,13 +71,13 @@ The app was also partially tested on "Docker for Mac" using a development MacOS
WINDOWS DEV MACHINE
- Visual Studio 2015 with latest Update
- .NET Core 1.0 (Including ASP.NET Core and VS Tooling)
- .NET Core 1.1 setup (Including ASP.NET Core and VS Tooling)
- Bower and Gulp as global installs (See steps below)
- <a href='https://docs.docker.com/docker-for-windows/'>Docker for Windows</a>
MAC DEV MACHINE
- Visual Studio Code
- .NET Core 1.0 for Mac
- .NET Core 1.1 for Mac - setup
- Bower and Gulp as global installs (See steps below)
- <a href='https://docs.docker.com/docker-for-mac/'>Docker for Mac</a>


+ 1
- 1
src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommand.cs View File

@ -31,7 +31,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands
public int CardTypeId { get; set; }
public string BuyerFullName { get; set; }
public string BuyerIdentityGuid { get; set; }
public IEnumerable<OrderItemDTO> OrderItems => _orderItems;


+ 2
- 2
src/Services/Ordering/Ordering.API/Application/Commands/CreateOrderCommandHandler.cs View File

@ -36,11 +36,11 @@
// methods and constructor so validations, invariants and business logic
// make sure that consistency is preserved across the whole aggregate
var buyer = await _buyerRepository.FindAsync(message.BuyerFullName);
var buyer = await _buyerRepository.FindAsync(message.BuyerIdentityGuid);
if (buyer == null)
{
buyer = new Buyer(message.BuyerFullName);
buyer = new Buyer(message.BuyerIdentityGuid);
}
var payment = buyer.AddPaymentMethod(message.CardTypeId,


+ 1
- 1
src/Services/Ordering/Ordering.API/Controllers/OrdersController.cs View File

@ -49,7 +49,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers
createOrderCommand.CardTypeId = 1;
}
createOrderCommand.BuyerFullName = _identityService.GetUserIdentity();
createOrderCommand.BuyerIdentityGuid = _identityService.GetUserIdentity();
var added = await _mediator.SendAsync(createOrderCommand);
if (added)


+ 217
- 0
src/Services/Ordering/Ordering.API/Infrastructure/Migrations/20170208054757_RefactorBuyerWithIdentityGuid.Designer.cs View File

@ -0,0 +1,217 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure;
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Migrations
{
[DbContext(typeof(OrderingContext))]
[Migration("20170208054757_RefactorBuyerWithIdentityGuid")]
partial class RefactorBuyerWithIdentityGuid
{
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.Order", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:HiLoSequenceName", "orderseq")
.HasAnnotation("SqlServer:HiLoSequenceSchema", "ordering")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
b.Property<int>("BuyerId");
b.Property<string>("City")
.IsRequired();
b.Property<string>("Country")
.IsRequired();
b.Property<DateTime>("OrderDate");
b.Property<int>("OrderStatusId");
b.Property<int>("PaymentMethodId");
b.Property<string>("State")
.IsRequired();
b.Property<string>("Street")
.IsRequired();
b.Property<string>("ZipCode")
.IsRequired();
b.HasKey("Id");
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.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.BuyerAggregate.Buyer", "Buyer")
.WithMany()
.HasForeignKey("BuyerId")
.OnDelete(DeleteBehavior.Cascade);
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);
});
}
}
}

+ 39
- 0
src/Services/Ordering/Ordering.API/Infrastructure/Migrations/20170208054757_RefactorBuyerWithIdentityGuid.cs View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Migrations
{
public partial class RefactorBuyerWithIdentityGuid : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "FullName",
schema: "ordering",
table: "buyers",
newName: "IdentityGuid");
migrationBuilder.RenameIndex(
name: "IX_buyers_FullName",
schema: "ordering",
table: "buyers",
newName: "IX_buyers_IdentityGuid");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "IdentityGuid",
schema: "ordering",
table: "buyers",
newName: "FullName");
migrationBuilder.RenameIndex(
name: "IX_buyers_IdentityGuid",
schema: "ordering",
table: "buyers",
newName: "IX_buyers_FullName");
}
}
}

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

@ -28,13 +28,13 @@ namespace Ordering.API.Migrations
.HasAnnotation("SqlServer:HiLoSequenceSchema", "ordering")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo);
b.Property<string>("FullName")
b.Property<string>("IdentityGuid")
.IsRequired()
.HasMaxLength(200);
b.HasKey("Id");
b.HasIndex("FullName")
b.HasIndex("IdentityGuid")
.IsUnique();
b.ToTable("buyers","ordering");


+ 2
- 2
src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/Buyer.cs View File

@ -8,7 +8,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B
public class Buyer
: Entity, IAggregateRoot
{
public string FullName { get; private set; }
public string IdentityGuid { get; private set; }
private List<PaymentMethod> _paymentMethods;
@ -23,7 +23,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B
throw new ArgumentNullException(nameof(identity));
}
FullName = identity;
IdentityGuid = identity;
_paymentMethods = new List<PaymentMethod>();
}


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

@ -47,11 +47,11 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
buyerConfiguration.Property(b => b.Id)
.ForSqlServerUseSequenceHiLo("buyerseq", DEFAULT_SCHEMA);
buyerConfiguration.Property(b=>b.FullName)
buyerConfiguration.Property(b=>b.IdentityGuid)
.HasMaxLength(200)
.IsRequired();
buyerConfiguration.HasIndex("FullName")
buyerConfiguration.HasIndex("IdentityGuid")
.IsUnique(true);
buyerConfiguration.HasMany(b => b.PaymentMethods)


+ 1
- 1
src/Services/Ordering/Ordering.Infrastructure/Repositories/BuyerRepository.cs View File

@ -49,7 +49,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Repositor
{
var buyer = await _context.Buyers
.Include(b => b.PaymentMethods)
.Where(b => b.FullName == identity)
.Where(b => b.IdentityGuid == identity)
.SingleOrDefaultAsync();
return buyer;


+ 3
- 3
test/Services/UnitTest/Ordering/Application/NewOrderCommandHandlerTest.cs View File

@ -25,7 +25,7 @@ namespace UnitTest.Ordering.Application
public async Task Handle_returns_true_when_order_is_persisted_succesfully()
{
// Arrange
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.FindAsync(FakeOrderRequestWithBuyer().BuyerFullName))
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.FindAsync(FakeOrderRequestWithBuyer().BuyerIdentityGuid))
.Returns(Task.FromResult<Buyer>(FakeBuyer()));
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
@ -48,7 +48,7 @@ namespace UnitTest.Ordering.Application
[Fact]
public async Task Handle_return_false_if_order_is_not_persisted()
{
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.FindAsync(FakeOrderRequestWithBuyer().BuyerFullName))
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.FindAsync(FakeOrderRequestWithBuyer().BuyerIdentityGuid))
.Returns(Task.FromResult<Buyer>(FakeBuyer()));
_buyerRepositoryMock.Setup(buyerRepo => buyerRepo.UnitOfWork.SaveChangesAsync(default(CancellationToken)))
@ -80,7 +80,7 @@ namespace UnitTest.Ordering.Application
{
return new CreateOrderCommand
{
BuyerFullName = "1234",
BuyerIdentityGuid = "1234",
CardNumber = "1234",
CardExpiration = DateTime.Now.AddYears(1),
CardSecurityNumber = "123",


Loading…
Cancel
Save