public UserCreditCard CreateCreditCardForUser(UserCreditCard card)
        {
            card = manager.CreateCustomerCard(card);

            if(card == null)
                return null;

            using(var context = new RentlerContext())
            {
                context.UserCreditCards.Add(card);
                context.SaveChanges();
            }

            return card;
        }
        public Status<UserCreditCard> AddUserCreditCard(string username, UserCreditCard card)
        {
            if (string.IsNullOrWhiteSpace(username))
                return Status.ValidationError<UserCreditCard>(null, "username", "The username is required");

            if (card == null)
                return Status.ValidationError<UserCreditCard>(null, "card", "card is null");

            card.CreatedBy = "orderadapter";
            card.CreateDate = DateTime.UtcNow;

            // validate the contactinfo
            var cardValidation = Status.Validatate<UserCreditCard>(card);
            if (cardValidation.StatusCode != 200)
                return Status.ValidationError<UserCreditCard>(card, "", "credit card is not valid");

            card.AccountReference = Guid.NewGuid();

            card = manager.CreateCustomerCard(card);

            if (card == null)
                return Status.Error("Problem creating card on payment service.", card);

            using (RentlerContext context = new RentlerContext())
            {
                try
                {
                    var user = (from u in context.Users
                                where u.IsDeleted == false &&
                                u.Username == username
                                select u).SingleOrDefault();

                    user.UserCreditCards.Add(card);
                    context.SaveChanges();

                    return Status.OK<UserCreditCard>(card);
                }
                catch (Exception ex)
                {
                    return Status.Error<UserCreditCard>(ex.Message, card);
                }
            }
        }
        /// <summary>
        /// Creates a one-time payment, to be processed on a specific date.
        /// Use this method for move in/out stuff like security deposits, pro-rated rent, etc.
        /// </summary>
        /// <param name="card">The user's credit card.</param>
        /// <param name="amount">The amount to charge the user.</param>
        /// <param name="payDate">The date to process the transaction.</param>
        public SinglePaymentResult CreateSinglePayment(UserCreditCard card, decimal amount, DateTime payDate)
        {
            if(card.Alias == null)
                throw new ArgumentNullException("Credit Card alias is null.");

            return manager.CreateSinglePayment(card.Alias.Value, amount, payDate, PaymentType.CreditCard);
        }
 /// <summary>
 /// Charges a customer's credit card for the amount, immediately.
 /// Use this for subscription/fee's.
 /// </summary>
 /// <param name="card">The user's credit card.</param>
 /// <param name="amount">The amount to charge the user.</param>
 /// <returns>A SinglePaymentResult, stating whether the card was approved and
 /// if not, why.</returns>
 public CardPaymentResult AuthorizePayment(UserCreditCard card, decimal amount)
 {
     return manager.AuthorizeCreditCardPayment(card, amount);
 }
        /// <summary>
        /// Takes care of storing the user's credit card information.
        /// If it is a new card, it will create a new entry in the payment system
        /// and in our own storage. If it is just an update (e.g. the user changing their
        /// address information), it will act accordingly.
        /// </summary>
        /// <param name="card">The user's credit card.</param>
        public void UpdateCreditCardForUser(UserCreditCard card)
        {
            card = manager.UpdateCustomerCard(card);

            if(card.UserCreditCardId == 0)
                CreateCreditCardForUser(card);
            else
            {
                UserCreditCard toUpdate = null;

                using(var context = new RentlerContext())
                {
                    toUpdate = (from u in context.UserCreditCards
                                where u.UserId == card.UserId &&
                                      u.UserCreditCardId == card.UserCreditCardId
                                select u).SingleOrDefault();

                    if(toUpdate == null)
                        throw new ArgumentNullException();

                    toUpdate.Alias = card.Alias;
                    toUpdate.AccountReference = card.AccountReference;
                    toUpdate.CardName = card.CardName;
                    toUpdate.CardNumber = card.CardNumber;
                    toUpdate.ExpirationMonth = card.ExpirationMonth;
                    toUpdate.ExpirationYear = card.ExpirationYear;
                    toUpdate.Address1 = card.Address1;
                    toUpdate.Address2 = card.Address2;
                    toUpdate.City = card.City;
                    toUpdate.Email = card.Email;
                    toUpdate.FirstName = card.FirstName;
                    toUpdate.LastName = card.LastName;
                    toUpdate.Phone = card.Phone;
                    toUpdate.State = card.State;
                    toUpdate.Zip = card.Zip;
                    toUpdate.IsDeleted = card.IsDeleted;

                    context.SaveChanges();
                }
            }
        }
        public void DeleteUserCreditCard(UserCreditCard card)
        {
            card.IsDeleted = true;

            manager.UpdateCustomerCard(card);
            UpdateCreditCardForUser(card);
        }
        public Status<UserCreditCard> UpdateUserCreditCard(string username, UserCreditCard card)
        {
            if (string.IsNullOrWhiteSpace(username))
                return Status.ValidationError<UserCreditCard>(null, "username", "The username is required");

            if (card == null)
                return Status.ValidationError<UserCreditCard>(null, "card", "card is null");

            card = manager.UpdateCustomerCard(card);

            if (card.UserCreditCardId == 0)
                return AddUserCreditCard(username, card);

            using (RentlerContext context = new RentlerContext())
            {
                try
                {
                    var userCreditCard = (from uc in context.UserCreditCards
                                          where uc.User.IsDeleted == false &&
                                          uc.User.Username == username &&
                                          uc.UserCreditCardId == card.UserCreditCardId
                                          select uc).SingleOrDefault();

                    userCreditCard.Alias = card.Alias;
                    userCreditCard.AccountReference = card.AccountReference;
                    userCreditCard.CardName = card.CardName;
                    userCreditCard.CardNumber = card.CardNumber;
                    userCreditCard.ExpirationMonth = card.ExpirationMonth;
                    userCreditCard.ExpirationYear = card.ExpirationYear;
                    userCreditCard.Address1 = card.Address1;
                    userCreditCard.Address2 = card.Address2;
                    userCreditCard.City = card.City;
                    userCreditCard.Email = card.Email;
                    userCreditCard.FirstName = card.FirstName;
                    userCreditCard.LastName = card.LastName;
                    userCreditCard.Phone = card.Phone;
                    userCreditCard.State = card.State;
                    userCreditCard.Zip = card.Zip;
                    userCreditCard.IsDeleted = card.IsDeleted;
                    userCreditCard.UpdatedBy = "orderadapter";
                    userCreditCard.UpdateDate = DateTime.UtcNow;

                    context.SaveChanges();

                    return Status.OK<UserCreditCard>(card);
                }
                catch (Exception ex)
                {
                    return Status.Error<UserCreditCard>(ex.Message, card);
                }
            }
        }
        public Status<Order> ProcessOrder(
            string username, int orderId, UserCreditCard card, bool saveCard)
        {
            bool isNewCard = card.UserCreditCardId == 0;

            if (isNewCard)
            {
                // we're adding the new card regardless but we don't know if its valid
                // if the user requested to save it we will make it active after the payment
                // is successful, otherwise it will remain inactive
                card.IsDeleted = true;

                var cardResult = AddUserCreditCard(username, card);

                if (cardResult.StatusCode != 200)
                {
                    var orderStatus = GetOrderForCheckout(username, orderId);

                    orderStatus.StatusCode = 500;
                    orderStatus.Errors = new ValidationResult[] {
                        new ValidationResult("An unexpected failure occurred: payment was not processed", new string[] { "Order" })
                    };

                    return orderStatus;
                }
            }
            else
            {
                //get the card
                var storedCard = GetUserCreditCard(username, card.UserCreditCardId);

                if (storedCard == null)
                {
                    var orderStatus = GetOrderForCheckout(username, orderId);

                    orderStatus.StatusCode = 500;
                    orderStatus.Errors = new ValidationResult[] {
                        new ValidationResult("Failed to locate credit card on file: payment was not processed", new string[] { "Order" })
                    };

                    return orderStatus;
                }

                //update the billing address if anything changed
                if (storedCard.Address1 != card.Address1 ||
                    storedCard.Address2 != card.Address2 ||
                    storedCard.City != card.City ||
                    storedCard.FirstName != card.FirstName ||
                    storedCard.LastName != card.LastName ||
                    storedCard.State != card.State ||
                    storedCard.Zip != card.Zip)
                {
                    storedCard.Address1 = card.Address1;
                    storedCard.Address2 = card.Address2;
                    storedCard.City = card.City;
                    storedCard.FirstName = card.FirstName;
                    storedCard.LastName = card.LastName;
                    storedCard.State = card.State;
                    storedCard.Zip = card.Zip;

                    var updateStatus = UpdateUserCreditCard(username, storedCard);

                    if (updateStatus.StatusCode != 200)
                    {
                        var orderStatus = GetOrderForCheckout(username, orderId);

                        orderStatus.StatusCode = 500;
                        orderStatus.Errors = new ValidationResult[] {
                            new ValidationResult("Failed to update card address: payment was not processed", new string[] { "Order" })
                        };

                        return orderStatus;
                    }
                }

                card = storedCard;
            }

            //grab the order
            var order = GetOrderForCheckout(username, orderId);

            //attach the credit card to the order for our records
            order.Result.UserCreditCardId = card.UserCreditCardId;

            if (order.StatusCode != 200)
                return order;

            //let's pay for stuff!

            CardPaymentResult result;

            if (App.StorePricing == "Penny")
                result = manager.AuthorizeCreditCardPayment(card, 0.01m);
            else
                result = manager.AuthorizeCreditCardPayment(card, order.Result.OrderTotal);

            //did it work?
            if (result.Approved)
            {
                order.Result.OrderStatus = OrderStatus.Succeeded;
            }
            else
            {
                order.StatusCode = 500;

                // the payment method used is not valid so it should not be attached to
                // the order. Clear it here and the change will be persisted later
                order.Result.UserCreditCardId = null;

                //gateway might be down
                if (result.ServiceUnavailable)
                {
                    order.Result.OrderStatus = OrderStatus.ServiceUnavailable;
                    order.Errors = new ValidationResult[] {
                        new ValidationResult("Payment service is unavailable. Please try again later.", new string[] { "Order" })
                    };
                }
                //or it was declined
                else
                {
                    order.Result.OrderStatus = OrderStatus.CardDeclined;
                    order.Errors = new ValidationResult[] {
                        new ValidationResult("Credit Card was declined", new string[] { "Order" })
                    };
                }
            }

            //update the order status
            using (var context = new RentlerContext())
            {

                var toUpdate = (from o in context.Orders
                                    .Include("Building")
                                where o.OrderId == order.Result.OrderId
                                select o).SingleOrDefault();

                toUpdate.OrderStatus = order.Result.OrderStatus;
                toUpdate.UserCreditCardId = order.Result.UserCreditCardId;

                //remove temporary order if we're good
                if (order.Result.OrderStatus == OrderStatus.Succeeded)
                {
                    toUpdate.Building.TemporaryOrderId = null;

                    // allow credit card to be used again if requested
                    if (isNewCard && saveCard)
                    {
                        context.Entry(toUpdate).Reference(o => o.UserCreditCard).Load();
                        toUpdate.UserCreditCard.IsDeleted = false;
                    }
                }

                context.SaveChanges();
            }

            // send receipt only if order was successful
            if (order.Result.OrderStatus == OrderStatus.Succeeded)
            {
                //send a receipt
                EmailOrderReceiptModel model = new EmailOrderReceiptModel()
                {
                    To = order.Result.User.Email,
                    Name = string.Format("{0} {1}", order.Result.User.FirstName, order.Result.User.LastName),
                    BuildingId = (order.Result.BuildingId.HasValue) ? order.Result.BuildingId.Value : 0,
                    OrderItems = order.Result.OrderItems.ToList(),
                    OrderTotal = order.Result.OrderTotal
                };
                mailer.Receipt(model);
            }

            return order;
        }
 /// <summary>
 /// Create a new UserCreditCard object.
 /// </summary>
 /// <param name="userCreditCardId">Initial value of the UserCreditCardId property.</param>
 /// <param name="userId">Initial value of the UserId property.</param>
 /// <param name="cardNumber">Initial value of the CardNumber property.</param>
 /// <param name="cardName">Initial value of the CardName property.</param>
 /// <param name="expirationMonth">Initial value of the ExpirationMonth property.</param>
 /// <param name="expirationYear">Initial value of the ExpirationYear property.</param>
 /// <param name="firstName">Initial value of the FirstName property.</param>
 /// <param name="lastName">Initial value of the LastName property.</param>
 /// <param name="address1">Initial value of the Address1 property.</param>
 /// <param name="city">Initial value of the City property.</param>
 /// <param name="state">Initial value of the State property.</param>
 /// <param name="zip">Initial value of the Zip property.</param>
 /// <param name="isDeleted">Initial value of the IsDeleted property.</param>
 /// <param name="createDate">Initial value of the CreateDate property.</param>
 /// <param name="createdBy">Initial value of the CreatedBy property.</param>
 public static UserCreditCard CreateUserCreditCard(global::System.Int32 userCreditCardId, global::System.Int32 userId, global::System.String cardNumber, global::System.String cardName, global::System.Int32 expirationMonth, global::System.Int32 expirationYear, global::System.String firstName, global::System.String lastName, global::System.String address1, global::System.String city, global::System.String state, global::System.String zip, global::System.Boolean isDeleted, global::System.DateTime createDate, global::System.String createdBy)
 {
     UserCreditCard userCreditCard = new UserCreditCard();
     userCreditCard.UserCreditCardId = userCreditCardId;
     userCreditCard.UserId = userId;
     userCreditCard.CardNumber = cardNumber;
     userCreditCard.CardName = cardName;
     userCreditCard.ExpirationMonth = expirationMonth;
     userCreditCard.ExpirationYear = expirationYear;
     userCreditCard.FirstName = firstName;
     userCreditCard.LastName = lastName;
     userCreditCard.Address1 = address1;
     userCreditCard.City = city;
     userCreditCard.State = state;
     userCreditCard.Zip = zip;
     userCreditCard.IsDeleted = isDeleted;
     userCreditCard.CreateDate = createDate;
     userCreditCard.CreatedBy = createdBy;
     return userCreditCard;
 }
 /// <summary>
 /// Deprecated Method for adding a new object to the UserCreditCards EntitySet. Consider using the .Add method of the associated ObjectSet&lt;T&gt; property instead.
 /// </summary>
 public void AddToUserCreditCards(UserCreditCard userCreditCard)
 {
     base.AddObject("UserCreditCards", userCreditCard);
 }