public void ProcessOrder(OrderData orderData)
        {
            try
            {
                using (TransactionScope scope = new TransactionScope())
                {
                    Customer customer = _StoreRepository.GetCustomerByEmail(orderData.CustomerEmail);
                    if (customer == null)
                    {
                        throw new ApplicationException(string.Format("No customer on file with email {0}.", orderData.CustomerEmail));
                    }

                    foreach (OrderLineItemData lineItem in orderData.LineItems)
                    {
                        if (_CommerceEvents.OrderItemProcessed != null)
                        {
                            OrderItemProcessedEventArgs args = new OrderItemProcessedEventArgs(customer, lineItem, _StoreRepository);
                            _CommerceEvents.OrderItemProcessed(args);
                            if (args.Cancel)
                            {
                                throw new ApplicationException(args.MessageText);
                            }
                        }

                        Product product = _StoreRepository.Products.Where(item => item.Sku == lineItem.Sku).FirstOrDefault();
                        if (product == null)
                        {
                            throw new ApplicationException(string.Format("Sku {0} not found in store inventory.", lineItem.Sku));
                        }

                        Inventory inventoryOnHand = _StoreRepository.ProductInventory.Where(item => item.Sku == lineItem.Sku).FirstOrDefault();
                        if (inventoryOnHand == null)
                        {
                            throw new ApplicationException(string.Format("Error attempting to determine on-hand inventory quantity for product {0}.", lineItem.Sku));
                        }

                        if (inventoryOnHand.QuantityInStock < lineItem.Quantity)
                        {
                            throw new ApplicationException(string.Format("Not enough quantity on-hand to satisfy product {0} purchase of {1} units.", lineItem.Sku, lineItem.Quantity));
                        }

                        inventoryOnHand.QuantityInStock -= lineItem.Quantity;
                        Console.WriteLine("Inventory for product {0}({2}) reduced by {1} units at {3}.", lineItem.Sku, lineItem.Quantity, product.Description, DateTime.Now.ToString());
                    }

                    // Update customer records with purchase
                    foreach (OrderLineItemData lineItem in orderData.LineItems)
                    {
                        for (int i = 0; i < lineItem.Quantity; i++)
                        {
                            customer.Purchases.Add(new PurchasedItem()
                            {
                                Sku = lineItem.Sku, PurchasePrice = lineItem.PurchasePrice, PurchasedOn = DateTime.Now
                            });
                        }
                        Console.WriteLine("Added {0} unit(s) or product {1} to customer's purchase history.", lineItem.Quantity, lineItem.Sku);
                    }

                    // Process customer credit card
                    double amount = 0;
                    foreach (OrderLineItemData lineItem in orderData.LineItems)
                    {
                        amount += (lineItem.PurchasePrice * lineItem.Quantity);
                    }

                    bool paymentSuccess = _PaymentProcessor.ProcessCreditCard(customer.Name, orderData.CreditCard, orderData.ExpirationDate, amount);
                    if (!paymentSuccess)
                    {
                        throw new ApplicationException(string.Format("Credit card {0} could not be processed.", orderData.CreditCard));
                    }

                    // Send invoice email
                    _Mailer.SendInvoiceEmail(orderData);

                    scope.Complete();
                }
            }
            catch (Exception)
            {
                _Mailer.SendRejectionEmail(orderData);
                throw;
            }
        }
        public void Initialize(CommerceEvents events, NameValueCollection config)
        {
            events.AdjustOrder += args =>
            {
                foreach (var lineItem in args.OrderData.LineItems)
                {
                    #region 1 - Check for promotion

                    if (events.OrderItemProcessed != null)
                    {
                        var e = new OrderItemProcessedEventArgs(args.Customer, lineItem, null);
                        events.OrderItemProcessed(e);

                        if (e.Cancel)
                        {
                            // do something important
                            throw new ApplicationException(e.Message);
                        }
                    }

                    #endregion

                    #region 2 - Get product

                    var product =
                        args.StoreRepository.Products.FirstOrDefault(item => item.Sku == lineItem.Sku);
                    if (product == null)
                    {
                        throw new ApplicationException($"Sku {lineItem.Sku} not found in store inventory.");
                    }

                    #endregion

                    #region 3 - Get line item by sku

                    var inventoryOnHand =
                        args.StoreRepository.ProductInventory.FirstOrDefault(
                            item => item.Sku == lineItem.Sku);
                    if (inventoryOnHand == null)
                    {
                        throw new ApplicationException(
                                  $"Error attempting to determine on-hand inventory quantity for product {lineItem.Sku}.");
                    }

                    #endregion

                    #region 4 - Check if line item in stock

                    if (inventoryOnHand.QuantityInStock < lineItem.Quantity)
                    {
                        throw new ApplicationException(
                                  $"Not enough quantity on-hand to satisfy product {lineItem.Sku} purchase of {lineItem.Quantity} units.");
                    }

                    #endregion

                    #region 5 - Change stock of the line item

                    inventoryOnHand.QuantityInStock -= lineItem.Quantity;

                    Console.WriteLine(
                        $"\tInventory for product {lineItem.Sku} reduced by {lineItem.Quantity} units.");
                    Console.WriteLine();

                    #endregion
                }
            };
        }