ShoppingCartManager.cs :  » Web-Frameworks » nopCommerce » NopSolutions » NopCommerce » BusinessLogic » Orders » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Web Frameworks » nopCommerce 
nopCommerce » NopSolutions » NopCommerce » BusinessLogic » Orders » ShoppingCartManager.cs
//------------------------------------------------------------------------------
// The contents of this file are subject to the nopCommerce Public License Version 1.0 ("License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at  http://www.nopCommerce.com/License.aspx. 
// 
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. 
// See the License for the specific language governing rights and limitations under the License.
// 
// The Original Code is nopCommerce.
// The Initial Developer of the Original Code is NopSolutions.
// All Rights Reserved.
// 
// Contributor(s): _______. 
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Globalization;
using System.Linq;
using System.Text;
using NopSolutions.NopCommerce.BusinessLogic.Caching;
using NopSolutions.NopCommerce.BusinessLogic.Configuration.Settings;
using NopSolutions.NopCommerce.BusinessLogic.CustomerManagement;
using NopSolutions.NopCommerce.BusinessLogic.Localization;
using NopSolutions.NopCommerce.BusinessLogic.Payment;
using NopSolutions.NopCommerce.BusinessLogic.Products;
using NopSolutions.NopCommerce.BusinessLogic.Products.Attributes;
using NopSolutions.NopCommerce.BusinessLogic.Profile;
using NopSolutions.NopCommerce.BusinessLogic.Promo.Discounts;
using NopSolutions.NopCommerce.BusinessLogic.Shipping;
using NopSolutions.NopCommerce.BusinessLogic.Tax;
using NopSolutions.NopCommerce.DataAccess;
using NopSolutions.NopCommerce.DataAccess.Orders;
using NopSolutions.NopCommerce.Common;
using NopSolutions.NopCommerce.BusinessLogic.Audit;
using NopSolutions.NopCommerce.Common.Utils;
using System.Web;
using NopSolutions.NopCommerce.BusinessLogic.Directory;

namespace NopSolutions.NopCommerce.BusinessLogic.Orders{
    /// <summary>
    /// Shopping cart manager
    /// </summary>
    public partial class ShoppingCartManager
    {
        #region Utilities
        private static ShoppingCart DBMapping(DBShoppingCart dbCollection)
        {
            if (dbCollection == null)
                return null;

            var collection = new ShoppingCart();
            foreach (var dbItem in dbCollection)
            {
                var item = DBMapping(dbItem);
                collection.Add(item);
            }

            return collection;
        }

        private static ShoppingCartItem DBMapping(DBShoppingCartItem dbItem)
        {
            if (dbItem == null)
                return null;

            var item = new ShoppingCartItem();
            item.ShoppingCartItemId = dbItem.ShoppingCartItemId;
            item.ShoppingCartTypeId = dbItem.ShoppingCartTypeId;
            item.CustomerSessionGuid = dbItem.CustomerSessionGuid;
            item.ProductVariantId = dbItem.ProductVariantId;
            item.AttributesXml = dbItem.AttributesXml;
            item.CustomerEnteredPrice = dbItem.CustomerEnteredPrice;
            item.Quantity = dbItem.Quantity;
            item.CreatedOn = dbItem.CreatedOn;
            item.UpdatedOn = dbItem.UpdatedOn;

            return item;
        }

        #endregion

        #region Methods

        #region Repository methods

        /// <summary>
        /// Deletes expired shopping cart items
        /// </summary>
        /// <param name="olderThan">Older than date and time</param>
        public static void DeleteExpiredShoppingCartItems(DateTime olderThan)
        {
            olderThan = DateTimeHelper.ConvertToUtcTime(olderThan);

            DBProviderManager<DBShoppingCartProvider>.Provider.DeleteExpiredShoppingCartItems(olderThan);
        }

        /// <summary>
        /// Deletes a shopping cart item
        /// </summary>
        /// <param name="shoppingCartItemId">The shopping cart item identifier</param>
        /// <param name="resetCheckoutData">A value indicating whether to reset checkout data</param>
        public static void DeleteShoppingCartItem(int shoppingCartItemId, bool resetCheckoutData)
        {
            if (resetCheckoutData)
            {
                if (NopContext.Current.Session != null)
                {
                    CustomerManager.ResetCheckoutData(NopContext.Current.Session.CustomerId, false);
                }
            }

            var shoppingCartItem = GetShoppingCartItemById(shoppingCartItemId);
            if (shoppingCartItem != null)
            {
                if (shoppingCartItem.ShoppingCartType == ShoppingCartTypeEnum.ShoppingCart)
                {
                    CustomerActivityManager.InsertActivity(
                        "RemoveFromShoppingCart",
                        LocalizationManager.GetLocaleResourceString("ActivityLog.RemoveFromShoppingCart"),
                        shoppingCartItem.ProductVariant.FullProductName);
                }

                DBProviderManager<DBShoppingCartProvider>.Provider.DeleteShoppingCartItem(shoppingCartItemId);
            }
        }

        /// <summary>
        /// Gets a shopping cart by customer session GUId
        /// </summary>
        /// <param name="shoppingCartType">Shopping cart type</param>
        /// <param name="customerSessionGuid">The customer session identifier</param>
        /// <returns>Cart</returns>
        public static ShoppingCart GetShoppingCartByCustomerSessionGuid(ShoppingCartTypeEnum shoppingCartType, 
            Guid customerSessionGuid)
        {
            var dbCollection = DBProviderManager<DBShoppingCartProvider>.Provider.GetShoppingCartByCustomerSessionGuid((int)shoppingCartType,
                customerSessionGuid);
            var shoppingCart = DBMapping(dbCollection);
            return shoppingCart;
        }

        /// <summary>
        /// Gets a shopping cart item
        /// </summary>
        /// <param name="shoppingCartItemId">The shopping cart item identifier</param>
        /// <returns>Shopping cart item</returns>
        public static ShoppingCartItem GetShoppingCartItemById(int shoppingCartItemId)
        {
            if (shoppingCartItemId == 0)
                return null;

            var dbItem = DBProviderManager<DBShoppingCartProvider>.Provider.GetShoppingCartItemById(shoppingCartItemId);
            var shoppingCartItem = DBMapping(dbItem);
            return shoppingCartItem;
        }

        /// <summary>
        /// Inserts a shopping cart item
        /// </summary>
        /// <param name="shoppingCartType">The shopping cart type</param>
        /// <param name="customerSessionGuid">The customer session identifier</param>
        /// <param name="productVariantId">The product variant identifier</param>
        /// <param name="attributesXml">The product variant attributes</param>
        /// <param name="customerEnteredPrice">The price enter by a customer</param>
        /// <param name="quantity">The quantity</param>
        /// <param name="createdOn">The date and time of instance creation</param>
        /// <param name="updatedOn">The date and time of instance update</param>
        /// <returns>Shopping cart item</returns>
        internal static ShoppingCartItem InsertShoppingCartItem(ShoppingCartTypeEnum shoppingCartType,
            Guid customerSessionGuid, int productVariantId, string attributesXml,
            decimal customerEnteredPrice, int quantity,
            DateTime createdOn, DateTime updatedOn)
        {
            if (attributesXml == null)
                attributesXml = string.Empty;

            createdOn = DateTimeHelper.ConvertToUtcTime(createdOn);
            updatedOn = DateTimeHelper.ConvertToUtcTime(updatedOn);

            var dbItem = DBProviderManager<DBShoppingCartProvider>.Provider.InsertShoppingCartItem((int)shoppingCartType,
                customerSessionGuid, productVariantId, attributesXml,
                customerEnteredPrice, quantity, createdOn, updatedOn);

            var shoppingCartItem = DBMapping(dbItem);
            if (shoppingCartItem != null)
            {
                if (shoppingCartItem.ShoppingCartType == ShoppingCartTypeEnum.ShoppingCart)
                {
                    CustomerActivityManager.InsertActivity(
                        "AddToShoppingCart",
                        LocalizationManager.GetLocaleResourceString("ActivityLog.AddToShoppingCart"),
                        shoppingCartItem.ProductVariant.FullProductName);
                }
            }

            return shoppingCartItem;
        }

        /// <summary>
        /// Updates the shopping cart item
        /// </summary>
        /// <param name="shoppingCartItemId">The shopping cart item identifier</param>
        /// <param name="shoppingCartType">The shopping cart type</param>
        /// <param name="customerSessionGuid">The customer session identifier</param>
        /// <param name="productVariantId">The product variant identifier</param>
        /// <param name="attributesXml">The product variant attributes</param>
        /// <param name="customerEnteredPrice">The price enter by a customer</param>
        /// <param name="quantity">The quantity</param>
        /// <param name="createdOn">The date and time of instance creation</param>
        /// <param name="updatedOn">The date and time of instance update</param>
        /// <returns>Shopping cart item</returns>
        internal static ShoppingCartItem UpdateShoppingCartItem(int shoppingCartItemId,
            ShoppingCartTypeEnum shoppingCartType, Guid customerSessionGuid,
            int productVariantId, string attributesXml, decimal customerEnteredPrice,
            int quantity, DateTime createdOn, DateTime updatedOn)
        {
            if (shoppingCartItemId == 0)
                return null;

            if (attributesXml == null)
                attributesXml = string.Empty;

            createdOn = DateTimeHelper.ConvertToUtcTime(createdOn);
            updatedOn = DateTimeHelper.ConvertToUtcTime(updatedOn);

            var dbItem = DBProviderManager<DBShoppingCartProvider>.Provider.UpdateShoppingCartItem(shoppingCartItemId,
                (int)shoppingCartType, customerSessionGuid, productVariantId, attributesXml,
                customerEnteredPrice, quantity, createdOn, updatedOn);

            var shoppingCartItem = DBMapping(dbItem);
            return shoppingCartItem;
        }

        /// <summary>
        /// Gets current user shopping cart
        /// </summary>
        /// <param name="shoppingCartType">Shopping cart type</param>
        /// <returns>Cart</returns>
        public static ShoppingCart GetCurrentShoppingCart(ShoppingCartTypeEnum shoppingCartType)
        {
            if (NopContext.Current.Session == null)
                return new ShoppingCart();
            var customerSessionGuid = NopContext.Current.Session.CustomerSessionGuid;
            return GetShoppingCartByCustomerSessionGuid(shoppingCartType, customerSessionGuid);
        }

        /// <summary>
        /// Gets shopping cart
        /// </summary>
        /// <param name="customerId">Customer identifier</param>
        /// <param name="shoppingCartType">Shopping cart type</param>
        /// <returns>Cart</returns>
        public static ShoppingCart GetCustomerShoppingCart(int customerId, 
            ShoppingCartTypeEnum shoppingCartType)
        {
            var customerSession = CustomerManager.GetCustomerSessionByCustomerId(customerId);
            if (customerSession == null)
                return new ShoppingCart();
            var customerSessionGuid = customerSession.CustomerSessionGuid;
            return GetShoppingCartByCustomerSessionGuid(shoppingCartType, customerSessionGuid);
        }
        
        #endregion

        #region Workflow/helper methods

        /// <summary>
        /// Gets shopping cart total
        /// </summary>
        /// <param name="cart">Cart</param>
        /// <param name="paymentMethodId">Payment method identifier</param>
        /// <param name="customer">Customer</param>
        /// <returns>Shopping cart total;Null if shopping cart total couldn't be calculated now</returns>
        public static decimal? GetShoppingCartTotal(ShoppingCart cart,
            int paymentMethodId, Customer customer)
        {
            bool useRewardPoints = false;
            if (customer != null)
                useRewardPoints = customer.UseRewardPointsDuringCheckout;
            return GetShoppingCartTotal(cart, paymentMethodId, customer, useRewardPoints);
        }

        /// <summary>
        /// Gets shopping cart total
        /// </summary>
        /// <param name="cart">Cart</param>
        /// <param name="paymentMethodId">Payment method identifier</param>
        /// <param name="customer">Customer</param>
        /// <param name="useRewardPoints">A value indicating whether to use reward points</param>
        /// <returns>Shopping cart total;Null if shopping cart total couldn't be calculated now</returns>
        public static decimal? GetShoppingCartTotal(ShoppingCart cart,
            int paymentMethodId, Customer customer, bool useRewardPoints)
        {
            int redeemedRewardPoints = 0;
            decimal redeemedRewardPointsAmount = decimal.Zero;
            List<AppliedGiftCard> appliedGiftCards = null;
            return GetShoppingCartTotal(cart, paymentMethodId, customer,
                out appliedGiftCards, useRewardPoints, 
                out redeemedRewardPoints, out redeemedRewardPointsAmount);
        }

        /// <summary>
        /// Gets shopping cart total
        /// </summary>
        /// <param name="cart">Cart</param>
        /// <param name="paymentMethodId">Payment method identifier</param>
        /// <param name="customer">Customer</param>
        /// <param name="appliedGiftCards">Applied gift cards</param>
        /// <param name="useRewardPoints">A value indicating whether to use reward points</param>
        /// <param name="redeemedRewardPoints">Reward points to redeem</param>
        /// <param name="redeemedRewardPointsAmount">Reward points amount in primary store currency to redeem</param>
        /// <returns>Shopping cart total;Null if shopping cart total couldn't be calculated now</returns>
        public static decimal? GetShoppingCartTotal(ShoppingCart cart,
            int paymentMethodId, Customer customer,
            out List<AppliedGiftCard> appliedGiftCards, bool useRewardPoints,
            out int redeemedRewardPoints, out decimal redeemedRewardPointsAmount)
        {
            string subTotalError = string.Empty;
            string shippingError = string.Empty;
            string paymentMethodAdditionalFeeError = string.Empty;
            string taxError = string.Empty;
            redeemedRewardPoints = 0;
            redeemedRewardPointsAmount = decimal.Zero;

            //subtotal without tax
            decimal subTotalDiscountBase = decimal.Zero;
            Discount appliedDiscount = null;
            decimal subtotalBaseWithoutPromo = decimal.Zero;
            decimal subtotalBaseWithPromo = decimal.Zero;
            subTotalError = ShoppingCartManager.GetShoppingCartSubTotal(cart,
                customer, out subTotalDiscountBase,
                out appliedDiscount, false,
                out subtotalBaseWithoutPromo, out subtotalBaseWithPromo);

            //shipping without tax
            decimal? shoppingCartShipping = ShippingManager.GetShoppingCartShippingTotal(cart, customer, false, ref shippingError);

            //payment method additional fee without tax
            decimal paymentMethodAdditionalFeeWithoutTax = decimal.Zero;
            if (paymentMethodId > 0)
            {
                decimal paymentMethodAdditionalFee = PaymentManager.GetAdditionalHandlingFee(paymentMethodId);
                paymentMethodAdditionalFeeWithoutTax = TaxManager.GetPaymentMethodAdditionalFee(paymentMethodAdditionalFee,
                    false, customer, ref paymentMethodAdditionalFeeError);
            }

            //tax
            decimal shoppingCartTax = TaxManager.GetTaxTotal(cart, paymentMethodId, customer, ref taxError);

            //order total
            decimal resultTemp = decimal.Zero;
            resultTemp += subtotalBaseWithPromo;
            if (shoppingCartShipping.HasValue)
            {
                resultTemp += shoppingCartShipping.Value;
            }
            resultTemp += paymentMethodAdditionalFeeWithoutTax;
            resultTemp += shoppingCartTax;
            resultTemp = Math.Round(resultTemp, 2);

            #region Gift Cards

            //let's apply gift cards now (gift cards that can be used)
            appliedGiftCards = new List<AppliedGiftCard>();
            var giftCards = GiftCardHelper.GetActiveGiftCards(customer);
            foreach (var gc in giftCards)
            {
                if (resultTemp > decimal.Zero)
                {
                    decimal remainingAmount = GiftCardHelper.GetGiftCardRemainingAmount(gc);
                    decimal amountCanBeUsed = decimal.Zero;
                    if (resultTemp > remainingAmount)
                        amountCanBeUsed = remainingAmount;
                    else
                        amountCanBeUsed = resultTemp;

                    //reduce subtotal
                    resultTemp -= amountCanBeUsed;

                    AppliedGiftCard appliedGiftCard = new AppliedGiftCard();
                    appliedGiftCard.GiftCardId = gc.GiftCardId;
                    appliedGiftCard.AmountCanBeUsed = amountCanBeUsed;
                    appliedGiftCards.Add(appliedGiftCard);
                }
            }

            #endregion

            if (resultTemp < decimal.Zero)
                resultTemp = decimal.Zero;
            resultTemp = Math.Round(resultTemp, 2);

            decimal? orderTotal = null;
            if (!String.IsNullOrEmpty(subTotalError) ||
                !String.IsNullOrEmpty(shippingError) ||
                !String.IsNullOrEmpty(paymentMethodAdditionalFeeError) ||
                !String.IsNullOrEmpty(taxError))
            {
                //return null if we have errors
                orderTotal = null;
                return orderTotal;
            }
            else
            {
                //return result if we have no errors
                orderTotal = resultTemp;
            }

            #region Reward points
            if (OrderManager.RewardPointsEnabled && useRewardPoints && customer != null)
            {
                int rewardPointsBalance = customer.RewardPointsBalance;
                decimal rewardPointsBalanceAmount = OrderManager.ConvertRewardPointsToAmount(rewardPointsBalance);
                if (orderTotal.HasValue && orderTotal.Value > decimal.Zero)
                {
                    if (orderTotal.Value > rewardPointsBalanceAmount)
                    {
                        redeemedRewardPoints = rewardPointsBalance;
                        redeemedRewardPointsAmount = rewardPointsBalanceAmount;
                    }
                    else
                    {
                        redeemedRewardPointsAmount = orderTotal.Value;
                        redeemedRewardPoints = OrderManager.ConvertAmountToRewardPoints(redeemedRewardPointsAmount);
                    }
                }
            }
            #endregion

            if (orderTotal.HasValue)
            {
                orderTotal = orderTotal.Value - redeemedRewardPointsAmount;
                orderTotal = Math.Round(orderTotal.Value, 2);
                return orderTotal;
            }
            else
                return null;
        }

        /// <summary>
        /// Gets shopping cart subtotal
        /// </summary>
        /// <param name="cart">Cart</param>
        /// <param name="customer">Customer</param>
        /// <param name="discountAmount">Subtotal discount amount</param>
        /// <param name="appliedDiscount">Applied discount</param>
        /// <param name="subtotalWithoutPromo">Sub total without promo (discounts, gift cards)</param>
        /// <param name="subtotalWithPromo">Sub total with promo (discounts, gift cards)</param>
        /// <returns>Error</returns>
        public static string GetShoppingCartSubTotal(ShoppingCart cart, Customer customer,
            out decimal discountAmount, out Discount appliedDiscount,
            out decimal subtotalWithoutPromo, out decimal subtotalWithPromo)
        {
            bool includingTax = false;
            switch (NopContext.Current.TaxDisplayType)
            {
                case TaxDisplayTypeEnum.ExcludingTax:
                    includingTax = false;
                    break;
                case TaxDisplayTypeEnum.IncludingTax:
                    includingTax = true;
                    break;
            }
            return GetShoppingCartSubTotal(cart, customer, out discountAmount,
                out appliedDiscount, includingTax,
                out subtotalWithoutPromo, out subtotalWithPromo);
        }

        /// <summary>
        /// Gets shopping cart subtotal
        /// </summary>
        /// <param name="cart">Cart</param>
        /// <param name="customer">Customer</param>
        /// <param name="discountAmount">Subtotal discount amount</param>
        /// <param name="appliedDiscount">Applied discount</param>
        /// <param name="includingTax">A value indicating whether calculated price should include tax</param>
        /// <param name="subtotalWithoutPromo">Sub total without promo (discounts, gift cards)</param>
        /// <param name="subtotalWithPromo">Sub total with promo (discounts, gift cards)</param>
        /// <returns>Error</returns>
        public static string GetShoppingCartSubTotal(ShoppingCart cart, Customer customer,
            out decimal discountAmount, out Discount appliedDiscount, bool includingTax,
            out decimal subtotalWithoutPromo, out decimal subtotalWithPromo)
        {
            string error = string.Empty;

            //sub totals without discount and gift cards
            decimal subTotalExclTaxWithoutDiscount = decimal.Zero;
            decimal subTotalInclTaxWithoutDiscount = decimal.Zero;
            foreach (var shoppingCartItem in cart)
            {
                string error2 = string.Empty;
                decimal sciSubTotal = PriceHelper.GetSubTotal(shoppingCartItem, customer, true);
                subTotalExclTaxWithoutDiscount += TaxManager.GetPrice(shoppingCartItem.ProductVariant, sciSubTotal, false, customer, ref error2);
                if (!String.IsNullOrEmpty(error2))
                {
                    error = error2;
                }
                subTotalInclTaxWithoutDiscount += TaxManager.GetPrice(shoppingCartItem.ProductVariant, sciSubTotal, true, customer, ref error2);
                if (!String.IsNullOrEmpty(error2))
                {
                    error = error2;
                }
            }

            //checkout attributes
            if (customer != null)
            {
                var caValues = CheckoutAttributeHelper.ParseCheckoutAttributeValues(customer.CheckoutAttributes);
                foreach (var caValue in caValues)
                {
                    string error3 = string.Empty;
                    subTotalExclTaxWithoutDiscount += TaxManager.GetCheckoutAttributePrice(caValue, false, customer, ref error3);
                    if (!String.IsNullOrEmpty(error3))
                    {
                        error = error3;
                    }
                    subTotalInclTaxWithoutDiscount += TaxManager.GetCheckoutAttributePrice(caValue, true, customer, ref error3);
                    if (!String.IsNullOrEmpty(error3))
                    {
                        error = error3;
                    }
                }
            }

            if (includingTax)
                subtotalWithoutPromo = subTotalInclTaxWithoutDiscount;
            else
                subtotalWithoutPromo = subTotalExclTaxWithoutDiscount;
            

            #region Discounts
            //Discount amount (excl tax)
            //We calculate discount amount on subtotal excl tax
            //This type of discounts [Assigned to whole order] is not taxable
            discountAmount = GetOrderDiscount(customer, subTotalExclTaxWithoutDiscount, out appliedDiscount);

            //sub totals with discount
            decimal subTotalWithDiscount = decimal.Zero;
            if (includingTax)
            {
                if (subTotalInclTaxWithoutDiscount < discountAmount)
                    discountAmount = subTotalInclTaxWithoutDiscount;

                subTotalWithDiscount = subTotalInclTaxWithoutDiscount - discountAmount;
            }
            else
            {
                if (subTotalExclTaxWithoutDiscount < discountAmount)
                    discountAmount = subTotalExclTaxWithoutDiscount;

                subTotalWithDiscount = subTotalExclTaxWithoutDiscount - discountAmount;
            }

            if (subTotalWithDiscount < decimal.Zero)
                subTotalWithDiscount = decimal.Zero;
            subTotalWithDiscount = Math.Round(subTotalWithDiscount, 2);

            #endregion

            subtotalWithPromo = subTotalWithDiscount;
            if (subtotalWithPromo < decimal.Zero)
                subtotalWithPromo = decimal.Zero;
            subtotalWithPromo = Math.Round(subtotalWithPromo, 2);

            return error;
        }

        /// <summary>
        /// Gets an order discount
        /// </summary>
        /// <param name="customer">Customer</param>
        /// <param name="orderSubTotal">Order subtotal</param>
        /// <param name="appliedDiscount">Applied discount</param>
        /// <returns>Order discount</returns>
        public static decimal GetOrderDiscount(Customer customer, 
            decimal orderSubTotal, out Discount appliedDiscount)
        {
            decimal subTotalDiscountAmount = decimal.Zero;

            string customerCouponCode = string.Empty;
            if (customer != null)
                customerCouponCode = customer.LastAppliedCouponCode;

            var allDiscounts = DiscountManager.GetAllDiscounts(DiscountTypeEnum.AssignedToOrderSubTotal);
            var allowedDiscounts = new DiscountCollection();
            foreach (var _discount in allDiscounts)
            {
                if (_discount.IsActive(customerCouponCode) &&
                    _discount.DiscountType == DiscountTypeEnum.AssignedToOrderSubTotal &&
                    !allowedDiscounts.ContainsDiscount(_discount.Name))
                {
                    //discount requirements
                    if (_discount.CheckDiscountRequirements(customer)
                        && _discount.CheckDiscountLimitations(customer))
                    {
                        allowedDiscounts.Add(_discount);
                    }
                }
            }

            appliedDiscount = DiscountManager.GetPreferredDiscount(allowedDiscounts, orderSubTotal);
            if (appliedDiscount != null)
            {
                subTotalDiscountAmount = appliedDiscount.GetDiscountAmount(orderSubTotal);
            }

            if (subTotalDiscountAmount < decimal.Zero)
                subTotalDiscountAmount = decimal.Zero;

            subTotalDiscountAmount = Math.Round(subTotalDiscountAmount, 2);

            return subTotalDiscountAmount;
        }
              
        /// <summary>
        /// Validates shopping cart item
        /// </summary>
        /// <param name="shoppingCartType">Shopping cart type</param>
        /// <param name="productVariantId">Product variant identifier</param>
        /// <param name="selectedAttributes">Selected attributes</param>
        /// <param name="customerEnteredPrice">Customer entered price</param>
        /// <param name="quantity">Quantity</param>
        /// <returns>Warnings</returns>
        public static List<string> GetShoppingCartItemWarnings(ShoppingCartTypeEnum shoppingCartType,
            int productVariantId, string selectedAttributes, decimal customerEnteredPrice, 
            int quantity)
        {
            var warnings = new List<string>();
            var productVariant = ProductManager.GetProductVariantById(productVariantId);
            if (productVariant == null)
            {
                warnings.Add(string.Format("Product variant (Id={0}) can not be loaded", productVariantId));
                return warnings;
            }

            var product = productVariant.Product;
            if (product == null)
            {
                warnings.Add(string.Format("Product (Id={0}) can not be loaded", productVariant.ProductId));
                return warnings;
            }

            if (product.Deleted || productVariant.Deleted)
            {
                warnings.Add("Product is deleted");
                return warnings;
            }

            if (!product.Published || !productVariant.Published)
            {
                warnings.Add("Product is not published");
            }

            if (productVariant.DisableBuyButton)
            {
                warnings.Add("Buying is disabled");
            }

            if (productVariant.CustomerEntersPrice)
            {
                if (customerEnteredPrice < productVariant.MinimumCustomerEnteredPrice ||
                    customerEnteredPrice > productVariant.MaximumCustomerEnteredPrice)
                {
                    int minimumCustomerEnteredPrice = Convert.ToInt32(Math.Ceiling(CurrencyManager.ConvertCurrency(productVariant.MinimumCustomerEnteredPrice, CurrencyManager.PrimaryStoreCurrency, NopContext.Current.WorkingCurrency)));
                    int maximumCustomerEnteredPrice = Convert.ToInt32(Math.Truncate(CurrencyManager.ConvertCurrency(productVariant.MaximumCustomerEnteredPrice, CurrencyManager.PrimaryStoreCurrency, NopContext.Current.WorkingCurrency)));
                
                    warnings.Add(string.Format(LocalizationManager.GetLocaleResourceString("ShoppingCart.CustomerEnteredPrice.RangeError"),
                        minimumCustomerEnteredPrice, maximumCustomerEnteredPrice));
                }
            }

            if (quantity < productVariant.OrderMinimumQuantity)
            {
                warnings.Add(string.Format(LocalizationManager.GetLocaleResourceString("ShoppingCart.MinimumQuantity"), productVariant.OrderMinimumQuantity));
            }

            if (quantity > productVariant.OrderMaximumQuantity)
            {
                warnings.Add(string.Format(LocalizationManager.GetLocaleResourceString("ShoppingCart.MaximumQuantity"), productVariant.OrderMaximumQuantity));
            }

            switch ((ManageInventoryMethodEnum)productVariant.ManageInventory)
            {
                case ManageInventoryMethodEnum.DontManageStock:
                    {
                    }
                    break;
                case ManageInventoryMethodEnum.ManageStock:
                    {
                        if (!productVariant.AllowOutOfStockOrders)
                        {
                            if (productVariant.StockQuantity < quantity)
                            {
                                int maximumQuantityCanBeAdded = productVariant.StockQuantity;
                                if (maximumQuantityCanBeAdded <= 0)
                                    warnings.Add(LocalizationManager.GetLocaleResourceString("ShoppingCart.OutOfStock"));
                                else
                                    warnings.Add(string.Format(LocalizationManager.GetLocaleResourceString("ShoppingCart.QuantityExceedsStock"), maximumQuantityCanBeAdded));
                            }
                        }
                    }
                    break;
                case ManageInventoryMethodEnum.ManageStockByAttributes:
                    {
                        var combination = ProductAttributeManager.FindProductVariantAttributeCombination(productVariant.ProductVariantId, selectedAttributes);
                        if (combination != null)
                        {
                            if (!combination.AllowOutOfStockOrders)
                            {
                                if (combination.StockQuantity < quantity)
                                {
                                    int maximumQuantityCanBeAdded = combination.StockQuantity;
                                    if (maximumQuantityCanBeAdded <= 0)
                                        warnings.Add(LocalizationManager.GetLocaleResourceString("ShoppingCart.OutOfStock"));
                                    else
                                        warnings.Add(string.Format(LocalizationManager.GetLocaleResourceString("ShoppingCart.QuantityExceedsStock"), maximumQuantityCanBeAdded));
                                }
                            }
                        }
                    }
                    break;
                default:
                    break;
            }

            if (productVariant.AvailableStartDateTime.HasValue)
            {
                DateTime now = DateTimeHelper.ConvertToUtcTime(DateTime.Now);
                if (productVariant.AvailableStartDateTime.Value.CompareTo(now) > 0)
                {
                    warnings.Add("Product is not available");
                }
            }
            else if (productVariant.AvailableEndDateTime.HasValue)
            {
                DateTime now = DateTimeHelper.ConvertToUtcTime(DateTime.Now);
                if (productVariant.AvailableEndDateTime.Value.CompareTo(now) < 0)
                {
                    warnings.Add("Product is not available");
                }
            }

            //selected attributes
            warnings.AddRange(GetShoppingCartItemAttributeWarnings(shoppingCartType, productVariantId, selectedAttributes, quantity));

            //gift cards
            warnings.AddRange(GetShoppingCartItemGiftCardWarnings(shoppingCartType, productVariantId, selectedAttributes));

            return warnings;
        }

        /// <summary>
        /// Validates shopping cart item attributes
        /// </summary>
        /// <param name="shoppingCartType">Shopping cart type</param>
        /// <param name="productVariantId">Product variant identifier</param>
        /// <param name="selectedAttributes">Selected attributes</param>
        /// <param name="quantity">Quantity</param>
        /// <returns>Warnings</returns>
        public static List<string> GetShoppingCartItemAttributeWarnings(ShoppingCartTypeEnum shoppingCartType,
            int productVariantId, string selectedAttributes, int quantity)
        {
            return GetShoppingCartItemAttributeWarnings(shoppingCartType,
                productVariantId, selectedAttributes, quantity, true);
        }

        /// <summary>
        /// Validates shopping cart item attributes
        /// </summary>
        /// <param name="shoppingCartType">Shopping cart type</param>
        /// <param name="productVariantId">Product variant identifier</param>
        /// <param name="selectedAttributes">Selected attributes</param>
        /// <param name="quantity">Quantity</param>
        /// <param name="validateQuantity">Value indicating whether to validation quantity</param>
        /// <returns>Warnings</returns>
        public static List<string> GetShoppingCartItemAttributeWarnings(ShoppingCartTypeEnum shoppingCartType,
            int productVariantId, string selectedAttributes, int quantity, bool validateQuantity)
        {
            var warnings = new List<string>();
            var productVariant = ProductManager.GetProductVariantById(productVariantId);
            if (productVariant == null)
            {
                warnings.Add(string.Format("Product variant (Id={0}) can not be loaded", productVariantId));
                return warnings;
            }

            //selected attributes
            var pva1Collection = ProductAttributeHelper.ParseProductVariantAttributes(selectedAttributes);
            foreach (var pva1 in pva1Collection)
            {
                var pv1 = pva1.ProductVariant;
                if (pv1 != null)
                {
                    if (pv1.ProductVariantId != productVariant.ProductVariantId)
                    {
                        warnings.Add("Attribute error");
                    }
                }
                else
                {
                    warnings.Add("Attribute error");
                    return warnings;
                }
            }

            //existing product attributes
            var pva2Collection = productVariant.ProductVariantAttributes;
            foreach (var pva2 in pva2Collection)
            {
                if (pva2.IsRequired)
                {
                    bool found = false;
                    //selected product attributes
                    foreach (var pva1 in pva1Collection)
                    {
                        if (pva1.ProductVariantAttributeId == pva2.ProductVariantAttributeId)
                        {
                            var pvaValuesStr = ProductAttributeHelper.ParseValues(selectedAttributes, pva1.ProductVariantAttributeId);
                            foreach (string str1 in pvaValuesStr)
                            {
                                if (!String.IsNullOrEmpty(str1.Trim()))
                                {
                                    found = true;
                                    break;
                                }
                            }
                        }
                    }

                    //if not found
                    if (!found)
                    {
                        if (!string.IsNullOrEmpty(pva2.TextPrompt))
                        {
                            warnings.Add(pva2.TextPrompt);
                        }
                        else
                        {
                            warnings.Add(string.Format(LocalizationManager.GetLocaleResourceString("ShoppingCart.SelectAttribute"), pva2.ProductAttribute.Name));
                        }
                    }
                }
            }

            return warnings;
        }

        /// <summary>
        /// Validates shopping cart item (gift card)
        /// </summary>
        /// <param name="shoppingCartType">Shopping cart type</param>
        /// <param name="productVariantId">Product variant identifier</param>
        /// <param name="selectedAttributes">Selected attributes</param>
        /// <returns>Warnings</returns>
        public static List<string> GetShoppingCartItemGiftCardWarnings(ShoppingCartTypeEnum shoppingCartType,
            int productVariantId, string selectedAttributes)
        {
            var warnings = new List<string>();
            var productVariant = ProductManager.GetProductVariantById(productVariantId);
            if (productVariant == null)
            {
                warnings.Add(string.Format("Product variant (Id={0}) can not be loaded", productVariantId));
                return warnings;
            }

            //gift cards
            if (productVariant.IsGiftCard)
            {
                string giftCardRecipientName = string.Empty;
                string giftCardRecipientEmail = string.Empty;
                string giftCardSenderName = string.Empty;
                string giftCardSenderEmail = string.Empty;
                string giftCardMessage = string.Empty;
                ProductAttributeHelper.GetGiftCardAttribute(selectedAttributes,
                    out giftCardRecipientName, out giftCardRecipientEmail,
                    out giftCardSenderName, out giftCardSenderEmail, out giftCardMessage);

                if (String.IsNullOrEmpty(giftCardRecipientName))
                    warnings.Add(LocalizationManager.GetLocaleResourceString("ShoppingCartWarning.RecipientNameError"));

                if (String.IsNullOrEmpty(giftCardRecipientEmail) || !CommonHelper.IsValidEmail(giftCardRecipientEmail))
                    warnings.Add(LocalizationManager.GetLocaleResourceString("ShoppingCartWarning.RecipientEmailError"));

                if (String.IsNullOrEmpty(giftCardSenderName))
                    warnings.Add(LocalizationManager.GetLocaleResourceString("ShoppingCartWarning.SenderNameError"));

                if (String.IsNullOrEmpty(giftCardSenderEmail) || !CommonHelper.IsValidEmail(giftCardSenderEmail))
                    warnings.Add(LocalizationManager.GetLocaleResourceString("ShoppingCartWarning.SenderEmailError"));
            }

            return warnings;
        }

        /// <summary>
        /// Validates whether this shopping cart is valid
        /// </summary>
        /// <param name="shoppingCart">Shopping cart</param>
        /// <param name="checkoutAttributes">Checkout attributes</param>
        /// <param name="validateCheckoutAttributes">A value indicating whether to validate checkout attributes</param>
        /// <returns>Warnings</returns>
        public static List<string> GetShoppingCartWarnings(ShoppingCart shoppingCart, string checkoutAttributes, bool validateCheckoutAttributes)
        {
            var warnings = new List<string>();

            bool hasStandartProducts = false;
            bool hasRecurringProducts = false;
            int cycleLength = 0;
            int cyclePeriod = 0;
            int totalCycles = 0;

            foreach (var sci in shoppingCart)
            {
                var productVariant = sci.ProductVariant;
                if (productVariant == null)
                {
                    warnings.Add(string.Format("Product variant (Id={0}) can not be loaded", sci.ProductVariantId));
                    return warnings;
                }

                if (productVariant.IsRecurring)
                {
                    hasRecurringProducts = true;
                }
                else
                {
                    hasStandartProducts = true;
                }
            }

            if (hasStandartProducts && hasRecurringProducts)
            {
                warnings.Add(LocalizationManager.GetLocaleResourceString("ShoppingCart.CannotMixStandardAndAutoshipProducts"));
            }

            if (hasRecurringProducts)
            {
                string cyclesError = GetReccuringCycleInfo(shoppingCart, out cycleLength, out cyclePeriod, out totalCycles);
                if (!string.IsNullOrEmpty(cyclesError))
                {
                    warnings.Add(cyclesError);
                    return warnings;
                }
            }

            //validate checkout attributes
            if (validateCheckoutAttributes)
            {
                //selected attributes
                var ca1Collection = CheckoutAttributeHelper.ParseCheckoutAttributes(checkoutAttributes);

                //existing checkout attributes
                bool shoppingCartRequiresShipping = ShippingManager.ShoppingCartRequiresShipping(shoppingCart);
                var ca2Collection = CheckoutAttributeManager.GetAllCheckoutAttributes(!shoppingCartRequiresShipping);
                foreach (var ca2 in ca2Collection)
                {
                    if (ca2.IsRequired)
                    {
                        bool found = false;
                        //selected checkout attributes
                        foreach (var ca1 in ca1Collection)
                        {
                            if (ca1.CheckoutAttributeId == ca2.CheckoutAttributeId)
                            {
                                var caValuesStr = CheckoutAttributeHelper.ParseValues(checkoutAttributes, ca1.CheckoutAttributeId);
                                foreach (string str1 in caValuesStr)
                                {
                                    if (!String.IsNullOrEmpty(str1.Trim()))
                                    {
                                        found = true;
                                        break;
                                    }
                                }
                            }
                        }

                        //if not found
                        if (!found)
                        {
                            if (!string.IsNullOrEmpty(ca2.TextPrompt))
                            {
                                warnings.Add(ca2.TextPrompt);
                            }
                            else
                            {
                                warnings.Add(string.Format(LocalizationManager.GetLocaleResourceString("ShoppingCart.SelectAttribute"), ca2.Name));
                            }
                        }
                    }
                }
            }

            return warnings;
        }

        /// <summary>
        /// Validates whether this shopping cart is valid
        /// </summary>
        /// <param name="shoppingCart">Shopping cart</param>
        /// <param name="cycleLength">Cycle length</param>
        /// <param name="cyclePeriod">Cycle period</param>
        /// <param name="totalCycles">Toital cycles</param>
        /// <returns>Error</returns>
        public static string GetReccuringCycleInfo(ShoppingCart shoppingCart, 
            out int cycleLength, out int cyclePeriod, out int totalCycles)
        {
            string error = string.Empty;

            cycleLength = 0;
            cyclePeriod = 0;
            totalCycles = 0;

            int? _cycleLength = null;
            int? _cyclePeriod = null;
            int? _totalCycles = null;

            foreach (var sci in shoppingCart)
            {
                var productVariant = sci.ProductVariant;
                if (productVariant == null)
                {
                    throw new NopException(string.Format("Product variant (Id={0}) can not be loaded", sci.ProductVariantId));
                }

                if (productVariant.IsRecurring)
                {
                    //cycle length
                    if (_cycleLength.HasValue && _cycleLength.Value != productVariant.CycleLength)
                    {
                        error = LocalizationManager.GetLocaleResourceString("ShoppingCart.ConflictingShipmentSchedules");
                        return error;
                    }
                    else
                    {
                        _cycleLength = productVariant.CycleLength;
                    }

                    //cycle period
                    if (_cyclePeriod.HasValue && _cyclePeriod.Value != productVariant.CyclePeriod)
                    {
                        error = LocalizationManager.GetLocaleResourceString("ShoppingCart.ConflictingShipmentSchedules");
                        return error;
                    }
                    else
                    {
                        _cyclePeriod = productVariant.CyclePeriod;
                    }

                    //total cycles
                    if (_totalCycles.HasValue && _totalCycles.Value != productVariant.TotalCycles)
                    {
                        error = LocalizationManager.GetLocaleResourceString("ShoppingCart.ConflictingShipmentSchedules");
                        return error;
                    }
                    else
                    {
                        _totalCycles = productVariant.TotalCycles;
                    }
                }
            }

            if (!_cycleLength.HasValue || !_cyclePeriod.HasValue || !_totalCycles.HasValue)
            {
                error = "No recurring products";
            }
            else
            {
                cycleLength = _cycleLength.Value;
                cyclePeriod = _cyclePeriod.Value;
                totalCycles = _totalCycles.Value;
            }

            return error;
        }

        /// <summary>
        /// Add a product variant to shopping cart
        /// </summary>
        /// <param name="shoppingCartType">Shopping cart type</param>
        /// <param name="productVariantId">Product variant identifier</param>
        /// <param name="selectedAttributes">Selected attributes</param>
        /// <param name="customerEnteredPrice">The price enter by a customer</param>
        /// <param name="quantity">Quantity</param>
        /// <returns>Warnings</returns>
        public static List<string> AddToCart(ShoppingCartTypeEnum shoppingCartType,
            int productVariantId, string selectedAttributes, 
            decimal customerEnteredPrice, int quantity)
        {
            var warnings = new List<string>();
            if (shoppingCartType == ShoppingCartTypeEnum.Wishlist && !SettingManager.GetSettingValueBoolean("Common.EnableWishlist"))
                return warnings;

            if (NopContext.Current.Session == null)
                NopContext.Current.Session = NopContext.Current.GetSession(true);

            var customerSessionGuid = NopContext.Current.Session.CustomerSessionGuid;

            CustomerManager.ResetCheckoutData(NopContext.Current.Session.CustomerId, false);

            var cart = GetShoppingCartByCustomerSessionGuid(shoppingCartType, customerSessionGuid);
            ShoppingCartItem shoppingCartItem = null;
            
            foreach (var _shoppingCartItem in cart)
            {
                if (_shoppingCartItem.ProductVariantId == productVariantId)
                {
                    //attributes
                    bool attributesEqual = ProductAttributeHelper.AreProductAttributesEqual(_shoppingCartItem.AttributesXml, selectedAttributes);

                    //gift cards
                    bool giftCardInfoSame = true;
                    if (_shoppingCartItem.ProductVariant.IsGiftCard)
                    {
                        string giftCardRecipientName1 = string.Empty;
                        string giftCardRecipientEmail1 = string.Empty;
                        string giftCardSenderName1 = string.Empty;
                        string giftCardSenderEmail1 = string.Empty;
                        string giftCardMessage1 = string.Empty;
                        ProductAttributeHelper.GetGiftCardAttribute(selectedAttributes,
                            out giftCardRecipientName1, out giftCardRecipientEmail1,
                            out giftCardSenderName1, out giftCardSenderEmail1, out giftCardMessage1);

                        string giftCardRecipientName2 = string.Empty;
                        string giftCardRecipientEmail2 = string.Empty;
                        string giftCardSenderName2 = string.Empty;
                        string giftCardSenderEmail2 = string.Empty;
                        string giftCardMessage2 = string.Empty;
                        ProductAttributeHelper.GetGiftCardAttribute(_shoppingCartItem.AttributesXml,
                            out giftCardRecipientName2, out giftCardRecipientEmail2,
                            out giftCardSenderName2, out giftCardSenderEmail2, out giftCardMessage2);


                        if (giftCardRecipientName1.ToLowerInvariant() != giftCardRecipientName2.ToLowerInvariant() ||
                            giftCardSenderName1.ToLowerInvariant() != giftCardSenderName2.ToLowerInvariant())
                            giftCardInfoSame = false;
                    }

                    //price is the same (for products which requires customers to enter a price)
                    bool customerEnteredPricesEqual = true;
                    if (_shoppingCartItem.ProductVariant.CustomerEntersPrice)
                    {
                        customerEnteredPricesEqual = Math.Round(_shoppingCartItem.CustomerEnteredPrice, 2) == Math.Round(customerEnteredPrice, 2);
                    }

                    if (attributesEqual &&
                        giftCardInfoSame &&
                        customerEnteredPricesEqual)
                        shoppingCartItem = _shoppingCartItem;
                }
            }

            DateTime now = DateTime.Now;
            if (shoppingCartItem != null)
            {
                int newQuantity = shoppingCartItem.Quantity + quantity;
                warnings.AddRange(GetShoppingCartItemWarnings(shoppingCartType, productVariantId, 
                    selectedAttributes, customerEnteredPrice, newQuantity));

                if (warnings.Count == 0)
                {
                    UpdateShoppingCartItem(shoppingCartItem.ShoppingCartItemId, 
                        shoppingCartType,
                        customerSessionGuid, 
                        productVariantId, 
                        selectedAttributes,
                        shoppingCartItem.CustomerEnteredPrice,
                        newQuantity,
                        shoppingCartItem.CreatedOn, 
                        now);
                }
            }
            else
            {
                warnings.AddRange(GetShoppingCartItemWarnings(shoppingCartType, productVariantId, 
                    selectedAttributes, customerEnteredPrice, quantity));
                if (warnings.Count == 0)
                {
                    //maximum items validation
                    if (shoppingCartType == ShoppingCartTypeEnum.ShoppingCart)
                    {
                        if (cart.Count >= SettingManager.GetSettingValueInteger("Common.MaximumShoppingCartItems", 1000))
                            return warnings;
                    }
                    else if (shoppingCartType == ShoppingCartTypeEnum.Wishlist)
                    {
                        if (cart.Count >= SettingManager.GetSettingValueInteger("Common.MaximumWishlistItems", 1000))
                            return warnings;
                    }

                    //insert item
                    InsertShoppingCartItem(shoppingCartType,
                        customerSessionGuid, 
                        productVariantId, 
                        selectedAttributes,
                        customerEnteredPrice,
                        quantity, 
                        now, 
                        now);
                }
            }

            return warnings;
        }

        /// <summary>
        /// Updates the shopping cart item
        /// </summary>
        /// <param name="shoppingCartItemId">Shopping cart item identifier</param>
        /// <param name="newQuantity">New shopping cart item quantity</param>
        /// <param name="resetCheckoutData">A value indicating whether to reset checkout data</param>
        /// <returns>Warnings</returns>
        public static List<string> UpdateCart(int shoppingCartItemId, int newQuantity,
            bool resetCheckoutData)
        {
            var warnings = new List<string>();

            if (NopContext.Current.Session == null)
                return warnings;

            var shoppingCartItem = GetShoppingCartItemById(shoppingCartItemId);
            if (shoppingCartItem != null)
            {
                if (resetCheckoutData)
                {
                    CustomerManager.ResetCheckoutData(NopContext.Current.Session.CustomerId, false);
                }
                if (newQuantity > 0)
                {
                    warnings.AddRange(GetShoppingCartItemWarnings(shoppingCartItem.ShoppingCartType,
                        shoppingCartItem.ProductVariantId, shoppingCartItem.AttributesXml, 
                        shoppingCartItem.CustomerEnteredPrice, newQuantity));
                    if (warnings.Count == 0)
                    {
                        UpdateShoppingCartItem(
                            shoppingCartItem.ShoppingCartItemId, 
                            shoppingCartItem.ShoppingCartType, 
                            shoppingCartItem.CustomerSessionGuid,
                            shoppingCartItem.ProductVariantId, 
                            shoppingCartItem.AttributesXml,
                            shoppingCartItem.CustomerEnteredPrice,
                            newQuantity, 
                            shoppingCartItem.CreatedOn, 
                            DateTime.Now);
                    }
                }
                else
                {
                    DeleteShoppingCartItem(shoppingCartItem.ShoppingCartItemId, resetCheckoutData);
                }
            }

            return warnings;
        }

        #endregion

        #endregion
    }
}
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.