@ -1,227 +0,0 @@ | |||||
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.Infrastructure.Migrations | |||||
{ | |||||
[DbContext(typeof(OrderingContext))] | |||||
[Migration("20161124133626_InitialModel")] | |||||
partial class InitialModel | |||||
{ | |||||
protected override void BuildTargetModel(ModelBuilder modelBuilder) | |||||
{ | |||||
modelBuilder | |||||
.HasAnnotation("ProductVersion", "1.0.1") | |||||
.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.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.Buyer", b => | |||||
{ | |||||
b.Property<int>("Id") | |||||
.ValueGeneratedOnAdd() | |||||
.HasAnnotation("SqlServer:HiLoSequenceName", "buyerseq") | |||||
.HasAnnotation("SqlServer:HiLoSequenceSchema", "ordering") | |||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); | |||||
b.Property<string>("FullName") | |||||
.IsRequired() | |||||
.HasAnnotation("MaxLength", 200); | |||||
b.HasKey("Id"); | |||||
b.HasIndex("FullName") | |||||
.IsUnique(); | |||||
b.ToTable("buyers","ordering"); | |||||
}); | |||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.CardType", b => | |||||
{ | |||||
b.Property<int>("Id") | |||||
.ValueGeneratedOnAdd() | |||||
.HasDefaultValue(1); | |||||
b.Property<string>("Name") | |||||
.IsRequired() | |||||
.HasAnnotation("MaxLength", 200); | |||||
b.HasKey("Id"); | |||||
b.ToTable("cardtypes","ordering"); | |||||
}); | |||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.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<DateTime>("OrderDate"); | |||||
b.Property<int>("PaymentId"); | |||||
b.Property<int?>("ShippingAddressId"); | |||||
b.Property<int>("StatusId"); | |||||
b.HasKey("Id"); | |||||
b.HasIndex("BuyerId"); | |||||
b.HasIndex("PaymentId"); | |||||
b.HasIndex("ShippingAddressId"); | |||||
b.HasIndex("StatusId"); | |||||
b.ToTable("orders","ordering"); | |||||
}); | |||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.OrderItem", b => | |||||
{ | |||||
b.Property<int>("Id") | |||||
.ValueGeneratedOnAdd(); | |||||
b.Property<decimal>("Discount"); | |||||
b.Property<int>("OrderId"); | |||||
b.Property<int>("ProductId"); | |||||
b.Property<string>("ProductName") | |||||
.IsRequired(); | |||||
b.Property<decimal>("UnitPrice"); | |||||
b.Property<int>("Units") | |||||
.ValueGeneratedOnAdd() | |||||
.HasAnnotation("SqlServer:DefaultValue", 1); | |||||
b.HasKey("Id"); | |||||
b.HasIndex("OrderId"); | |||||
b.ToTable("orderItems","ordering"); | |||||
}); | |||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.OrderStatus", b => | |||||
{ | |||||
b.Property<int>("Id") | |||||
.ValueGeneratedOnAdd() | |||||
.HasDefaultValue(1); | |||||
b.Property<string>("Name") | |||||
.IsRequired() | |||||
.HasAnnotation("MaxLength", 200); | |||||
b.HasKey("Id"); | |||||
b.ToTable("orderstatus","ordering"); | |||||
}); | |||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.Payment", b => | |||||
{ | |||||
b.Property<int>("Id") | |||||
.ValueGeneratedOnAdd() | |||||
.HasAnnotation("SqlServer:HiLoSequenceName", "paymentseq") | |||||
.HasAnnotation("SqlServer:HiLoSequenceSchema", "ordering") | |||||
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.SequenceHiLo); | |||||
b.Property<int>("BuyerId"); | |||||
b.Property<string>("CardHolderName") | |||||
.IsRequired() | |||||
.HasAnnotation("MaxLength", 200); | |||||
b.Property<string>("CardNumber") | |||||
.IsRequired() | |||||
.HasAnnotation("MaxLength", 25); | |||||
b.Property<int>("CardTypeId"); | |||||
b.Property<DateTime>("Expiration"); | |||||
b.Property<string>("SecurityNumber"); | |||||
b.HasKey("Id"); | |||||
b.HasIndex("BuyerId"); | |||||
b.HasIndex("CardTypeId"); | |||||
b.ToTable("payments","ordering"); | |||||
}); | |||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.Order", b => | |||||
{ | |||||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.Buyer", "Buyer") | |||||
.WithMany() | |||||
.HasForeignKey("BuyerId") | |||||
.OnDelete(DeleteBehavior.Cascade); | |||||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.Payment", "Payment") | |||||
.WithMany() | |||||
.HasForeignKey("PaymentId"); | |||||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.Address", "ShippingAddress") | |||||
.WithMany() | |||||
.HasForeignKey("ShippingAddressId"); | |||||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.OrderStatus", "Status") | |||||
.WithMany() | |||||
.HasForeignKey("StatusId") | |||||
.OnDelete(DeleteBehavior.Cascade); | |||||
}); | |||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.OrderItem", b => | |||||
{ | |||||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.Order") | |||||
.WithMany("OrderItems") | |||||
.HasForeignKey("OrderId") | |||||
.OnDelete(DeleteBehavior.Cascade); | |||||
}); | |||||
modelBuilder.Entity("Microsoft.eShopOnContainers.Services.Ordering.Domain.Payment", b => | |||||
{ | |||||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.Buyer") | |||||
.WithMany("Payments") | |||||
.HasForeignKey("BuyerId") | |||||
.OnDelete(DeleteBehavior.Cascade); | |||||
b.HasOne("Microsoft.eShopOnContainers.Services.Ordering.Domain.CardType", "CardType") | |||||
.WithMany() | |||||
.HasForeignKey("CardTypeId") | |||||
.OnDelete(DeleteBehavior.Cascade); | |||||
}); | |||||
} | |||||
} | |||||
} |
@ -1,28 +0,0 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using Microsoft.EntityFrameworkCore.Migrations; | |||||
namespace Ordering.API.Infrastructure.Migrations | |||||
{ | |||||
public partial class PaymentMethodWithAlias : Migration | |||||
{ | |||||
protected override void Up(MigrationBuilder migrationBuilder) | |||||
{ | |||||
migrationBuilder.AddColumn<string>( | |||||
name: "Alias", | |||||
schema: "ordering", | |||||
table: "payments", | |||||
maxLength: 200, | |||||
nullable: false, | |||||
defaultValue: ""); | |||||
} | |||||
protected override void Down(MigrationBuilder migrationBuilder) | |||||
{ | |||||
migrationBuilder.DropColumn( | |||||
name: "Alias", | |||||
schema: "ordering", | |||||
table: "payments"); | |||||
} | |||||
} | |||||
} |
@ -1,35 +0,0 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Models | |||||
{ | |||||
//TO DO: Confirm if this class is not needed, if not, remove it | |||||
//(CDLTLL) | |||||
public class NewOrderViewModel | |||||
{ | |||||
public string ShippingCity { get; set; } | |||||
public string ShippingStreet { get; set; } | |||||
public string ShippingState { get; set; } | |||||
public string ShippingCountry { get; set; } | |||||
public string CardType { get; set; } | |||||
public string CardNumber { get; set; } | |||||
public string CardHolderName { get; set; } | |||||
public DateTime CardExpiration { get; set; } | |||||
public string CardSecurityNumber { get; set; } | |||||
public List<OrderItemViewModel> Items { get; set; } | |||||
public NewOrderViewModel() | |||||
{ | |||||
Items = new List<OrderItemViewModel>(); | |||||
} | |||||
} | |||||
} |
@ -1,19 +0,0 @@ | |||||
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Models | |||||
{ | |||||
//TO DO: Confirm if this class is not needed, if not, remove it | |||||
//(CDLTLL) | |||||
public class OrderItemViewModel | |||||
{ | |||||
public int ProductId { get; set; } | |||||
public string ProductName { get; set; } | |||||
public decimal UnitPrice { get; set; } | |||||
public decimal Discount { get; set; } | |||||
public int Units { get; set; } | |||||
public string PictureUrl { get; set; } | |||||
} | |||||
} |
@ -1,5 +0,0 @@ | |||||
| |||||
REFACTORING TO DO: | |||||
//TO DO: Confirm if these ViewModel classes are still needed, if not, remove it | |||||
//and remove the related Unit Tests | |||||
//(CDLTLL) |
@ -1,27 +1,50 @@ | |||||
namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate | |||||
{ | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate | |||||
{ | |||||
public class Buyer | public class Buyer | ||||
:Entity,IAggregateRoot | |||||
: Entity, IAggregateRoot | |||||
{ | { | ||||
public string FullName { get; private set; } | public string FullName { get; private set; } | ||||
public HashSet<Payment> Payments { get; private set; } | |||||
private HashSet<PaymentMethod> _paymentMethods; | |||||
public IEnumerable<PaymentMethod> PaymentMethods => _paymentMethods?.ToList().AsEnumerable(); | |||||
protected Buyer() { } | protected Buyer() { } | ||||
public Buyer(string IdentityGuid) | |||||
public Buyer(string identity) | |||||
{ | |||||
if (String.IsNullOrWhiteSpace(identity)) | |||||
{ | |||||
throw new ArgumentNullException(nameof(identity)); | |||||
} | |||||
FullName = identity; | |||||
_paymentMethods = new HashSet<PaymentMethod>(); | |||||
} | |||||
public PaymentMethod AddPaymentMethod(int cardTypeId, string alias, string cardNumber, string securityNumber, string cardHolderName, DateTime expiration) | |||||
{ | { | ||||
if (String.IsNullOrWhiteSpace(IdentityGuid)) | |||||
var existingPayment = _paymentMethods.Where(p => p.IsEqualTo(cardTypeId, cardNumber, expiration)) | |||||
.SingleOrDefault(); | |||||
if (existingPayment != null) | |||||
{ | { | ||||
throw new ArgumentNullException(nameof(IdentityGuid)); | |||||
return existingPayment; | |||||
} | } | ||||
else | |||||
{ | |||||
var payment = new PaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration); | |||||
_paymentMethods.Add(payment); | |||||
this.FullName = IdentityGuid; | |||||
this.Payments = new HashSet<Payment>(); | |||||
return payment; | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } |
@ -1,57 +0,0 @@ | |||||
namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate | |||||
{ | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; | |||||
using System; | |||||
public class Payment | |||||
: Entity | |||||
{ | |||||
public string Alias { get; private set; } | |||||
public int BuyerId { get; private set; } | |||||
public string CardNumber { get; private set; } | |||||
public string SecurityNumber { get; private set; } | |||||
public string CardHolderName { get; private set; } | |||||
public int CardTypeId { get; private set; } | |||||
public CardType CardType { get; private set; } | |||||
public DateTime Expiration { get; private set; } | |||||
protected Payment() { } | |||||
public Payment(string alias, string cardNumber, string securityNumber, string cardHolderName, DateTime expiration, int cardTypeId) | |||||
{ | |||||
if (String.IsNullOrWhiteSpace(cardNumber)) | |||||
{ | |||||
throw new ArgumentException(nameof(cardNumber)); | |||||
} | |||||
if (String.IsNullOrWhiteSpace(securityNumber)) | |||||
{ | |||||
throw new ArgumentException(nameof(securityNumber)); | |||||
} | |||||
if (String.IsNullOrWhiteSpace(cardHolderName)) | |||||
{ | |||||
throw new ArgumentException(nameof(cardHolderName)); | |||||
} | |||||
if (expiration < DateTime.UtcNow) | |||||
{ | |||||
throw new ArgumentException(nameof(expiration)); | |||||
} | |||||
this.Alias = alias; | |||||
this.CardNumber = cardNumber; | |||||
this.SecurityNumber = securityNumber; | |||||
this.CardHolderName = cardHolderName; | |||||
this.Expiration = expiration; | |||||
this.CardTypeId = cardTypeId; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,59 @@ | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; | |||||
using System; | |||||
namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate | |||||
{ | |||||
public class PaymentMethod | |||||
: Entity | |||||
{ | |||||
private int _buyerId; | |||||
private string _alias; | |||||
private string _cardNumber; | |||||
private string _securityNumber; | |||||
private string _cardHolderName; | |||||
private DateTime _expiration; | |||||
private int _cardTypeId; | |||||
public CardType CardType { get; private set; } | |||||
protected PaymentMethod() { } | |||||
public PaymentMethod(int cardTypeId, string alias, string cardNumber, string securityNumber, string cardHolderName, DateTime expiration) | |||||
{ | |||||
if (String.IsNullOrWhiteSpace(cardNumber)) | |||||
{ | |||||
throw new ArgumentException(nameof(cardNumber)); | |||||
} | |||||
if (String.IsNullOrWhiteSpace(securityNumber)) | |||||
{ | |||||
throw new ArgumentException(nameof(securityNumber)); | |||||
} | |||||
if (String.IsNullOrWhiteSpace(cardHolderName)) | |||||
{ | |||||
throw new ArgumentException(nameof(cardHolderName)); | |||||
} | |||||
if (expiration < DateTime.UtcNow) | |||||
{ | |||||
throw new ArgumentException(nameof(expiration)); | |||||
} | |||||
_alias = alias; | |||||
_cardNumber = cardNumber; | |||||
_securityNumber = securityNumber; | |||||
_cardHolderName = cardHolderName; | |||||
_expiration = expiration; | |||||
_cardTypeId = cardTypeId; | |||||
} | |||||
public bool IsEqualTo(int cardTypeId, string cardNumber,DateTime expiration) | |||||
{ | |||||
return _cardTypeId == cardTypeId | |||||
&& _cardNumber == cardNumber | |||||
&& _expiration == expiration; | |||||
} | |||||
} | |||||
} |
@ -1,22 +1,26 @@ | |||||
namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate | |||||
{ | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; | |||||
using System; | |||||
using System; | |||||
//(CDLTLL) | |||||
//TO DO: Need to convert this entity to a Value-Object (Address VO) | |||||
namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate | |||||
{ | |||||
public class Address | public class Address | ||||
: Entity | |||||
{ | { | ||||
public String Street { get; set; } | |||||
public String Street { get; } | |||||
public String City { get; set; } | |||||
public String City { get; } | |||||
public String State { get; set; } | |||||
public String State { get; } | |||||
public String Country { get; set; } | |||||
public String Country { get; } | |||||
public String ZipCode { get; set; } | |||||
public String ZipCode { get; } | |||||
public Address(string street, string city, string state, string country, string zipcode) | |||||
{ | |||||
Street = street; | |||||
City = city; | |||||
State = state; | |||||
Country = country; | |||||
ZipCode = zipcode; | |||||
} | |||||
} | } | ||||
} | } |
@ -1,79 +1,75 @@ | |||||
namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate | |||||
{ | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
//(CDLTLL) | |||||
//TO DO: Need to add additional Domain Logic to this Aggregate-Root for | |||||
//scenarios related to Order state changes, stock availability validation, etc. | |||||
namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate | |||||
{ | |||||
public class Order | public class Order | ||||
: Entity, IAggregateRoot | |||||
: Entity | |||||
{ | { | ||||
public int BuyerId { get; private set; } | |||||
private string _street; | |||||
private string _city; | |||||
private string _state; | |||||
private string _country; | |||||
private string _zipCode; | |||||
private DateTime _orderDate; | |||||
public Buyer Buyer { get; private set; } | public Buyer Buyer { get; private set; } | ||||
int _buyerId; | |||||
public DateTime OrderDate { get; private set; } | |||||
public int StatusId { get; private set; } | |||||
public OrderStatus Status { get; private set; } | |||||
public ICollection<OrderItem> OrderItems { get; private set; } | |||||
public OrderStatus OrderStatus { get; private set; } | |||||
int _orderStatusId; | |||||
public int? ShippingAddressId { get; private set; } | |||||
HashSet<OrderItem> _orderItems; | |||||
public IEnumerable<OrderItem> OrderItems => _orderItems.ToList().AsEnumerable(); | |||||
public Address ShippingAddress { get; private set; } | |||||
public int PaymentId { get; private set; } | |||||
public Payment Payment { get; private set; } | |||||
public PaymentMethod PaymentMethod { get; private set; } | |||||
int _paymentMethodId; | |||||
protected Order() { } | protected Order() { } | ||||
public Order(int buyerId, int paymentId) | |||||
public Order(int buyerId, int paymentMethodId, Address address) | |||||
{ | { | ||||
BuyerId = buyerId; | |||||
PaymentId = paymentId; | |||||
StatusId = OrderStatus.InProcess.Id; | |||||
OrderDate = DateTime.UtcNow; | |||||
OrderItems = new List<OrderItem>(); | |||||
_buyerId = buyerId; | |||||
_paymentMethodId = paymentMethodId; | |||||
_orderStatusId = OrderStatus.InProcess.Id; | |||||
_orderDate = DateTime.UtcNow; | |||||
_street = address.Street; | |||||
_city = address.City; | |||||
_state = address.State; | |||||
_country = address.Country; | |||||
_zipCode = address.ZipCode; | |||||
_orderItems = new HashSet<OrderItem>(); | |||||
} | } | ||||
public void SetAddress(Address address) | |||||
public void AddOrderItem(int productId, string productName, decimal unitPrice, decimal discount, string pictureUrl, int units = 1) | |||||
{ | { | ||||
if (address == null) | |||||
{ | |||||
throw new ArgumentNullException(nameof(address)); | |||||
} | |||||
var existingOrderForProduct = _orderItems.Where(o => o.ProductId == productId) | |||||
.SingleOrDefault(); | |||||
ShippingAddress = address; | |||||
} | |||||
if (existingOrderForProduct != null) | |||||
{ | |||||
//if previous line exist modify it with higher discount and units.. | |||||
//TO DO: | |||||
// (CDLTLL) Bad implementation, needs to be changed. | |||||
// The AddOrderItem should have the needed data params | |||||
// instead of an already created OrderItem object. | |||||
// The Aggregate-Root is responsible for any Update/Creation of its child entities | |||||
// If we are providing an already created OrderItem, that was created from the outside | |||||
// and the AggregateRoot cannot control/validate any rule/invariants/consistency. | |||||
public void AddOrderItem(OrderItem item) | |||||
{ | |||||
//TO DO: Bad implementation, need to change. | |||||
// The code "new OrderItem(params);" should be done here | |||||
// Plus any validation/rule related | |||||
OrderItems.Add(item); | |||||
if (discount > existingOrderForProduct.GetCurrentDiscount()) | |||||
{ | |||||
existingOrderForProduct.SetNewDiscount(discount); | |||||
existingOrderForProduct.AddUnits(units); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
//add validated new order item | |||||
//(CDLTLL) | |||||
// TO DO: Some more logic needs to be added here, | |||||
// Like consolidating items that are the same product in one single OrderItem with several units | |||||
// Also validation logic could be added here (like ensuring it is adding at least one item unit) | |||||
var orderItem = new OrderItem(productId, productName, unitPrice, discount, pictureUrl, units); | |||||
//Or, If there are different amounts of discounts per added OrderItem | |||||
//but the product Id is the same to existing Order Items, you should | |||||
//apply the higher discount, or any other domain logic that makes sense. | |||||
_orderItems.Add(orderItem); | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } |
@ -1,28 +1,75 @@ | |||||
namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate | |||||
{ | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.SeedWork; | |||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork; | |||||
using System; | |||||
//TO DO: | |||||
//(CDLTLL) Wrong implementation. Need to put Setters as private | |||||
// and only be able to update the OrderItem through specific methods, if needed, so we can | |||||
// have validations/control/logic in those "update or set methods". | |||||
//We also need to have a constructor with the needed params, we must not use the "setters".. | |||||
namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate | |||||
{ | |||||
public class OrderItem | public class OrderItem | ||||
:Entity | |||||
: Entity | |||||
{ | { | ||||
public int ProductId { get; set; } | |||||
private string _productName; | |||||
private string _pictureUrl; | |||||
private int _orderId; | |||||
private decimal _unitPrice; | |||||
private decimal _discount; | |||||
private int _units; | |||||
public int ProductId { get; private set; } | |||||
protected OrderItem() { } | |||||
public OrderItem(int productId, string productName, decimal unitPrice, decimal discount, string PictureUrl, int units = 1) | |||||
{ | |||||
if (units <= 0) | |||||
{ | |||||
throw new ArgumentNullException("Invalid number of units"); | |||||
} | |||||
if ((unitPrice * units) < discount) | |||||
{ | |||||
throw new ArgumentException("The total of order item is lower than applied discount"); | |||||
} | |||||
ProductId = productId; | |||||
public string ProductName { get; set; } | |||||
_productName = productName; | |||||
_unitPrice = unitPrice; | |||||
_discount = discount; | |||||
_units = units; | |||||
_pictureUrl = PictureUrl; | |||||
} | |||||
public string PictureUrl { get; set; } | |||||
public void SetPictureUri(string pictureUri) | |||||
{ | |||||
if (!String.IsNullOrWhiteSpace(pictureUri)) | |||||
{ | |||||
_pictureUrl = pictureUri; | |||||
} | |||||
} | |||||
public int OrderId { get; set; } | |||||
public decimal GetCurrentDiscount() | |||||
{ | |||||
return _discount; | |||||
} | |||||
public decimal UnitPrice { get; set; } | |||||
public void SetNewDiscount(decimal discount) | |||||
{ | |||||
if (discount < 0) | |||||
{ | |||||
throw new ArgumentException("Discount is not valid"); | |||||
} | |||||
public decimal Discount { get; set; } | |||||
_discount = discount; | |||||
} | |||||
public int Units { get; set; } | |||||
public void AddUnits(int units) | |||||
{ | |||||
if (units < 0) | |||||
{ | |||||
throw new ArgumentException("Invalid units"); | |||||
} | |||||
_units += units; | |||||
} | |||||
} | } | ||||
} | } |