public PreOrderSummary SaveShippingRateQuote(SalesPreparationModel model)
        {
            // This is sort of weird to have the customer key in the ShippingAddress ... but we repurposed an object
            // to simplify the JS
            var customer = Services.CustomerService.GetAnyByKey(model.ShippingAddress.CustomerKey);

            if (customer == null)
            {
                throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
            }

            var salesPreparation = customer.Basket().SalePreparation();

            if (salesPreparation.ItemCache.Items.Any(x => x.LineItemType == LineItemType.Shipping))
            {
                foreach (var shipQuote in salesPreparation.ItemCache.Items.Where(x => x.LineItemType == LineItemType.Shipping))
                {
                    salesPreparation.ItemCache.Items.RemoveItem(shipQuote.Sku);
                }
            }

            // save the ship rate quote selected
            var shipments = customer.Basket().PackageBasket(model.ShippingAddress.ToAddress()).ToArray();

            if (shipments.Any() && model.ShipMethodKey != Guid.Empty)
            {
                // there will only be one shipment in version 1.  This quote is cached in
                // the runtime cache so there should not be another trip to the provider (if it were carrier based)
                var approvedQuote = shipments.First().ShipmentRateQuoteByShipMethod(model.ShipMethodKey);

                salesPreparation.SaveShipmentRateQuote(approvedQuote);
            }

            return(GetPreOrderSummary(salesPreparation));
        }
        public PreOrderSummary SaveBillingAddress(SalesPreparationModel model)
        {
            var salesPreparation = GetSalePreparation(model.BillingAddress.CustomerKey);

            salesPreparation.SaveBillToAddress(model.BillingAddress.ToAddress());

            return(GetPreOrderSummary(salesPreparation));
        }
        public object PlaceOrder(SalesPreparationModel model)
        {
            var customer = Services.CustomerService.GetAnyByKey(model.ShippingAddress.CustomerKey);

            if (customer == null)
            {
                throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
            }

            var salesPreparation = customer.Basket().SalePreparation();

            salesPreparation.SaveBillToAddress(model.BillingAddress.ToAddress());

            if (!salesPreparation.IsReadyToInvoice())
            {
                return new
                       {
                           Success = false,
                           Message = "Not ready to invoice"
                       }
            }
            ;

            var processorArgs = model.PaymentArgs.ToProcessorArgumentCollection();

            //// TODO - refactor after Merchello issue #M-297 has been resolved.

            var method = MerchelloContext.Current.Gateways.Payment.GetPaymentGatewayMethodByKey(model.PaymentMethodKey);

            var attempt = method.PaymentMethod.ProviderKey.Equals(Merchello.Core.Constants.ProviderKeys.Payment.CashPaymentProviderKey) ?
                          salesPreparation.AuthorizePayment(model.PaymentMethodKey, processorArgs) :
                          salesPreparation.AuthorizeCapturePayment(model.PaymentMethodKey, processorArgs);

            if (!attempt.Payment.Success)
            {
                return new
                       {
                           Success = attempt.Payment.Success.ToString(),
                           attempt.Payment.Exception.Message
                       }
            }
            ;

            // Example of http://issues.merchello.com/youtrack/issue/M-290
            if (customer.IsAnonymous)
            {
                if (customer.ExtendedData.ContainsKey(SiteConstants.ExtendedDataKeys.AnonymousCustomersInvoices))
                {
                    var existing = customer.ExtendedData.GetValue(SiteConstants.ExtendedDataKeys.AnonymousCustomersInvoices);
                    customer.ExtendedData.SetValue(SiteConstants.ExtendedDataKeys.AnonymousCustomersInvoices, string.Format("{0},{1}", existing, attempt.Invoice.Key));
                }
                else
                {
                    customer.ExtendedData.SetValue(SiteConstants.ExtendedDataKeys.AnonymousCustomersInvoices, attempt.Invoice.Key.ToString());
                }
            }

            Notification.Trigger("OrderConfirmation", attempt, new[] { model.ContactInfo.Email });

            return(new { Redirect = string.Format("/checkout/receipt/{0}", attempt.Invoice.Key.ToString()) });
        }