Skip to content

Instantly share code, notes, and snippets.

@arleypadua
Last active August 4, 2023 12:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arleypadua/f96a8b0fc6ed6b358a7afd6d5de5a1ed to your computer and use it in GitHub Desktop.
Save arleypadua/f96a8b0fc6ed6b358a7afd6d5de5a1ed to your computer and use it in GitHub Desktop.
Rich Domain Model
public class Order
{
private Order() { }
public string OrderId { get; private set; }
public string CustomerId { get; private set; }
public decimal Discount { get; private set; }
public bool Paid { get; private set; }
public DateTime? PaymentTime { get; private set; }
public DateTime CreationTime { get; private set; }
private List<OrderItem> _items; // The original source is private and can only be modified by this class.
public IEnumerable<OrderItem> Items => _items.AsReadOnly(); // Exposes a readonly copy of order items
public static Order New(string orderId, string customerId, DateTime? creationTime = null)
{
if (string.IsNullOrWhiteSpace(orderId)) throw new ArgumentNullException(nameof(orderId));
if (string.IsNullOrWhiteSpace(customerId)) throw new ArgumentNullException(nameof(customerId));
return new Order
{
OrderId = orderId,
CustomerId = customerId,
CreationTime = creationTime ?? DateTime.UtcNow,
_items = new List<OrderItem>()
};
}
public decimal TotalDiscountOnItems => Items.Sum(i => i.Discount);
public decimal GrossTotal => Items.Sum(i => i.Quantity * i.Price);
public decimal OrderTotal => GrossTotal - TotalDiscountOnItems - Discount;
public void AddItem(OrderItem item)
{
if (Paid) throw new InvalidOperationException("The order is paid already.");
if (_items.Count > 5) throw new InvalidOperationException("Cannot add more than 5 items in an order.");
if (TotalDiscountOnItems + item.Discount > GrossTotal) throw new ArgumentException("Discount on item cannot exceed the order total.");
_items.Add(item);
}
public void AddOrderDiscount(decimal discount)
{
if (Paid) throw new InvalidOperationException("The order is already paid.");
if (OrderTotal - discount < 0) throw new ArgumentException("Discount cannot exceed the order total.", nameof(discount));
Discount = discount;
}
public void PayOrder()
{
if (Paid) return;
Paid = true;
PaymentTime = DateTime.UtcNow;
}
}
public class OrderItem
{
private OrderItem() { }
public static OrderItem New(string productId, int quantity, decimal price, decimal discount = 0)
{
if (string.IsNullOrWhiteSpace(productId)) throw new ArgumentNullException(nameof(productId));
if (quantity <= 0) throw new ArgumentOutOfRangeException(nameof(quantity));
if (price <= 0) throw new ArgumentOutOfRangeException(nameof(price));
if (discount <= 0) throw new ArgumentOutOfRangeException(nameof(discount));
if (discount > price * quantity) throw new ArgumentException("The discount cannot be more than the total of the order item.", nameof(discount));
return new OrderItem
{
ProductId = productId,
Quantity = quantity,
Price = price,
Discount = discount
};
}
public string ProductId { get; private set; }
public int Quantity { get; private set; }
public decimal Price { get; private set; }
public decimal Discount { get; private set; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment