83 lines
3.4 KiB
C#
83 lines
3.4 KiB
C#
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate;
|
|
using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate
|
|
{
|
|
public class Order
|
|
: Entity
|
|
{
|
|
// DDD Patterns comment
|
|
// Using private fields, allowed since EF Core 1.1, is a much better encapsulation
|
|
// aligned with DDD Aggregates and Domain Entities (Instead of properties and property collections)
|
|
private DateTime _orderDate;
|
|
|
|
public Address Address { get; private set; }
|
|
|
|
public Buyer Buyer { get; private set; }
|
|
private int _buyerId;
|
|
|
|
public OrderStatus OrderStatus { get; private set; }
|
|
private int _orderStatusId;
|
|
|
|
// DDD Patterns comment
|
|
// Using a private collection field, better for DDD Aggregate's encapsulation
|
|
// so OrderItems cannot be added from "outside the AggregateRoot" directly to the collection,
|
|
// but only through the method OrderAggrergateRoot.AddOrderItem() which includes behaviour.
|
|
private readonly List<OrderItem> _orderItems;
|
|
|
|
public IEnumerable<OrderItem> OrderItems => _orderItems.AsReadOnly();
|
|
// Using List<>.AsReadOnly()
|
|
// This will create a read only wrapper around the private list so is protected against "external updates".
|
|
// It's much cheaper than .ToList() because it will not have to copy all items in a new collection. (Just one heap alloc for the wrapper instance)
|
|
//https://msdn.microsoft.com/en-us/library/e78dcd75(v=vs.110).aspx
|
|
|
|
public PaymentMethod PaymentMethod { get; private set; }
|
|
private int _paymentMethodId;
|
|
|
|
protected Order() { }
|
|
|
|
public Order(int buyerId, int paymentMethodId, Address address)
|
|
{
|
|
_orderItems = new List<OrderItem>();
|
|
_buyerId = buyerId;
|
|
_paymentMethodId = paymentMethodId;
|
|
_orderStatusId = OrderStatus.InProcess.Id;
|
|
_orderDate = DateTime.UtcNow;
|
|
|
|
Address = address;
|
|
}
|
|
|
|
// DDD Patterns comment
|
|
// This Order AggregateRoot's method "AddOrderitem()" should be the only way to add Items to the Order,
|
|
// so any behavior (discounts, etc.) and validations are controlled by the AggregateRoot
|
|
// in order to maintain consistency between the whole Aggregate.
|
|
public void AddOrderItem(int productId, string productName, decimal unitPrice, decimal discount, string pictureUrl, int units = 1)
|
|
{
|
|
var existingOrderForProduct = _orderItems.Where(o => o.ProductId == productId)
|
|
.SingleOrDefault();
|
|
|
|
if (existingOrderForProduct != null)
|
|
{
|
|
//if previous line exist modify it with higher discount and units..
|
|
|
|
if (discount > existingOrderForProduct.GetCurrentDiscount())
|
|
{
|
|
existingOrderForProduct.SetNewDiscount(discount);
|
|
existingOrderForProduct.AddUnits(units);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//add validated new order item
|
|
|
|
var orderItem = new OrderItem(productId, productName, unitPrice, discount, pictureUrl, units);
|
|
|
|
_orderItems.Add(orderItem);
|
|
}
|
|
}
|
|
}
|
|
}
|