1 usingSystem;2 usingSystem.Collections.Generic;3 usingSystem.Linq;4 usingSystem.Text;5 usingAgathas.Storefront.Infrastructure.Domain;6 usingAgathas.Storefront.Model.Customers;7 usingAgathas.Storefront.Model.Orders.States;8 usingAgathas.Storefront.Model.Products;9 usingAgathas.Storefront.Model.Shipping;10
11 namespaceAgathas.Storefront.Model.Orders12 {13 public class Order : EntityBase, IAggregateRoot14 {15 private IList_items;16 privateDateTime _created;17 privatePayment _payment;18 privateIOrderState _state;19
20 publicOrder()21 {22 _created =DateTime.Now;23 _items = new List();24 _state =OrderStates.Open;25 }26
27 publicDateTime Created28 {29 get { return_created; }30 }31
32 public decimal ShippingCharge { get; set; }33
34 public ShippingService ShippingService { get; set; }35
36 public decimalItemTotal()37 {38 return Items.Sum(i =>i.LineTotal());39 }40
41 public decimalTotal()42 {43 return Items.Sum(i => i.LineTotal()) +ShippingCharge;44 }45
46 publicPayment Payment47 {48 get { return_payment; }49 }50
51 public voidSetPayment(Payment payment)52 {53 if(OrderHasBeenPaidFor())54 throw newOrderAlreadyPaidForException(55 GetDetailsOnExisitingPayment());56
57 if(OrderTotalMatches(payment))58 _payment =payment;59 else
60 throw newPaymentAmountDoesNotEqualOrderTotalException(61 GetDetailsOnIssueWith(payment));62
63 _state.Submit(this);64 }65
66 private stringGetDetailsOnExisitingPayment()67 {68 return String.Format("Order has already been paid for." +
69 "{0} was paid on {1}. Payment token '{2}'",70 Payment.Amount, Payment.DatePaid,71 Payment.TransactionId);72 }73
74 private stringGetDetailsOnIssueWith(Payment payment)75 {76 return String.Format("Payment amount is invalid." +
77 "Order total is {0} but payment for {1}." +
78 "Payment token '{2}'",79 this.Total(), payment.Amount, payment.TransactionId);80 }81
82 public boolOrderHasBeenPaidFor()83 {84 return Payment != null &&OrderTotalMatches(Payment);85 }86
87 private boolOrderTotalMatches(Payment payment)88 {89 return Total() ==payment.Amount;90 }91
92 public Customer Customer { get; set; }93
94 public Address DeliveryAddress { get; set; }95
96 public IEnumerableItems97 {98 get { return_items; }99 }100
101 publicOrderStatus Status102 {103 get { return_state.Status; }104 }105
106 public void AddItem(Product product, intqty)107 {108 if(_state.CanAddProduct())109 {110 if (!OrderContains(product))111 _items.Add(OrderItemFactory.CreateItemFor(product, this, qty));112 }113 else
114 throw newCannotAmendOrderException(String.Format(115 "You cannot add an item to an order with the status of '{0}'.",116 Status.ToString()));117 }118
119 private boolOrderContains(Product product)120 {121 return _items.Any(i =>i.Contains(product));122 }123
124 protected override voidValidate()125 {126 if (Created ==DateTime.MinValue)127 base.AddBrokenRule(OrderBusinessRules.CreatedDateRequired);128
129 if (Customer == null)130 base.AddBrokenRule(OrderBusinessRules.CustomerRequired);131
132 if (DeliveryAddress == null)133 base.AddBrokenRule(OrderBusinessRules.DeliveryAddressRequired);134
135 if (Items == null || Items.Count() == 0)136 base.AddBrokenRule(OrderBusinessRules.ItemsRequired);137 else
138 {139 if (Items.Any(i => i.GetBrokenRules().Count() > 0))140 {141 foreach (OrderItem item in Items.Where(i => i.GetBrokenRules().Count() > 0))142 {143 foreach (BusinessRule businessRule initem.GetBrokenRules())144 {145 base.AddBrokenRule(businessRule);146 }147 }148 }149 }150
151 if (ShippingService == null)152 base.AddBrokenRule(OrderBusinessRules.ShippingServiceRequired);153
154 }155
156 internal voidSetStateTo(IOrderState state)157 {158 this._state =state;159 }160
161 public override stringToString()162 {163 StringBuilder orderInfo = newStringBuilder();164
165 foreach (OrderItem item in_items)166 {167 orderInfo.AppendLine(String.Format("{0} of {1}",168 item.Qty, item.Product.Name));169 }170
171 orderInfo.AppendLine(String.Format("Shipping: {0}", this.ShippingCharge));172 orderInfo.AppendLine(String.Format("Total: {0}", this.Total()));173
174 returnorderInfo.ToString();175
176 }177 }178
179 }