Example #1
0
        public virtual async Task PrepareConditionAttributes(CheckoutAttributeModel model, CheckoutAttribute checkoutAttribute)
        {
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }

            //currenty any checkout attribute can have condition.
            model.ConditionAllowed = true;

            if (checkoutAttribute == null)
            {
                return;
            }

            var selectedAttribute = (await _checkoutAttributeParser.ParseCheckoutAttributes(checkoutAttribute.ConditionAttribute)).FirstOrDefault();
            var selectedValues    = await _checkoutAttributeParser.ParseCheckoutAttributeValues(checkoutAttribute.ConditionAttribute);

            model.ConditionModel = new ConditionModel()
            {
                EnableCondition     = checkoutAttribute.ConditionAttribute.Any(),
                SelectedAttributeId = selectedAttribute != null ? selectedAttribute.Id : "",
                ConditionAttributes = (await _checkoutAttributeService.GetAllCheckoutAttributes(ignorAcl: false))
                                      //ignore this attribute and non-combinable attributes
                                      .Where(x => x.Id != checkoutAttribute.Id && x.CanBeUsedAsCondition())
                                      .Select(x =>
                                              new AttributeConditionModel()
                {
                    Id   = x.Id,
                    Name = x.Name,
                    AttributeControlType = x.AttributeControlTypeId,
                    Values = x.CheckoutAttributeValues
                             .Select(v => new SelectListItem()
                    {
                        Text     = v.Name,
                        Value    = v.Id.ToString(),
                        Selected = selectedAttribute != null && selectedAttribute.Id == x.Id && selectedValues.Any(sv => sv.Id == v.Id)
                    }).ToList()
                }).ToList()
            };
        }
Example #2
0
        protected virtual void PrepareConditionAttributes(CheckoutAttributeModel model, CheckoutAttribute checkoutAttribute)
        {
            if (model == null)
            {
                throw new ArgumentNullException("model");
            }

            //currenty any checkout attribute can have condition.
            model.ConditionAllowed = true;

            if (checkoutAttribute == null)
            {
                return;
            }

            var selectedAttribute = _checkoutAttributeParser.ParseCheckoutAttributes(checkoutAttribute.ConditionAttributeXml).FirstOrDefault();
            var selectedValues    = _checkoutAttributeParser.ParseCheckoutAttributeValues(checkoutAttribute.ConditionAttributeXml);

            model.ConditionModel = new ConditionModel()
            {
                EnableCondition     = !string.IsNullOrEmpty(checkoutAttribute.ConditionAttributeXml),
                SelectedAttributeId = selectedAttribute != null ? selectedAttribute.Id : "",
                ConditionAttributes = _checkoutAttributeService.GetAllCheckoutAttributes()
                                      //ignore this attribute and non-combinable attributes
                                      .Where(x => x.Id != checkoutAttribute.Id && x.CanBeUsedAsCondition())
                                      .Select(x =>
                                              new AttributeConditionModel()
                {
                    Id   = x.Id,
                    Name = x.Name,
                    AttributeControlType = x.AttributeControlType,
                    Values = x.CheckoutAttributeValues         //_checkoutAttributeService.GetCheckoutAttributeValues(x.Id)
                             .Select(v => new SelectListItem()
                    {
                        Text     = v.Name,
                        Value    = v.Id.ToString(),
                        Selected = selectedAttribute != null && selectedAttribute.Id == x.Id && selectedValues.Any(sv => sv.Id == v.Id)
                    }).ToList()
                }).ToList()
            };
        }
        public OrderDto PrepareOrderDTO(Order order)
        {
            var orderDto = order.ToDto();

            var checkoutAttributes = _checkoutAttributeParser.ParseCheckoutAttributeValues(order.CheckoutAttributesXml);
            var commentAttribute   = checkoutAttributes.FirstOrDefault(x => x.Name.Equals("kommentar", StringComparison.InvariantCultureIgnoreCase));

            if (commentAttribute != null)
            {
                orderDto.Comment = commentAttribute.Name;
            }

            var customerDto = _customerApiService.GetCustomerById(order.Customer.Id);

            if (customerDto != null)
            {
                orderDto.Customer = customerDto.ToOrderCustomerDto();
            }

            return(orderDto);
        }
        /// <summary>
        /// Prepare condition attributes model
        /// </summary>
        /// <param name="model">Condition attributes model</param>
        /// <param name="checkoutAttribute">Checkout attribute</param>
        protected virtual void PrepareConditionAttributesModel(ConditionModel model, CheckoutAttribute checkoutAttribute)
        {
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }

            if (checkoutAttribute == null)
            {
                throw new ArgumentNullException(nameof(checkoutAttribute));
            }

            model.EnableCondition = !string.IsNullOrEmpty(checkoutAttribute.ConditionAttributeXml);

            //get selected checkout attribute
            var selectedAttribute = _checkoutAttributeParser.ParseCheckoutAttributes(checkoutAttribute.ConditionAttributeXml).FirstOrDefault();

            model.SelectedAttributeId = selectedAttribute?.Id ?? 0;

            //get selected checkout attribute values identifiers
            var selectedValuesIds = _checkoutAttributeParser
                                    .ParseCheckoutAttributeValues(checkoutAttribute.ConditionAttributeXml).Select(value => value.Id);

            //get available condition checkout attributes (ignore this attribute and non-combinable attributes)
            var availableConditionAttributes = _checkoutAttributeService.GetAllCheckoutAttributes()
                                               .Where(attribute => attribute.Id != checkoutAttribute.Id && attribute.CanBeUsedAsCondition());

            model.ConditionAttributes = availableConditionAttributes.Select(attribute => new AttributeConditionModel
            {
                Id   = attribute.Id,
                Name = attribute.Name,
                AttributeControlType = attribute.AttributeControlType,
                Values = _checkoutAttributeService.GetCheckoutAttributeValues(attribute.Id).Select(value => new SelectListItem
                {
                    Text     = value.Name,
                    Value    = value.Id.ToString(),
                    Selected = selectedAttribute?.Id == attribute.Id && selectedValuesIds.Contains(value.Id)
                }).ToList()
            }).ToList();
        }
Example #5
0
        public virtual decimal GetShoppingCartTotalWeight(IList <OrganizedShoppingCartItem> cart, bool includeFreeShippingProducts = true)
        {
            var totalWeight = decimal.Zero;
            var customer    = cart.GetCustomer();

            // shopping cart items
            foreach (var cartItem in cart)
            {
                var product = cartItem.Item.Product;
                if (product != null)
                {
                    if (!includeFreeShippingProducts && product.IsFreeShipping)
                    {
                        // skip product
                    }
                    else
                    {
                        totalWeight += GetShoppingCartItemTotalWeight(cartItem);
                    }
                }
            }

            // checkout attributes
            if (customer != null)
            {
                var checkoutAttributesXml = customer.GetAttribute <string>(SystemCustomerAttributeNames.CheckoutAttributes, _genericAttributeService);
                if (!String.IsNullOrEmpty(checkoutAttributesXml))
                {
                    var caValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(checkoutAttributesXml);
                    foreach (var caValue in caValues)
                    {
                        totalWeight += caValue.WeightAdjustment;
                    }
                }
            }

            return(totalWeight);
        }
Example #6
0
        /// <summary>
        /// Gets shopping cart weight
        /// </summary>
        /// <param name="request">Request</param>
        /// <param name="includeCheckoutAttributes">A value indicating whether we should calculate weights of selected checkotu attributes</param>
        /// <param name="ignoreFreeShippedItems">Whether to ignore the weight of the products marked as "Free shipping"</param>
        /// <returns>Total weight</returns>
        public virtual decimal GetTotalWeight(GetShippingOptionRequest request,
                                              bool includeCheckoutAttributes = true, bool ignoreFreeShippedItems = false)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            var totalWeight = decimal.Zero;

            //shopping cart items
            foreach (var packageItem in request.Items)
            {
                totalWeight += GetShoppingCartItemWeight(packageItem.ShoppingCartItem, ignoreFreeShippedItems) * packageItem.GetQuantity();
            }

            //checkout attributes
            if (request.Customer == null || !includeCheckoutAttributes)
            {
                return(totalWeight);
            }
            var checkoutAttributesXml = _genericAttributeService.GetAttribute <string>(request.Customer, NopCustomerDefaults.CheckoutAttributes, _storeContext.CurrentStore.Id);

            if (string.IsNullOrEmpty(checkoutAttributesXml))
            {
                return(totalWeight);
            }
            var attributeValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(checkoutAttributesXml);

            foreach (var attributeValue in attributeValues)
            {
                totalWeight += attributeValue.WeightAdjustment;
            }

            return(totalWeight);
        }
        /// <summary>
        /// Gets shopping cart subtotal
        /// </summary>
        /// <param name="cart">Cart</param>
        /// <param name="includingTax">A value indicating whether calculated price should include tax</param>
        /// <param name="discountAmount">Applied discount amount</param>
        /// <param name="appliedDiscounts">Applied discounts</param>
        /// <param name="subTotalWithoutDiscount">Sub total (without discount)</param>
        /// <param name="subTotalWithDiscount">Sub total (with discount)</param>
        /// <param name="taxRates">Tax rates (of subscription sub total)</param>
        public virtual void GetShoppingCartSubTotal(IList <ShoppingCartItem> cart,
                                                    bool includingTax,
                                                    out decimal discountAmount,
                                                    out decimal subTotalWithoutDiscount, out decimal subTotalWithDiscount,
                                                    out SortedDictionary <decimal, decimal> taxRates)
        {
            discountAmount = decimal.Zero;

            subTotalWithoutDiscount = decimal.Zero;
            subTotalWithDiscount    = decimal.Zero;
            taxRates = new SortedDictionary <decimal, decimal>();

            if (!cart.Any())
            {
                return;
            }

            //get the customer
            Customer customer = cart.GetCustomer();

            //sub totals
            decimal subTotalExclTaxWithoutDiscount = decimal.Zero;
            decimal subTotalInclTaxWithoutDiscount = decimal.Zero;

            foreach (var shoppingCartItem in cart)
            {
                decimal sciSubTotal = _priceCalculationService.GetSubTotal(shoppingCartItem);

                decimal taxRate;
                decimal sciExclTax = _taxService.GetArticlePrice(shoppingCartItem.Article, sciSubTotal, false, customer, out taxRate);
                decimal sciInclTax = _taxService.GetArticlePrice(shoppingCartItem.Article, sciSubTotal, true, customer, out taxRate);
                subTotalExclTaxWithoutDiscount += sciExclTax;
                subTotalInclTaxWithoutDiscount += sciInclTax;

                //tax rates
                decimal sciTax = sciInclTax - sciExclTax;
                if (taxRate > decimal.Zero && sciTax > decimal.Zero)
                {
                    if (!taxRates.ContainsKey(taxRate))
                    {
                        taxRates.Add(taxRate, sciTax);
                    }
                    else
                    {
                        taxRates[taxRate] = taxRates[taxRate] + sciTax;
                    }
                }
            }

            //checkout attributes
            if (customer != null)
            {
                var checkoutAttributesXml = customer.GetAttribute <string>(SystemCustomerAttributeNames.CheckoutAttributes, _genericAttributeService, _storeContext.CurrentStore.Id);
                var attributeValues       = _checkoutAttributeParser.ParseCheckoutAttributeValues(checkoutAttributesXml);
                if (attributeValues != null)
                {
                    foreach (var attributeValue in attributeValues)
                    {
                        decimal taxRate;

                        decimal caExclTax = _taxService.GetCheckoutAttributePrice(attributeValue, false, customer, out taxRate);
                        decimal caInclTax = _taxService.GetCheckoutAttributePrice(attributeValue, true, customer, out taxRate);
                        subTotalExclTaxWithoutDiscount += caExclTax;
                        subTotalInclTaxWithoutDiscount += caInclTax;

                        //tax rates
                        decimal caTax = caInclTax - caExclTax;
                        if (taxRate > decimal.Zero && caTax > decimal.Zero)
                        {
                            if (!taxRates.ContainsKey(taxRate))
                            {
                                taxRates.Add(taxRate, caTax);
                            }
                            else
                            {
                                taxRates[taxRate] = taxRates[taxRate] + caTax;
                            }
                        }
                    }
                }
            }

            //subtotal without discount
            subTotalWithoutDiscount = includingTax ? subTotalInclTaxWithoutDiscount : subTotalExclTaxWithoutDiscount;
            if (subTotalWithoutDiscount < decimal.Zero)
            {
                subTotalWithoutDiscount = decimal.Zero;
            }

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
            {
                subTotalWithoutDiscount = RoundingHelper.RoundPrice(subTotalWithoutDiscount);
            }

            //We calculate discount amount on subscription subtotal excl tax (discount first)
            //calculate discount amount ('Applied to subscription subtotal' discount)
            decimal discountAmountExclTax = GetSubscriptionSubtotalDiscount(customer, subTotalExclTaxWithoutDiscount);

            if (subTotalExclTaxWithoutDiscount < discountAmountExclTax)
            {
                discountAmountExclTax = subTotalExclTaxWithoutDiscount;
            }
            decimal discountAmountInclTax = discountAmountExclTax;
            //subtotal with discount (excl tax)
            decimal subTotalExclTaxWithDiscount = subTotalExclTaxWithoutDiscount - discountAmountExclTax;
            decimal subTotalInclTaxWithDiscount = subTotalExclTaxWithDiscount;

            //add tax for shopping items & checkout attributes
            var tempTaxRates = new Dictionary <decimal, decimal>(taxRates);

            foreach (KeyValuePair <decimal, decimal> kvp in tempTaxRates)
            {
                decimal taxRate  = kvp.Key;
                decimal taxValue = kvp.Value;

                if (taxValue != decimal.Zero)
                {
                    //discount the tax amount that applies to subtotal items
                    if (subTotalExclTaxWithoutDiscount > decimal.Zero)
                    {
                        decimal discountTax = taxRates[taxRate] * (discountAmountExclTax / subTotalExclTaxWithoutDiscount);
                        discountAmountInclTax += discountTax;
                        taxValue = taxRates[taxRate] - discountTax;
                        if (_shoppingCartSettings.RoundPricesDuringCalculation)
                        {
                            taxValue = RoundingHelper.RoundPrice(taxValue);
                        }
                        taxRates[taxRate] = taxValue;
                    }

                    //subtotal with discount (incl tax)
                    subTotalInclTaxWithDiscount += taxValue;
                }
            }

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
            {
                discountAmountInclTax = RoundingHelper.RoundPrice(discountAmountInclTax);
                discountAmountExclTax = RoundingHelper.RoundPrice(discountAmountExclTax);
            }

            if (includingTax)
            {
                subTotalWithDiscount = subTotalInclTaxWithDiscount;
                discountAmount       = discountAmountInclTax;
            }
            else
            {
                subTotalWithDiscount = subTotalExclTaxWithDiscount;
                discountAmount       = discountAmountExclTax;
            }

            if (subTotalWithDiscount < decimal.Zero)
            {
                subTotalWithDiscount = decimal.Zero;
            }

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
            {
                subTotalWithDiscount = RoundingHelper.RoundPrice(subTotalWithDiscount);
            }
        }
        private async Task PrepareCheckoutAttributes(ShoppingCartModel model, GetShoppingCart request)
        {
            #region Checkout attributes

            var checkoutAttributes = await _checkoutAttributeService.GetAllCheckoutAttributes(request.Store.Id, !request.Cart.RequiresShipping());

            foreach (var attribute in checkoutAttributes)
            {
                var attributeModel = new ShoppingCartModel.CheckoutAttributeModel {
                    Id                   = attribute.Id,
                    Name                 = attribute.GetLocalized(x => x.Name, request.Language.Id),
                    TextPrompt           = attribute.GetLocalized(x => x.TextPrompt, request.Language.Id),
                    IsRequired           = attribute.IsRequired,
                    AttributeControlType = attribute.AttributeControlType,
                    DefaultValue         = attribute.DefaultValue
                };
                if (!String.IsNullOrEmpty(attribute.ValidationFileAllowedExtensions))
                {
                    attributeModel.AllowedFileExtensions = attribute.ValidationFileAllowedExtensions
                                                           .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                                                           .ToList();
                }

                if (attribute.ShouldHaveValues())
                {
                    //values
                    var attributeValues = attribute.CheckoutAttributeValues;
                    foreach (var attributeValue in attributeValues)
                    {
                        var attributeValueModel = new ShoppingCartModel.CheckoutAttributeValueModel {
                            Id              = attributeValue.Id,
                            Name            = attributeValue.GetLocalized(x => x.Name, request.Language.Id),
                            ColorSquaresRgb = attributeValue.ColorSquaresRgb,
                            IsPreSelected   = attributeValue.IsPreSelected,
                        };
                        attributeModel.Values.Add(attributeValueModel);

                        //display price if allowed
                        if (await _permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
                        {
                            decimal priceAdjustmentBase = (await _taxService.GetCheckoutAttributePrice(attribute, attributeValue)).checkoutPrice;
                            decimal priceAdjustment     = await _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, request.Currency);

                            if (priceAdjustmentBase > decimal.Zero)
                            {
                                attributeValueModel.PriceAdjustment = "+" + _priceFormatter.FormatPrice(priceAdjustment);
                            }
                            else if (priceAdjustmentBase < decimal.Zero)
                            {
                                attributeValueModel.PriceAdjustment = "-" + _priceFormatter.FormatPrice(-priceAdjustment);
                            }
                        }
                    }
                }
                //set already selected attributes
                var selectedCheckoutAttributes = request.Customer.GetAttributeFromEntity <string>(SystemCustomerAttributeNames.CheckoutAttributes, request.Store.Id);
                switch (attribute.AttributeControlType)
                {
                case AttributeControlType.DropdownList:
                case AttributeControlType.RadioList:
                case AttributeControlType.Checkboxes:
                case AttributeControlType.ColorSquares:
                case AttributeControlType.ImageSquares:
                {
                    if (!String.IsNullOrEmpty(selectedCheckoutAttributes))
                    {
                        //clear default selection
                        foreach (var item in attributeModel.Values)
                        {
                            item.IsPreSelected = false;
                        }

                        //select new values
                        var selectedValues = await _checkoutAttributeParser.ParseCheckoutAttributeValues(selectedCheckoutAttributes);

                        foreach (var attributeValue in selectedValues)
                        {
                            if (attributeModel.Id == attributeValue.CheckoutAttributeId)
                            {
                                foreach (var item in attributeModel.Values)
                                {
                                    if (attributeValue.Id == item.Id)
                                    {
                                        item.IsPreSelected = true;
                                    }
                                }
                            }
                        }
                    }
                }
                break;

                case AttributeControlType.ReadonlyCheckboxes:
                {
                    //do nothing
                    //values are already pre-set
                }
                break;

                case AttributeControlType.TextBox:
                case AttributeControlType.MultilineTextbox:
                {
                    if (!String.IsNullOrEmpty(selectedCheckoutAttributes))
                    {
                        var enteredText = _checkoutAttributeParser.ParseValues(selectedCheckoutAttributes, attribute.Id);
                        if (enteredText.Any())
                        {
                            attributeModel.DefaultValue = enteredText[0];
                        }
                    }
                }
                break;

                case AttributeControlType.Datepicker:
                {
                    //keep in mind my that the code below works only in the current culture
                    var selectedDateStr = _checkoutAttributeParser.ParseValues(selectedCheckoutAttributes, attribute.Id);
                    if (selectedDateStr.Any())
                    {
                        DateTime selectedDate;
                        if (DateTime.TryParseExact(selectedDateStr[0], "D", CultureInfo.CurrentCulture,
                                                   DateTimeStyles.None, out selectedDate))
                        {
                            //successfully parsed
                            attributeModel.SelectedDay   = selectedDate.Day;
                            attributeModel.SelectedMonth = selectedDate.Month;
                            attributeModel.SelectedYear  = selectedDate.Year;
                        }
                    }
                }
                break;

                case AttributeControlType.FileUpload:
                {
                    if (!String.IsNullOrEmpty(selectedCheckoutAttributes))
                    {
                        var  downloadGuidStr = _checkoutAttributeParser.ParseValues(selectedCheckoutAttributes, attribute.Id).FirstOrDefault();
                        Guid downloadGuid;
                        Guid.TryParse(downloadGuidStr, out downloadGuid);
                        var download = await _downloadService.GetDownloadByGuid(downloadGuid);

                        if (download != null)
                        {
                            attributeModel.DefaultValue = download.DownloadGuid.ToString();
                        }
                    }
                }
                break;

                default:
                    break;
                }

                model.CheckoutAttributes.Add(attributeModel);
            }
            #endregion
        }
Example #9
0
        private void AddInvoiceVars(Dictionary <string, string> vars, PostProcessPaymentRequest postProcessPaymentRequest)
        {
            // article for invoice vars:  http://kb.cardcom.co.il/article/AA-00244/0
            var customer  = _workContext.CurrentCustomer;
            var firstName = customer.GetAttribute <string>(SystemCustomerAttributeNames.FirstName);
            var lastName  = customer.GetAttribute <string>(SystemCustomerAttributeNames.LastName);

            // customer info :
            vars["InvoiceHead.CustName"]        = firstName + " " + lastName; // customer name
            vars["InvoiceHead.SendByEmail"]     = "true";                     // will the invoice be send by email to the customer
            vars["InvoiceHead.Language"]        = GetLanguageNameInvoice(_workContext.WorkingLanguage.UniqueSeoCode);
            vars["InvoiceHead.CoinID"]          = GetCurrencyIdByCurrencyName(_currencyService.GetCurrencyById(_workContext.WorkingCurrency.Id).CurrencyCode).ToString();
            vars["InvoiceHead.Email"]           = postProcessPaymentRequest.Order.BillingAddress.Email; // value that will be return and save in CardCom system
            vars["InvoiceHead.CustAddresLine1"] = postProcessPaymentRequest.Order.BillingAddress.Address1;
            vars["InvoiceHead.CustAddresLine2"] = postProcessPaymentRequest.Order.BillingAddress.Address2;
            vars["InvoiceHead.CustCity"]        = postProcessPaymentRequest.Order.BillingAddress.City;
            vars["InvoiceHead.CustLinePH"]      = postProcessPaymentRequest.Order.BillingAddress.PhoneNumber;

            //get the items in the cart
            decimal cartTotal  = decimal.Zero;
            var     cartItems  = postProcessPaymentRequest.Order.OrderItems;
            int     itemsCount = 1;

            foreach (var item in cartItems) //50 chars limit
            {
                var unitPriceExclTax = item.UnitPriceExclTax;
                var priceExclTax     = item.PriceExclTax;
                //round
                var unitPriceExclTaxRounded = Math.Round(unitPriceExclTax, 2);
                if (item.Product.WeightProduct)
                {
                    if (item.Product.ByUnit.HasValue && item.Product.ByUnit.Value == true)
                    {
                        vars["InvoiceLines" + itemsCount.ToString() + ".Quantity"] = HttpUtility.UrlEncode((item.Quantity).ToString() + " " + "יחידות");
                        vars["InvoiceLines" + itemsCount.ToString() + ".Price"]    = Math.Round(item.Product.UnitPrice.Value).ToString("0.00", CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        vars["InvoiceLines" + itemsCount.ToString() + ".Quantity"] = HttpUtility.UrlEncode((item.Quantity * item.Product.BaseWeight.Value).ToString() + " " + item.Product.WeightUnit);
                        vars["InvoiceLines" + itemsCount.ToString() + ".Price"]    = unitPriceExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture);
                    }
                }
                else
                {
                    vars["InvoiceLines" + itemsCount.ToString() + ".Quantity"] = HttpUtility.UrlEncode(item.Quantity.ToString());
                    vars["InvoiceLines" + itemsCount.ToString() + ".Price"]    = unitPriceExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture);
                }

                vars["InvoiceLines" + itemsCount.ToString() + ".Description"] = HttpUtility.UrlEncode(item.Product.Name);
                vars["InvoiceLines" + itemsCount.ToString() + ".ProductID"]   = (String.IsNullOrWhiteSpace(item.Product.Sku)) ? item.Product.Sku : "";

                itemsCount++;
                cartTotal += priceExclTax;
            }
            //the checkout attributes that have a dollar value and send them to CardCom as items to be paid for
            var caValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(postProcessPaymentRequest.Order.CheckoutAttributesXml);

            foreach (var val in caValues)
            {
                var attPrice = _taxService.GetCheckoutAttributePrice(val, false, postProcessPaymentRequest.Order.Customer);
                //round
                var attPriceRounded = Math.Round(attPrice, 2);
                if (attPrice > decimal.Zero) //if it has a price
                {
                    var ca = val.CheckoutAttribute;
                    if (ca != null)
                    {
                        var attName = ca.Name;                                                                                                          //set the name
                        vars["InvoiceLines" + itemsCount.ToString() + ".Description"] = HttpUtility.UrlEncode(attName);
                        vars["InvoiceLines" + itemsCount.ToString() + ".Price"]       = attPriceRounded.ToString("0.00", CultureInfo.InvariantCulture); //amount
                        vars["InvoiceLines" + itemsCount.ToString() + ".Quantity"]    = "1";                                                            //quantity
                        itemsCount++;
                        cartTotal += attPrice;
                    }
                }
            }
            //order totals

            //shipping
            var orderShippingExclTax        = postProcessPaymentRequest.Order.OrderShippingExclTax;
            var orderShippingExclTaxRounded = Math.Round(orderShippingExclTax, 2);

            if (orderShippingExclTax > decimal.Zero)
            {
                vars["InvoiceLines" + itemsCount.ToString() + ".Description"] = _localizationService.GetResource("Plugins.Payments.CardCom.ShippingFee");
                vars["InvoiceLines" + itemsCount.ToString() + ".Price"]       = orderShippingExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture);
                vars["InvoiceLines" + itemsCount.ToString() + ".Quantity"]    = "1"; //quantity
                itemsCount++;
                cartTotal += orderShippingExclTax;
            }

            //payment method additional fee
            var paymentMethodAdditionalFeeExclTax        = postProcessPaymentRequest.Order.PaymentMethodAdditionalFeeExclTax;
            var paymentMethodAdditionalFeeExclTaxRounded = Math.Round(paymentMethodAdditionalFeeExclTax, 2);

            if (paymentMethodAdditionalFeeExclTax > decimal.Zero)
            {
                vars["InvoiceLines" + itemsCount.ToString() + ".Description"] = _localizationService.GetResource("Plugins.Payments.CardCom.PaymentMethodFee");
                vars["InvoiceLines" + itemsCount.ToString() + ".Price"]       = paymentMethodAdditionalFeeExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture);
                vars["InvoiceLines" + itemsCount.ToString() + ".Quantity"]    = "1"; //quantity
                itemsCount++;
                cartTotal += paymentMethodAdditionalFeeExclTax;
            }
            //tax
            var orderTax        = postProcessPaymentRequest.Order.OrderTax;
            var orderTaxRounded = Math.Round(orderTax, 2);

            if (orderTax > decimal.Zero)
            {
                //add tax as item
                vars["InvoiceLines" + itemsCount.ToString() + ".Description"] = _localizationService.GetResource("Plugins.Payments.CardCom.SalesTax"); //name
                vars["InvoiceLines" + itemsCount.ToString() + ".Price"]       = orderTaxRounded.ToString("0.00", CultureInfo.InvariantCulture);        //amount
                vars["InvoiceLines" + itemsCount.ToString() + ".Quantity"]    = "1";                                                                   //quantity

                cartTotal += orderTax;
                itemsCount++;
            }

            if (cartTotal > postProcessPaymentRequest.Order.OrderTotal)
            {
                /* Take the difference between what the order total is and what it should be and use that as the "discount".
                 * The difference equals the amount of the gift card and/or reward points used.
                 */
                decimal discountTotal = cartTotal - postProcessPaymentRequest.Order.OrderTotal;
                discountTotal = Math.Round(discountTotal, 2) * (-1);
                //gift card or rewared point amount applied to cart in nopCommerce - shows in Paypal as "discount"
                vars["InvoiceLines" + itemsCount.ToString() + ".Description"] = _localizationService.GetResource("Plugins.Payments.CardCom.Discount"); //name
                vars["InvoiceLines" + itemsCount.ToString() + ".Price"]       = discountTotal.ToString("0.00", CultureInfo.InvariantCulture);
                vars["InvoiceLines" + itemsCount.ToString() + ".Quantity"]    = "1";                                                                   //quantity
            }
        }
Example #10
0
        /// <summary>
        /// Gets shopping cart subtotal
        /// </summary>
        /// <param name="cart">Cart</param>
        /// <param name="includingTax">A value indicating whether calculated price should include tax</param>
        /// <param name="discountAmount">Applied discount amount</param>
        /// <param name="appliedDiscount">Applied discount</param>
        /// <param name="subTotalWithoutDiscount">Sub total (without discount)</param>
        /// <param name="subTotalWithDiscount">Sub total (with discount)</param>
        /// <param name="taxRates">Tax rates (of order sub total)</param>
        public virtual void GetShoppingCartSubTotal(IList <ShoppingCartItem> cart,
                                                    bool includingTax,
                                                    out decimal discountAmount, out Discount appliedDiscount,
                                                    out decimal subTotalWithoutDiscount, out decimal subTotalWithDiscount,
                                                    out SortedDictionary <decimal, decimal> taxRates)
        {
            discountAmount          = decimal.Zero;
            appliedDiscount         = null;
            subTotalWithoutDiscount = decimal.Zero;
            subTotalWithDiscount    = decimal.Zero;
            taxRates = new SortedDictionary <decimal, decimal>();

            if (cart.Count == 0)
            {
                return;
            }

            //get the customer
            Customer customer = cart.GetCustomer();

            //sub totals
            decimal subTotalExclTaxWithoutDiscount = decimal.Zero;
            decimal subTotalInclTaxWithoutDiscount = decimal.Zero;

            foreach (var shoppingCartItem in cart)
            {
                decimal taxRate     = decimal.Zero;
                decimal sciSubTotal = _priceCalculationService.GetSubTotal(shoppingCartItem, true);

                decimal sciExclTax = _taxService.GetProductPrice(shoppingCartItem.ProductVariant, sciSubTotal, false, customer, out taxRate);
                decimal sciInclTax = _taxService.GetProductPrice(shoppingCartItem.ProductVariant, sciSubTotal, true, customer, out taxRate);
                subTotalExclTaxWithoutDiscount += sciExclTax;
                subTotalInclTaxWithoutDiscount += sciInclTax;

                //tax rates
                decimal sciTax = sciInclTax - sciExclTax;
                if (taxRate > decimal.Zero && sciTax > decimal.Zero)
                {
                    if (!taxRates.ContainsKey(taxRate))
                    {
                        taxRates.Add(taxRate, sciTax);
                    }
                    else
                    {
                        taxRates[taxRate] = taxRates[taxRate] + sciTax;
                    }
                }
            }

            //checkout attributes
            if (customer != null)
            {
                var caValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(customer.CheckoutAttributes);
                if (caValues != null)
                {
                    foreach (var caValue in caValues)
                    {
                        decimal taxRate = decimal.Zero;

                        decimal caExclTax = _taxService.GetCheckoutAttributePrice(caValue, false, customer, out taxRate);
                        decimal caInclTax = _taxService.GetCheckoutAttributePrice(caValue, true, customer, out taxRate);
                        subTotalExclTaxWithoutDiscount += caExclTax;
                        subTotalInclTaxWithoutDiscount += caInclTax;

                        //tax rates
                        decimal caTax = caInclTax - caExclTax;
                        if (taxRate > decimal.Zero && caTax > decimal.Zero)
                        {
                            if (!taxRates.ContainsKey(taxRate))
                            {
                                taxRates.Add(taxRate, caTax);
                            }
                            else
                            {
                                taxRates[taxRate] = taxRates[taxRate] + caTax;
                            }
                        }
                    }
                }
            }

            //subtotal without discount
            if (includingTax)
            {
                subTotalWithoutDiscount = subTotalInclTaxWithoutDiscount;
            }
            else
            {
                subTotalWithoutDiscount = subTotalExclTaxWithoutDiscount;
            }
            if (subTotalWithoutDiscount < decimal.Zero)
            {
                subTotalWithoutDiscount = decimal.Zero;
            }

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
            {
                subTotalWithoutDiscount = Math.Round(subTotalWithoutDiscount, 2);
            }

            /*We calculate discount amount on order subtotal excl tax (discount first)*/
            //calculate discount amount ('Applied to order subtotal' discount)
            decimal discountAmountExclTax = GetOrderSubtotalDiscount(customer, subTotalExclTaxWithoutDiscount, out appliedDiscount);

            if (subTotalExclTaxWithoutDiscount < discountAmountExclTax)
            {
                discountAmountExclTax = subTotalExclTaxWithoutDiscount;
            }
            decimal discountAmountInclTax = discountAmountExclTax;
            //subtotal with discount (excl tax)
            decimal subTotalExclTaxWithDiscount = subTotalExclTaxWithoutDiscount - discountAmountExclTax;
            decimal subTotalInclTaxWithDiscount = subTotalExclTaxWithDiscount;

            //add tax for shopping items & checkout attributes
            Dictionary <decimal, decimal> tempTaxRates = new Dictionary <decimal, decimal>(taxRates);

            foreach (KeyValuePair <decimal, decimal> kvp in tempTaxRates)
            {
                decimal taxRate  = kvp.Key;
                decimal taxValue = kvp.Value;

                if (taxValue != decimal.Zero)
                {
                    //discount the tax amount that applies to subtotal items
                    if (subTotalExclTaxWithoutDiscount > decimal.Zero)
                    {
                        decimal discountTax = taxRates[taxRate] * (discountAmountExclTax / subTotalExclTaxWithoutDiscount);
                        discountAmountInclTax += discountTax;
                        taxValue = taxRates[taxRate] - discountTax;
                        if (_shoppingCartSettings.RoundPricesDuringCalculation)
                        {
                            taxValue = Math.Round(taxValue, 2);
                        }
                        taxRates[taxRate] = taxValue;
                    }

                    //subtotal with discount (incl tax)
                    subTotalInclTaxWithDiscount += taxValue;
                }
            }

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
            {
                discountAmountInclTax = Math.Round(discountAmountInclTax, 2);
            }

            if (includingTax)
            {
                subTotalWithDiscount = subTotalInclTaxWithDiscount;
                discountAmount       = discountAmountInclTax;
            }
            else
            {
                subTotalWithDiscount = subTotalExclTaxWithDiscount;
                discountAmount       = discountAmountExclTax;
            }

            //round
            if (subTotalWithDiscount < decimal.Zero)
            {
                subTotalWithDiscount = decimal.Zero;
            }

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
            {
                subTotalWithDiscount = Math.Round(subTotalWithDiscount, 2);
            }
        }
        /// <summary>
        /// Add order items to the request query parameters
        /// </summary>
        /// <param name="parameters">Query parameters</param>
        /// <param name="postProcessPaymentRequest">Payment info required for an order processing</param>
        private async Task AddItemsParameters(IDictionary <string, string> parameters, PostProcessPaymentRequest postProcessPaymentRequest)
        {
            //upload order items
            parameters.Add("cmd", "_cart");
            parameters.Add("upload", "1");

            var cartTotal        = decimal.Zero;
            var roundedCartTotal = decimal.Zero;
            var itemCount        = 1;

            //add shopping cart items
            foreach (var item in postProcessPaymentRequest.Order.OrderItems)
            {
                var product = await _productService.GetProductById(item.ProductId);

                var roundedItemPrice = Math.Round(item.UnitPriceExclTax, 2);

                //add query parameters
                parameters.Add($"item_name_{itemCount}", product.Name);
                parameters.Add($"amount_{itemCount}", roundedItemPrice.ToString("0.00", CultureInfo.InvariantCulture));
                parameters.Add($"quantity_{itemCount}", item.Quantity.ToString());

                cartTotal        += item.PriceExclTax;
                roundedCartTotal += roundedItemPrice * item.Quantity;
                itemCount++;
            }

            //add checkout attributes as order items
            var checkoutAttributeValues = await _checkoutAttributeParser.ParseCheckoutAttributeValues(postProcessPaymentRequest.Order.CheckoutAttributesXml);

            var customer = await _serviceProvider.GetRequiredService <ICustomerService>().GetCustomerById(postProcessPaymentRequest.Order.CustomerId);

            foreach (var attributeValue in checkoutAttributeValues)
            {
                var attributePrice = await _taxService.GetCheckoutAttributePrice(attributeValue, false, customer);

                if (attributePrice.checkoutPrice > 0)
                {
                    var roundedAttributePrice = Math.Round(attributePrice.checkoutPrice, 2);

                    //add query parameters
                    var attribute = await _serviceProvider.GetRequiredService <ICheckoutAttributeService>().GetCheckoutAttributeById(attributeValue.CheckoutAttributeId);

                    if (attribute != null)
                    {
                        parameters.Add($"item_name_{itemCount}", attribute.Name);
                        parameters.Add($"amount_{itemCount}", roundedAttributePrice.ToString("0.00", CultureInfo.InvariantCulture));
                        parameters.Add($"quantity_{itemCount}", "1");

                        cartTotal        += attributePrice.checkoutPrice;
                        roundedCartTotal += roundedAttributePrice;
                        itemCount++;
                    }
                }
            }

            //add shipping fee as a separate order item, if it has price
            var roundedShippingPrice = Math.Round(postProcessPaymentRequest.Order.OrderShippingExclTax, 2);

            if (roundedShippingPrice > decimal.Zero)
            {
                parameters.Add($"item_name_{itemCount}", "Shipping fee");
                parameters.Add($"amount_{itemCount}", roundedShippingPrice.ToString("0.00", CultureInfo.InvariantCulture));
                parameters.Add($"quantity_{itemCount}", "1");

                cartTotal        += postProcessPaymentRequest.Order.OrderShippingExclTax;
                roundedCartTotal += roundedShippingPrice;
                itemCount++;
            }

            //add payment method additional fee as a separate order item, if it has price
            var roundedPaymentMethodPrice = Math.Round(postProcessPaymentRequest.Order.PaymentMethodAdditionalFeeExclTax, 2);

            if (roundedPaymentMethodPrice > decimal.Zero)
            {
                parameters.Add($"item_name_{itemCount}", "Payment method fee");
                parameters.Add($"amount_{itemCount}", roundedPaymentMethodPrice.ToString("0.00", CultureInfo.InvariantCulture));
                parameters.Add($"quantity_{itemCount}", "1");

                cartTotal        += postProcessPaymentRequest.Order.PaymentMethodAdditionalFeeExclTax;
                roundedCartTotal += roundedPaymentMethodPrice;
                itemCount++;
            }

            //add tax as a separate order item, if it has positive amount
            var roundedTaxAmount = Math.Round(postProcessPaymentRequest.Order.OrderTax, 2);

            if (roundedTaxAmount > decimal.Zero)
            {
                parameters.Add($"item_name_{itemCount}", "Tax amount");
                parameters.Add($"amount_{itemCount}", roundedTaxAmount.ToString("0.00", CultureInfo.InvariantCulture));
                parameters.Add($"quantity_{itemCount}", "1");

                cartTotal        += postProcessPaymentRequest.Order.OrderTax;
                roundedCartTotal += roundedTaxAmount;
                itemCount++;
            }

            if (cartTotal > postProcessPaymentRequest.Order.OrderTotal)
            {
                //get the difference between what the order total is and what it should be and use that as the "discount"
                var discountTotal = Math.Round(cartTotal - postProcessPaymentRequest.Order.OrderTotal, 2);
                roundedCartTotal -= discountTotal;

                //gift card or rewarded point amount applied to cart in nopCommerce - shows in PayPal as "discount"
                parameters.Add("discount_amount_cart", discountTotal.ToString("0.00", CultureInfo.InvariantCulture));
            }

            //save order total that actually sent to PayPal (used for PDT order total validation)
            await _genericAttributeService.SaveAttribute(postProcessPaymentRequest.Order, PaypalHelper.OrderTotalSentToPayPal, roundedCartTotal);
        }
Example #12
0
        public PaymentDetailsType[] GetPaymentDetails(IList <ShoppingCartItem> cart)
        {
            var currencyCode = _payPalCurrencyCodeParser.GetCurrencyCodeType(_workContext.WorkingCurrency);

            decimal orderTotalDiscountAmount;
            List <DiscountForCaching> appliedDiscounts;
            int     redeemedRewardPoints;
            decimal redeemedRewardPointsAmount;
            List <AppliedGiftCard> appliedGiftCards;
            var orderTotalWithDiscount = _payPalCartItemService.GetCartTotal(cart, out orderTotalDiscountAmount,
                                                                             out appliedDiscounts,
                                                                             out redeemedRewardPoints,
                                                                             out redeemedRewardPointsAmount,
                                                                             out appliedGiftCards);

            decimal subTotalWithDiscount;
            decimal subTotalWithoutDiscount;
            List <DiscountForCaching> subTotalAppliedDiscounts;
            decimal subTotalDiscountAmount;
            var     itemTotalWithDiscount = _payPalCartItemService.GetCartItemTotal(cart,
                                                                                    out subTotalDiscountAmount,
                                                                                    out subTotalAppliedDiscounts,
                                                                                    out subTotalWithoutDiscount,
                                                                                    out subTotalWithDiscount);

            var giftCardsAmount = appliedGiftCards.Sum(x => x.AmountCanBeUsed);

            itemTotalWithDiscount = itemTotalWithDiscount - orderTotalDiscountAmount - giftCardsAmount;

            var taxTotal      = _payPalCartItemService.GetTax(cart);
            var shippingTotal = _payPalCartItemService.GetShippingTotal(cart);
            var items         = GetPaymentDetailsItems(cart);

            // checkout attributes
            var customer = cart.GetCustomer();

            if (customer != null)
            {
                var checkoutAttributesXml = customer.GetAttribute <string>(SystemCustomerAttributeNames.CheckoutAttributes, _genericAttributeService, _storeContext.CurrentStore.Id);
                var caValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(checkoutAttributesXml);
                if (caValues != null)
                {
                    foreach (var caValue in caValues)
                    {
                        if (caValue.PriceAdjustment > 0)
                        {
                            var checkoutAttrItem = new PaymentDetailsItemType
                            {
                                Name     = caValue.Name,
                                Amount   = caValue.PriceAdjustment.GetBasicAmountType(currencyCode),
                                Quantity = "1"
                            };
                            items.Add(checkoutAttrItem);
                        }
                    }
                }
            }
            if (orderTotalDiscountAmount > 0 || subTotalDiscountAmount > 0)
            {
                var discountItem = new PaymentDetailsItemType
                {
                    Name   = "Discount",
                    Amount =
                        (-orderTotalDiscountAmount + -subTotalDiscountAmount).GetBasicAmountType(
                            currencyCode),
                    Quantity = "1"
                };

                items.Add(discountItem);
            }

            foreach (var appliedGiftCard in appliedGiftCards)
            {
                var giftCardItem = new PaymentDetailsItemType
                {
                    Name     = string.Format("Gift Card ({0})", appliedGiftCard.GiftCard.GiftCardCouponCode),
                    Amount   = (-appliedGiftCard.AmountCanBeUsed).GetBasicAmountType(currencyCode),
                    Quantity = "1"
                };

                items.Add(giftCardItem);
            }

            return(new[]
            {
                new PaymentDetailsType
                {
                    OrderTotal = orderTotalWithDiscount.GetBasicAmountType(currencyCode),
                    ItemTotal = itemTotalWithDiscount.GetBasicAmountType(currencyCode),
                    TaxTotal = taxTotal.GetBasicAmountType(currencyCode),
                    ShippingTotal = shippingTotal.GetBasicAmountType(currencyCode),
                    PaymentDetailsItem = items.ToArray(),
                    PaymentAction = _payPalExpressCheckoutPaymentSettings.PaymentAction,
                    PaymentActionSpecified = true,
                    ButtonSource = PayPalHelper.BnCode
                }
            });
        }
        public virtual void PrepareShoppingCartModel(ShoppingCartModel model,
                                                     IList <ShoppingCartItem> cart, bool isEditable = true,
                                                     bool validateCheckoutAttributes       = false,
                                                     bool prepareEstimateShippingIfEnabled = true, bool setEstimateShippingDefaultAddress = true,
                                                     bool prepareAndDisplayOrderReviewData = false)
        {
            if (cart == null)
            {
                throw new ArgumentNullException("cart");
            }

            if (model == null)
            {
                throw new ArgumentNullException("model");
            }

            model.OnePageCheckoutEnabled = _orderSettings.OnePageCheckoutEnabled;

            if (cart.Count == 0)
            {
                return;
            }

            #region Simple properties

            model.IsEditable        = isEditable;
            model.ShowProductImages = _shoppingCartSettings.ShowProductImagesOnShoppingCart;
            model.ShowSku           = _catalogSettings.ShowProductSku;
            var checkoutAttributesXml = _workContext.CurrentCustomer.GetAttribute <string>(SystemCustomerAttributeNames.CheckoutAttributes, _genericAttributeService, _storeContext.CurrentStore.Id);
            model.CheckoutAttributeInfo = _checkoutAttributeFormatter.FormatAttributes(checkoutAttributesXml, _workContext.CurrentCustomer);
            bool minOrderSubtotalAmountOk = _orderProcessingService.ValidateMinOrderSubtotalAmount(cart);
            if (!minOrderSubtotalAmountOk)
            {
                decimal minOrderSubtotalAmount = _currencyService.ConvertFromPrimaryStoreCurrency(_orderSettings.MinOrderSubtotalAmount, _workContext.WorkingCurrency);
                model.MinOrderSubtotalWarning = string.Format(_localizationService.GetResource("Checkout.MinOrderSubtotalAmount"), _priceFormatter.FormatPrice(minOrderSubtotalAmount, true, false));
            }
            model.TermsOfServiceOnShoppingCartPage = _orderSettings.TermsOfServiceOnShoppingCartPage;
            model.TermsOfServiceOnOrderConfirmPage = _orderSettings.TermsOfServiceOnOrderConfirmPage;

            //gift card and gift card boxes
            model.DiscountBox.Display = _shoppingCartSettings.ShowDiscountBox;
            var discountCouponCode = _workContext.CurrentCustomer.GetAttribute <string>(SystemCustomerAttributeNames.DiscountCouponCode);
            var discount           = _discountService.GetDiscountByCouponCode(discountCouponCode);
            if (discount != null &&
                discount.RequiresCouponCode &&
                _discountService.IsDiscountValid(discount, _workContext.CurrentCustomer))
            {
                model.DiscountBox.CurrentCode = discount.CouponCode;
            }
            model.GiftCardBox.Display = _shoppingCartSettings.ShowGiftCardBox;

            //cart warnings
            var cartWarnings = _shoppingCartService.GetShoppingCartWarnings(cart, checkoutAttributesXml, validateCheckoutAttributes);
            foreach (var warning in cartWarnings)
            {
                model.Warnings.Add(warning);
            }

            #endregion

            #region Checkout attributes

            var checkoutAttributes = _checkoutAttributeService.GetAllCheckoutAttributes(_storeContext.CurrentStore.Id, !cart.RequiresShipping());
            foreach (var attribute in checkoutAttributes)
            {
                var attributeModel = new ShoppingCartModel.CheckoutAttributeModel
                {
                    Id                   = attribute.Id,
                    Name                 = attribute.GetLocalized(x => x.Name),
                    TextPrompt           = attribute.GetLocalized(x => x.TextPrompt),
                    IsRequired           = attribute.IsRequired,
                    AttributeControlType = attribute.AttributeControlType,
                    DefaultValue         = attribute.DefaultValue
                };
                if (!String.IsNullOrEmpty(attribute.ValidationFileAllowedExtensions))
                {
                    attributeModel.AllowedFileExtensions = attribute.ValidationFileAllowedExtensions
                                                           .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                                                           .ToList();
                }

                if (attribute.ShouldHaveValues())
                {
                    //values
                    var attributeValues = _checkoutAttributeService.GetCheckoutAttributeValues(attribute.Id);
                    foreach (var attributeValue in attributeValues)
                    {
                        var attributeValueModel = new ShoppingCartModel.CheckoutAttributeValueModel
                        {
                            Id              = attributeValue.Id,
                            Name            = attributeValue.GetLocalized(x => x.Name),
                            ColorSquaresRgb = attributeValue.ColorSquaresRgb,
                            IsPreSelected   = attributeValue.IsPreSelected,
                        };
                        attributeModel.Values.Add(attributeValueModel);

                        //display price if allowed
                        if (_permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
                        {
                            decimal priceAdjustmentBase = _taxService.GetCheckoutAttributePrice(attributeValue);
                            decimal priceAdjustment     = _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, _workContext.WorkingCurrency);
                            if (priceAdjustmentBase > decimal.Zero)
                            {
                                attributeValueModel.PriceAdjustment = "+" + _priceFormatter.FormatPrice(priceAdjustment);
                            }
                            else if (priceAdjustmentBase < decimal.Zero)
                            {
                                attributeValueModel.PriceAdjustment = "-" + _priceFormatter.FormatPrice(-priceAdjustment);
                            }
                        }
                    }
                }



                //set already selected attributes
                var selectedCheckoutAttributes = _workContext.CurrentCustomer.GetAttribute <string>(SystemCustomerAttributeNames.CheckoutAttributes, _genericAttributeService, _storeContext.CurrentStore.Id);
                switch (attribute.AttributeControlType)
                {
                case AttributeControlType.DropdownList:
                case AttributeControlType.RadioList:
                case AttributeControlType.Checkboxes:
                case AttributeControlType.ColorSquares:
                {
                    if (!String.IsNullOrEmpty(selectedCheckoutAttributes))
                    {
                        //clear default selection
                        foreach (var item in attributeModel.Values)
                        {
                            item.IsPreSelected = false;
                        }

                        //select new values
                        var selectedValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(selectedCheckoutAttributes);
                        foreach (var attributeValue in selectedValues)
                        {
                            foreach (var item in attributeModel.Values)
                            {
                                if (attributeValue.Id == item.Id)
                                {
                                    item.IsPreSelected = true;
                                }
                            }
                        }
                    }
                }
                break;

                case AttributeControlType.ReadonlyCheckboxes:
                {
                    //do nothing
                    //values are already pre-set
                }
                break;

                case AttributeControlType.TextBox:
                case AttributeControlType.MultilineTextbox:
                {
                    if (!String.IsNullOrEmpty(selectedCheckoutAttributes))
                    {
                        var enteredText = _checkoutAttributeParser.ParseValues(selectedCheckoutAttributes, attribute.Id);
                        if (enteredText.Count > 0)
                        {
                            attributeModel.DefaultValue = enteredText[0];
                        }
                    }
                }
                break;

                case AttributeControlType.Datepicker:
                {
                    //keep in mind my that the code below works only in the current culture
                    var selectedDateStr = _checkoutAttributeParser.ParseValues(selectedCheckoutAttributes, attribute.Id);
                    if (selectedDateStr.Count > 0)
                    {
                        DateTime selectedDate;
                        if (DateTime.TryParseExact(selectedDateStr[0], "D", CultureInfo.CurrentCulture,
                                                   DateTimeStyles.None, out selectedDate))
                        {
                            //successfully parsed
                            attributeModel.SelectedDay   = selectedDate.Day;
                            attributeModel.SelectedMonth = selectedDate.Month;
                            attributeModel.SelectedYear  = selectedDate.Year;
                        }
                    }
                }
                break;

                default:
                    break;
                }

                model.CheckoutAttributes.Add(attributeModel);
            }

            #endregion

            #region Estimate shipping

            if (prepareEstimateShippingIfEnabled)
            {
                model.EstimateShipping.Enabled = cart.Count > 0 && cart.RequiresShipping() && _shippingSettings.EstimateShippingEnabled;
                if (model.EstimateShipping.Enabled)
                {
                    //countries
                    int?defaultEstimateCountryId = (setEstimateShippingDefaultAddress && _workContext.CurrentCustomer.ShippingAddress != null) ? _workContext.CurrentCustomer.ShippingAddress.CountryId : model.EstimateShipping.CountryId;
                    model.EstimateShipping.AvailableCountries.Add(new SelectListItem {
                        Text = _localizationService.GetResource("Address.SelectCountry"), Value = "0"
                    });
                    foreach (var c in _countryService.GetAllCountriesForShipping())
                    {
                        model.EstimateShipping.AvailableCountries.Add(new SelectListItem
                        {
                            Text     = c.GetLocalized(x => x.Name),
                            Value    = c.Id.ToString(),
                            Selected = c.Id == defaultEstimateCountryId
                        });
                    }
                    //states
                    int?defaultEstimateStateId = (setEstimateShippingDefaultAddress && _workContext.CurrentCustomer.ShippingAddress != null) ? _workContext.CurrentCustomer.ShippingAddress.StateProvinceId : model.EstimateShipping.StateProvinceId;
                    var states = defaultEstimateCountryId.HasValue ? _stateProvinceService.GetStateProvincesByCountryId(defaultEstimateCountryId.Value).ToList() : new List <StateProvince>();
                    if (states.Count > 0)
                    {
                        foreach (var s in states)
                        {
                            model.EstimateShipping.AvailableStates.Add(new SelectListItem
                            {
                                Text     = s.GetLocalized(x => x.Name),
                                Value    = s.Id.ToString(),
                                Selected = s.Id == defaultEstimateStateId
                            });
                        }
                    }
                    else
                    {
                        model.EstimateShipping.AvailableStates.Add(new SelectListItem {
                            Text = _localizationService.GetResource("Address.OtherNonUS"), Value = "0"
                        });
                    }

                    if (setEstimateShippingDefaultAddress && _workContext.CurrentCustomer.ShippingAddress != null)
                    {
                        model.EstimateShipping.ZipPostalCode = _workContext.CurrentCustomer.ShippingAddress.ZipPostalCode;
                    }
                }
            }

            #endregion

            #region Cart items

            foreach (var sci in cart)
            {
                var cartItemModel = new ShoppingCartModel.ShoppingCartItemModel
                {
                    Id            = sci.Id,
                    Sku           = sci.Product.FormatSku(sci.AttributesXml, _productAttributeParser),
                    ProductId     = sci.Product.Id,
                    ProductName   = sci.Product.GetLocalized(x => x.Name),
                    ProductSeName = sci.Product.GetSeName(),
                    Quantity      = sci.Quantity,
                    AttributeInfo = _productAttributeFormatter.FormatAttributes(sci.Product, sci.AttributesXml),
                };

                //allow editing?
                //1. setting enabled?
                //2. simple product?
                //3. has attribute or gift card?
                //4. visible individually?
                cartItemModel.AllowItemEditing = _shoppingCartSettings.AllowCartItemEditing &&
                                                 sci.Product.ProductType == ProductType.SimpleProduct &&
                                                 (!String.IsNullOrEmpty(cartItemModel.AttributeInfo) || sci.Product.IsGiftCard) &&
                                                 sci.Product.VisibleIndividually;

                //allowed quantities
                var allowedQuantities = sci.Product.ParseAllowedQuatities();
                foreach (var qty in allowedQuantities)
                {
                    cartItemModel.AllowedQuantities.Add(new SelectListItem
                    {
                        Text     = qty.ToString(),
                        Value    = qty.ToString(),
                        Selected = sci.Quantity == qty
                    });
                }

                //recurring info
                if (sci.Product.IsRecurring)
                {
                    cartItemModel.RecurringInfo = string.Format(_localizationService.GetResource("ShoppingCart.RecurringPeriod"), sci.Product.RecurringCycleLength, sci.Product.RecurringCyclePeriod.GetLocalizedEnum(_localizationService, _workContext));
                }

                //rental info
                if (sci.Product.IsRental)
                {
                    var rentalStartDate = sci.RentalStartDateUtc.HasValue ? sci.Product.FormatRentalDate(sci.RentalStartDateUtc.Value) : "";
                    var rentalEndDate   = sci.RentalEndDateUtc.HasValue ? sci.Product.FormatRentalDate(sci.RentalEndDateUtc.Value) : "";
                    cartItemModel.RentalInfo = string.Format(_localizationService.GetResource("ShoppingCart.Rental.FormattedDate"),
                                                             rentalStartDate, rentalEndDate);
                }

                //unit prices
                if (sci.Product.CallForPrice)
                {
                    cartItemModel.UnitPrice = _localizationService.GetResource("Products.CallForPrice");
                }
                else
                {
                    decimal taxRate;
                    decimal shoppingCartUnitPriceWithDiscountBase = _taxService.GetProductPrice(sci.Product, _priceCalculationService.GetUnitPrice(sci), out taxRate);
                    decimal shoppingCartUnitPriceWithDiscount     = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartUnitPriceWithDiscountBase, _workContext.WorkingCurrency);
                    cartItemModel.UnitPrice = _priceFormatter.FormatPrice(shoppingCartUnitPriceWithDiscount);
                }
                //subtotal, discount
                if (sci.Product.CallForPrice)
                {
                    cartItemModel.SubTotal = _localizationService.GetResource("Products.CallForPrice");
                }
                else
                {
                    //sub total
                    Discount scDiscount;
                    decimal  shoppingCartItemDiscountBase;
                    decimal  taxRate;
                    decimal  shoppingCartItemSubTotalWithDiscountBase = _taxService.GetProductPrice(sci.Product, _priceCalculationService.GetSubTotal(sci, true, out shoppingCartItemDiscountBase, out scDiscount), out taxRate);
                    decimal  shoppingCartItemSubTotalWithDiscount     = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartItemSubTotalWithDiscountBase, _workContext.WorkingCurrency);
                    cartItemModel.SubTotal = _priceFormatter.FormatPrice(shoppingCartItemSubTotalWithDiscount);

                    //display an applied discount amount
                    if (scDiscount != null)
                    {
                        shoppingCartItemDiscountBase = _taxService.GetProductPrice(sci.Product, shoppingCartItemDiscountBase, out taxRate);
                        if (shoppingCartItemDiscountBase > decimal.Zero)
                        {
                            decimal shoppingCartItemDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartItemDiscountBase, _workContext.WorkingCurrency);
                            cartItemModel.Discount = _priceFormatter.FormatPrice(shoppingCartItemDiscount);
                        }
                    }
                }



                //item warnings
                var itemWarnings = _shoppingCartService.GetShoppingCartItemWarnings(
                    _workContext.CurrentCustomer,
                    sci.ShoppingCartType,
                    sci.Product,
                    sci.StoreId,
                    sci.AttributesXml,
                    sci.CustomerEnteredPrice,
                    sci.RentalStartDateUtc,
                    sci.RentalEndDateUtc,
                    sci.Quantity,
                    false);
                foreach (var warning in itemWarnings)
                {
                    cartItemModel.Warnings.Add(warning);
                }

                model.Items.Add(cartItemModel);
            }

            #endregion

            #region Button payment methods

            var paymentMethods = _paymentService
                                 .LoadActivePaymentMethods(_workContext.CurrentCustomer.Id, _storeContext.CurrentStore.Id)
                                 .Where(pm => pm.PaymentMethodType == PaymentMethodType.Button)
                                 .Where(pm => !pm.HidePaymentMethod(cart))
                                 .ToList();
            foreach (var pm in paymentMethods)
            {
                if (cart.IsRecurring() && pm.RecurringPaymentType == RecurringPaymentType.NotSupported)
                {
                    continue;
                }

                string actionName;
                string controllerName;
                RouteValueDictionary routeValues;
                pm.GetPaymentInfoRoute(out actionName, out controllerName, out routeValues);

                model.ButtonPaymentMethodActionNames.Add(actionName);
                model.ButtonPaymentMethodControllerNames.Add(controllerName);
                model.ButtonPaymentMethodRouteValues.Add(routeValues);
            }

            #endregion

            #region Order review data

            if (prepareAndDisplayOrderReviewData)
            {
                model.OrderReviewData.Display = true;

                //billing info
                var billingAddress = _workContext.CurrentCustomer.BillingAddress;
                if (billingAddress != null)
                {
                    model.OrderReviewData.BillingAddress.PrepareModel(
                        address: billingAddress,
                        excludeProperties: false,
                        addressSettings: _addressSettings,
                        addressAttributeFormatter: _addressAttributeFormatter);
                }

                //shipping info
                if (cart.RequiresShipping())
                {
                    model.OrderReviewData.IsShippable = true;

                    if (_shippingSettings.AllowPickUpInStore)
                    {
                        model.OrderReviewData.SelectedPickUpInStore = _workContext.CurrentCustomer.GetAttribute <bool>(SystemCustomerAttributeNames.SelectedPickUpInStore, _storeContext.CurrentStore.Id);
                    }

                    if (!model.OrderReviewData.SelectedPickUpInStore)
                    {
                        var shippingAddress = _workContext.CurrentCustomer.ShippingAddress;
                        if (shippingAddress != null)
                        {
                            model.OrderReviewData.ShippingAddress.PrepareModel(
                                address: shippingAddress,
                                excludeProperties: false,
                                addressSettings: _addressSettings,
                                addressAttributeFormatter: _addressAttributeFormatter);
                        }
                    }


                    //selected shipping method
                    var shippingOption = _workContext.CurrentCustomer.GetAttribute <ShippingOption>(SystemCustomerAttributeNames.SelectedShippingOption, _storeContext.CurrentStore.Id);
                    if (shippingOption != null)
                    {
                        model.OrderReviewData.ShippingMethod = shippingOption.Name;
                    }
                }
                //payment info
                var selectedPaymentMethodSystemName = _workContext.CurrentCustomer.GetAttribute <string>(
                    SystemCustomerAttributeNames.SelectedPaymentMethod, _storeContext.CurrentStore.Id);
                var paymentMethod = _paymentService.LoadPaymentMethodBySystemName(selectedPaymentMethodSystemName);
                model.OrderReviewData.PaymentMethod = paymentMethod != null?paymentMethod.GetLocalizedFriendlyName(_localizationService, _workContext.WorkingLanguage.Id) : "";
            }
            #endregion
        }
Example #14
0
        GetShoppingCartSubTotal(IList <ShoppingCartItem> cart, bool includingTax)
        {
            var discountAmount          = decimal.Zero;
            var appliedDiscounts        = new List <AppliedDiscount>();
            var subTotalWithoutDiscount = decimal.Zero;
            var subTotalWithDiscount    = decimal.Zero;
            var taxRates = new SortedDictionary <decimal, decimal>();

            if (!cart.Any())
            {
                return(discountAmount, appliedDiscounts, subTotalWithoutDiscount, subTotalWithDiscount, taxRates);
            }

            //get the customer
            Customer customer = _workContext.CurrentCustomer;
            var      currency = await _currencyService.GetPrimaryExchangeRateCurrency();

            //sub totals
            decimal subTotalExclTaxWithoutDiscount = decimal.Zero;
            decimal subTotalInclTaxWithoutDiscount = decimal.Zero;

            foreach (var shoppingCartItem in cart)
            {
                var subtotal = await _priceCalculationService.GetSubTotal(shoppingCartItem);

                decimal sciSubTotal = subtotal.subTotal;
                var     product     = await _productService.GetProductById(shoppingCartItem.ProductId);

                decimal taxRate;
                var     pricesExcl = await _taxService.GetProductPrice(product, sciSubTotal, false, customer);

                decimal sciExclTax = pricesExcl.productprice;

                var pricesIncl = await _taxService.GetProductPrice(product, sciSubTotal, true, customer);

                decimal sciInclTax = pricesIncl.productprice;
                taxRate = pricesIncl.taxRate;

                subTotalExclTaxWithoutDiscount += sciExclTax;
                subTotalInclTaxWithoutDiscount += sciInclTax;

                //tax rates
                decimal sciTax = sciInclTax - sciExclTax;
                if (taxRate > decimal.Zero && sciTax > decimal.Zero)
                {
                    if (!taxRates.ContainsKey(taxRate))
                    {
                        taxRates.Add(taxRate, sciTax);
                    }
                    else
                    {
                        taxRates[taxRate] = taxRates[taxRate] + sciTax;
                    }
                }
            }

            //checkout attributes
            if (customer != null)
            {
                var checkoutAttributesXml = customer.GetAttributeFromEntity <string>(SystemCustomerAttributeNames.CheckoutAttributes, _storeContext.CurrentStore.Id);
                var attributeValues       = await _checkoutAttributeParser.ParseCheckoutAttributeValues(checkoutAttributesXml);

                if (attributeValues != null)
                {
                    foreach (var attributeValue in attributeValues)
                    {
                        decimal taxRate;
                        var     checkoutAttributePriceExclTax = await _taxService.GetCheckoutAttributePrice(attributeValue, false, customer);

                        decimal caExclTax = checkoutAttributePriceExclTax.checkoutPrice;

                        var checkoutAttributePriceInclTax = await _taxService.GetCheckoutAttributePrice(attributeValue, true, customer);

                        decimal caInclTax = checkoutAttributePriceInclTax.checkoutPrice;

                        taxRate = checkoutAttributePriceInclTax.taxRate;

                        subTotalExclTaxWithoutDiscount += caExclTax;
                        subTotalInclTaxWithoutDiscount += caInclTax;

                        //tax rates
                        decimal caTax = caInclTax - caExclTax;
                        if (taxRate > decimal.Zero && caTax > decimal.Zero)
                        {
                            if (!taxRates.ContainsKey(taxRate))
                            {
                                taxRates.Add(taxRate, caTax);
                            }
                            else
                            {
                                taxRates[taxRate] = taxRates[taxRate] + caTax;
                            }
                        }
                    }
                }
            }

            //subtotal without discount
            subTotalWithoutDiscount = includingTax ? subTotalInclTaxWithoutDiscount : subTotalExclTaxWithoutDiscount;

            if (subTotalWithoutDiscount < decimal.Zero)
            {
                subTotalWithoutDiscount = decimal.Zero;
            }

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
            {
                subTotalWithoutDiscount = RoundingHelper.RoundPrice(subTotalWithoutDiscount, currency);
            }
            //We calculate discount amount on order subtotal excl tax (discount first)
            //calculate discount amount ('Applied to order subtotal' discount)
            var orderSubtotalDiscount = await GetOrderSubtotalDiscount(customer, subTotalExclTaxWithoutDiscount);

            decimal discountAmountExclTax = orderSubtotalDiscount.ordersubtotaldiscount;

            appliedDiscounts = orderSubtotalDiscount.appliedDiscounts;

            if (subTotalExclTaxWithoutDiscount < discountAmountExclTax)
            {
                discountAmountExclTax = subTotalExclTaxWithoutDiscount;
            }
            decimal discountAmountInclTax = discountAmountExclTax;
            //subtotal with discount (excl tax)
            decimal subTotalExclTaxWithDiscount = subTotalExclTaxWithoutDiscount - discountAmountExclTax;
            decimal subTotalInclTaxWithDiscount = subTotalExclTaxWithDiscount;

            //add tax for shopping items & checkout attributes
            var tempTaxRates = new Dictionary <decimal, decimal>(taxRates);

            foreach (KeyValuePair <decimal, decimal> kvp in tempTaxRates)
            {
                decimal taxRate  = kvp.Key;
                decimal taxValue = kvp.Value;

                if (taxValue != decimal.Zero)
                {
                    //discount the tax amount that applies to subtotal items
                    if (subTotalExclTaxWithoutDiscount > decimal.Zero)
                    {
                        decimal discountTax = taxRates[taxRate] * (discountAmountExclTax / subTotalExclTaxWithoutDiscount);
                        discountAmountInclTax += discountTax;
                        taxValue = taxRates[taxRate] - discountTax;
                        if (_shoppingCartSettings.RoundPricesDuringCalculation)
                        {
                            taxValue = RoundingHelper.RoundPrice(taxValue, currency);
                        }
                        taxRates[taxRate] = taxValue;
                    }

                    //subtotal with discount (incl tax)
                    subTotalInclTaxWithDiscount += taxValue;
                }
            }

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
            {
                discountAmountInclTax = RoundingHelper.RoundPrice(discountAmountInclTax, currency);
                discountAmountExclTax = RoundingHelper.RoundPrice(discountAmountExclTax, currency);
            }

            if (includingTax)
            {
                subTotalWithDiscount = subTotalInclTaxWithDiscount;
                discountAmount       = discountAmountInclTax;
            }
            else
            {
                subTotalWithDiscount = subTotalExclTaxWithDiscount;
                discountAmount       = discountAmountExclTax;
            }

            if (subTotalWithDiscount < decimal.Zero)
            {
                subTotalWithDiscount = decimal.Zero;
            }

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
            {
                subTotalWithDiscount = RoundingHelper.RoundPrice(subTotalWithDiscount, currency);
            }

            return(discountAmount, appliedDiscounts, subTotalWithoutDiscount, subTotalWithDiscount, taxRates);
        }
        /// <summary>
        /// Add order items to the request request metadata
        /// </summary>
        /// <param name="parameters">Query parameters</param>
        /// <param name="postProcessPaymentRequest">Payment info required for an order processing</param>
        private void AddOrderItemsMetaData(TransactionInitializeRequest request, PostProcessPaymentRequest postProcessPaymentRequest)
        {
            //upload order items
            var cartTotal        = decimal.Zero;
            var roundedCartTotal = decimal.Zero;
            var itemCount        = 1;

            //add shopping cart items
            foreach (var item in postProcessPaymentRequest.Order.OrderItems)
            {
                var roundedItemPrice = Math.Round(item.UnitPriceExclTax, 2);

                //add query parameters
                request.MetadataObject[$"item_name_{itemCount}"] = item.Product.Name;
                request.MetadataObject[$"amount_{itemCount}"]    = roundedItemPrice.ToString("0.00", CultureInfo.InvariantCulture);
                request.MetadataObject[$"quantity_{itemCount}"]  = item.Quantity.ToString();

                cartTotal        += item.PriceExclTax;
                roundedCartTotal += roundedItemPrice * item.Quantity;
                itemCount++;
            }

            //add checkout attributes as order items
            var checkoutAttributeValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(postProcessPaymentRequest.Order.CheckoutAttributesXml);

            foreach (var attributeValue in checkoutAttributeValues)
            {
                var attributePrice        = _taxService.GetCheckoutAttributePrice(attributeValue, false, postProcessPaymentRequest.Order.Customer);
                var roundedAttributePrice = Math.Round(attributePrice, 2);

                //add query parameters
                if (attributeValue.CheckoutAttribute == null)
                {
                    continue;
                }

                request.MetadataObject[$"item_name_{itemCount}"] = attributeValue.CheckoutAttribute.Name;
                request.MetadataObject[$"amount_{itemCount}"]    = roundedAttributePrice.ToString("0.00", CultureInfo.InvariantCulture);
                request.MetadataObject[$"quantity_{itemCount}"]  = "1";

                cartTotal        += attributePrice;
                roundedCartTotal += roundedAttributePrice;
                itemCount++;
            }

            //add shipping fee as a separate order item, if it has price
            var roundedShippingPrice = Math.Round(postProcessPaymentRequest.Order.OrderShippingExclTax, 2);

            if (roundedShippingPrice > decimal.Zero)
            {
                request.MetadataObject[$"item_name_{itemCount}"] = "Shipping fee";
                request.MetadataObject[$"amount_{itemCount}"]    = roundedShippingPrice.ToString("0.00", CultureInfo.InvariantCulture);
                request.MetadataObject[$"quantity_{itemCount}"]  = "1";

                cartTotal        += postProcessPaymentRequest.Order.OrderShippingExclTax;
                roundedCartTotal += roundedShippingPrice;
                itemCount++;
            }

            //add payment method additional fee as a separate order item, if it has price
            var roundedPaymentMethodPrice = Math.Round(postProcessPaymentRequest.Order.PaymentMethodAdditionalFeeExclTax, 2);

            if (roundedPaymentMethodPrice > decimal.Zero)
            {
                request.MetadataObject[$"item_name_{itemCount}"] = "Payment method fee";
                request.MetadataObject[$"amount_{itemCount}"]    = roundedPaymentMethodPrice.ToString("0.00", CultureInfo.InvariantCulture);
                request.MetadataObject[$"quantity_{itemCount}"]  = "1";

                cartTotal        += postProcessPaymentRequest.Order.PaymentMethodAdditionalFeeExclTax;
                roundedCartTotal += roundedPaymentMethodPrice;
                itemCount++;
            }

            //add tax as a separate order item, if it has positive amount
            var roundedTaxAmount = Math.Round(postProcessPaymentRequest.Order.OrderTax, 2);

            if (roundedTaxAmount > decimal.Zero)
            {
                request.MetadataObject[$"item_name_{itemCount}"] = "Tax amount";
                request.MetadataObject[$"amount_{itemCount}"]    = roundedTaxAmount.ToString("0.00", CultureInfo.InvariantCulture);
                request.MetadataObject[$"quantity_{itemCount}"]  = "1";

                cartTotal        += postProcessPaymentRequest.Order.OrderTax;
                roundedCartTotal += roundedTaxAmount;
            }

            if (cartTotal > postProcessPaymentRequest.Order.OrderTotal)
            {
                //get the difference between what the order total is and what it should be and use that as the "discount"
                var discountTotal = Math.Round(cartTotal - postProcessPaymentRequest.Order.OrderTotal, 2);
                roundedCartTotal -= discountTotal;

                //gift card or rewarded point amount applied to cart in nopCommerce - shows in Paystack as "discount"
                request.MetadataObject["discount_amount_cart"] = discountTotal.ToString("0.00", CultureInfo.InvariantCulture);
            }

            //save order total that actually sent to Paystack (used for PDT order total validation)
            _genericAttributeService.SaveAttribute(postProcessPaymentRequest.Order, PaystackHelper.OrderTotalSentToPaystack, roundedCartTotal);
        }
        public PaymentDetailsType[] GetPaymentDetails(IList <ShoppingCartItem> cart)
        {
            var currencyCode = _payPalCurrencyCodeParser.GetCurrencyCodeType(_workContext.WorkingCurrency);

            var orderTotalWithDiscount = _payPalCartItemService.GetCartTotal(cart, out var orderTotalDiscountAmount,
                                                                             out _,
                                                                             out _,
                                                                             out _,
                                                                             out var appliedGiftCards);

            var itemTotalWithDiscount = _payPalCartItemService.GetCartItemTotal(cart,
                                                                                out var subTotalDiscountAmount,
                                                                                out _,
                                                                                out _,
                                                                                out _);

            var giftCardsAmount = appliedGiftCards.Sum(x => x.AmountCanBeUsed);

            itemTotalWithDiscount = itemTotalWithDiscount - orderTotalDiscountAmount - giftCardsAmount;

            var taxTotal      = _payPalCartItemService.GetTax(cart);
            var shippingTotal = _payPalCartItemService.GetShippingTotal(cart);
            var items         = GetPaymentDetailsItems(cart);

            // checkout attributes
            var customer = _workContext.CurrentCustomer;

            if (customer != null)
            {
                var checkoutAttributesXml = _genericAttributeService.GetAttribute <string>(customer, NopCustomerDefaults.CheckoutAttributes, _storeContext.CurrentStore.Id);
                var caValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(checkoutAttributesXml);
                if (caValues != null)
                {
                    foreach (var caValue in caValues)
                    {
                        if (caValue.PriceAdjustment <= 0)
                        {
                            continue;
                        }

                        var checkoutAttrItem = new PaymentDetailsItemType
                        {
                            Name     = caValue.Name,
                            Amount   = caValue.PriceAdjustment.GetBasicAmountType(currencyCode),
                            Quantity = "1"
                        };

                        items.Add(checkoutAttrItem);
                    }
                }
            }

            if (orderTotalDiscountAmount > 0 || subTotalDiscountAmount > 0)
            {
                var discountItem = new PaymentDetailsItemType
                {
                    Name     = "Discount",
                    Amount   = (-orderTotalDiscountAmount + -subTotalDiscountAmount).GetBasicAmountType(currencyCode),
                    Quantity = "1"
                };

                items.Add(discountItem);
            }

            foreach (var appliedGiftCard in appliedGiftCards)
            {
                var giftCardItem = new PaymentDetailsItemType
                {
                    Name     = $"Gift Card ({appliedGiftCard.GiftCard.GiftCardCouponCode})",
                    Amount   = (-appliedGiftCard.AmountCanBeUsed).GetBasicAmountType(currencyCode),
                    Quantity = "1"
                };

                items.Add(giftCardItem);
            }

            return(new[]
            {
                new PaymentDetailsType
                {
                    OrderTotal = orderTotalWithDiscount.GetBasicAmountType(currencyCode),
                    ItemTotal = itemTotalWithDiscount.GetBasicAmountType(currencyCode),
                    TaxTotal = taxTotal.GetBasicAmountType(currencyCode),
                    ShippingTotal = shippingTotal.GetBasicAmountType(currencyCode),
                    PaymentDetailsItem = items.ToArray(),
                    PaymentAction = _payPalExpressCheckoutPaymentSettings.PaymentAction,
                    PaymentActionSpecified = true,
                    ButtonSource = PayPalHelper.BnCode
                }
            });
        }
Example #17
0
        public string AddUpdateOrderToNebim(Core.Domain.Orders.Order order, string customerCode, Guid?shippingPostalAddressID, Guid?billingPostalAddressID)
        {
            var      nebimIntegrationProvider = LoadNebimIntegrationServiceBySystemName("Misc.Nebim");
            string   description = order.Id.ToString();
            DateTime?orderDate   = _dateTimeHelper.ConvertToUserTime(order.CreatedOnUtc, TimeZoneInfo.Utc);

            #region parameters
            //string itemCode,
            //string colorCode,
            //string itemDim1Code,
            //string itemDim2Code,
            //int quantity,
            //decimal priceExcludingTax,
            //decimal priceIncludingTax,
            //in the rest tupple
            //barcode
            #endregion parameters
            IList <Tuple <string, string, string, string, int, decimal?, decimal?, Tuple <string> > > items = new List <Tuple <string, string, string, string, int, decimal?, decimal?, Tuple <string> > >();

            foreach (var orderItem in order.OrderProductVariants)
            {
                //string itemCode = string.IsNullOrWhiteSpace(orderItem.ProductVariant.ManufacturerPartNumber) ? orderItem.ProductVariant.Sku : orderItem.ProductVariant.ManufacturerPartNumber;
                string itemCode = string.IsNullOrWhiteSpace(orderItem.ProductVariant.ManufacturerPartNumber) ? GetProductCode(orderItem.ProductVariant) : orderItem.ProductVariant.ManufacturerPartNumber;

                var    barcode      = orderItem.ProductVariant.Gtin;
                string colorCode    = null;
                string itemDim1Code = null;
                var    pvaValues    = _productAttributeParser.ParseProductVariantAttributeValues(orderItem.AttributesXml);
                var    pvavColor    = pvaValues.FirstOrDefault(x => x.ProductVariantAttribute.ProductAttribute.Id == _NebimIntegrationSettings.ColorAttributeId);
                var    pvavDims     = pvaValues.Where(x => (x.ProductVariantAttribute.ProductAttribute.Id == _NebimIntegrationSettings.Dim1AttributeId) || (x.ProductVariantAttribute.ProductAttribute.Id == _NebimIntegrationSettings.Dim2AttributeId)).ToList();

                if (pvavColor != null)
                {
                    colorCode = pvavColor.ProductAttributeOptionId.ToString();

                    if (pvavDims.Count > 0)
                    {
                        var dim1 = pvavDims.First();
                        itemDim1Code = dim1.Name;//not localized!
                    }
                    else
                    {
                        itemDim1Code = _NebimIntegrationSettings.API_StandardSizeCode;
                    }
                }
                else
                {
                    colorCode = _NebimIntegrationSettings.API_StandardColorCode;
                    if (pvavDims.Count > 0)
                    {
                        var dim1 = pvavDims.First();
                        itemDim1Code = dim1.Name;//not localized!
                    }
                    else
                    {
                        itemDim1Code = _NebimIntegrationSettings.API_StandardSizeCode;
                    }
                }
                string  itemDim2Code         = null;
                int     quantity             = orderItem.Quantity;
                decimal?discountIncudingTax  = orderItem.DiscountAmountInclTax;
                decimal?priceIncludingTax    = orderItem.UnitPriceInclTax;
                string  orderItemDescription = null;

                Tuple <string, string, string, string, int, decimal?, decimal?, Tuple <string> > item = Tuple.Create <string, string, string, string, int, decimal?, decimal?, string>(itemCode, colorCode, itemDim1Code, itemDim2Code, quantity, discountIncudingTax, priceIncludingTax, barcode);
                items.Add(item);
            }
            decimal?discountAmount = null;
            decimal?giftCardAmount = null;
            double? discountRate   = null;
            //Discount discountToOrderTotal = null;
            string discountNames = null;//"--" seperated discount names.

            if (order.GiftCardUsageHistory != null && order.GiftCardUsageHistory.Count > 0)
            {
                giftCardAmount = order.GiftCardUsageHistory.Sum(x => x.UsedValue);
            }
            if (order.DiscountUsageHistory != null && order.DiscountUsageHistory.Count > 0)
            {
                //order total discount
                //discountToOrderTotal = order.DiscountUsageHistory.Where(n => (n.Discount.DiscountTypeId == 1 || n.Discount.DiscountTypeId == 20)).Select(n => n.Discount).FirstOrDefault();
                //all discount names sperated by "--"
                discountNames = string.Join("--", order.DiscountUsageHistory.Select(n => n.Discount.Name));
            }
            if (order.DiscountUsageHistory.Any(n => (n.Discount.DiscountTypeId == 1 || n.Discount.DiscountTypeId == 20)))
            {
                //discountRate = (double)((order.OrderDiscount / (order.OrderTotal + order.OrderDiscount)) * 100);
                discountAmount = order.OrderDiscount;
            }
            if (discountAmount.HasValue || giftCardAmount.HasValue)
            {
                decimal dsc = discountAmount.HasValue ? discountAmount.Value : 0;
                decimal gft = giftCardAmount.HasValue ? giftCardAmount.Value : 0;
                discountRate = (double)(((dsc + gft) / (order.OrderTotal + dsc + gft)) * 100);
            }
            //shipment expense
            decimal shippingCost     = order.OrderShippingInclTax;
            decimal giftBoxCost      = 0;
            var     caValues         = _checkoutAttributeParser.ParseCheckoutAttributeValues(order.CheckoutAttributesXml);
            var     giftBoxAttribute = caValues.FirstOrDefault(x => x.PriceAdjustment > 0);
            if (giftBoxAttribute != null)
            {
                giftBoxCost = giftBoxAttribute.PriceAdjustment;
            }
            string currencyCode = "TRY";
            // if barcode is null save order line(s) via color/dim values else save via barcode
            string orderNumber = nebimIntegrationProvider.AddUpdateOrderToNebim(description, orderDate, customerCode, shippingPostalAddressID, billingPostalAddressID, items, null, discountRate, currencyCode, shippingCost, giftBoxCost, discountNames);
            return(orderNumber);
        }
        /// <summary>
        /// Generate string (URL) for redirection
        /// </summary>
        /// <param name="postProcessPaymentRequest">Payment info required for an order processing</param>
        /// <param name="passProductNamesAndTotals">A value indicating whether to pass product names and totals</param>
        private string GenerationCallBackUrl(PostProcessPaymentRequest postProcessPaymentRequest, bool passProductNamesAndTotals, long transactionid)
        {
            var builder = new StringBuilder();

            builder.Append(_webHelper.GetStoreLocation(false) + "Plugins/PaymentMellatBank/PDTHandler");
            var cmd = passProductNamesAndTotals
                ? "_cart"
                : "_xclick";

            builder.AppendFormat("?cmd={0}", cmd);
            builder.AppendFormat("&transactionid={0}", transactionid);
            builder.AppendFormat("&orderid={0}", postProcessPaymentRequest.Order.Id);
            if (passProductNamesAndTotals)
            {
                builder.AppendFormat("&upload=1");

                //get the items in the cart
                decimal cartTotal        = decimal.Zero;
                var     cartTotalRounded = decimal.Zero;
                var     cartItems        = postProcessPaymentRequest.Order.OrderItems;
                int     x = 1;
                foreach (var item in cartItems)
                {
                    var unitPriceExclTax = item.UnitPriceExclTax;
                    var priceExclTax     = item.PriceExclTax;
                    //round
                    var unitPriceExclTaxRounded = Math.Round(unitPriceExclTax, 2);
                    builder.AppendFormat("&item_name_" + x + "={0}", HttpUtility.UrlEncode(item.Product.Name));
                    builder.AppendFormat("&amount_" + x + "={0}", unitPriceExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture));
                    builder.AppendFormat("&quantity_" + x + "={0}", item.Quantity);
                    x++;
                    cartTotal        += priceExclTax;
                    cartTotalRounded += unitPriceExclTaxRounded * item.Quantity;
                }

                //the checkout attributes that have a cost value and send them to MellatBank as items to be paid for
                var attributeValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(postProcessPaymentRequest.Order.CheckoutAttributesXml);
                foreach (var val in attributeValues)
                {
                    var attPrice = _taxService.GetCheckoutAttributePrice(val, false, postProcessPaymentRequest.Order.Customer);
                    //round
                    var attPriceRounded = Math.Round(attPrice, 2);
                    if (attPrice > decimal.Zero) //if it has a price
                    {
                        var attribute = val.CheckoutAttribute;
                        if (attribute != null)
                        {
                            var attName = attribute.Name;                                                                                  //set the name
                            builder.AppendFormat("&item_name_" + x + "={0}", HttpUtility.UrlEncode(attName));                              //name
                            builder.AppendFormat("&amount_" + x + "={0}", attPriceRounded.ToString("0.00", CultureInfo.InvariantCulture)); //amount
                            builder.AppendFormat("&quantity_" + x + "={0}", 1);                                                            //quantity
                            x++;
                            cartTotal        += attPrice;
                            cartTotalRounded += attPriceRounded;
                        }
                    }
                }

                //order totals

                //shipping
                var orderShippingExclTax        = postProcessPaymentRequest.Order.OrderShippingExclTax;
                var orderShippingExclTaxRounded = Math.Round(orderShippingExclTax, 2);
                if (orderShippingExclTax > decimal.Zero)
                {
                    builder.AppendFormat("&item_name_" + x + "={0}", "Shipping fee");
                    builder.AppendFormat("&amount_" + x + "={0}", orderShippingExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture));
                    builder.AppendFormat("&quantity_" + x + "={0}", 1);
                    x++;
                    cartTotal        += orderShippingExclTax;
                    cartTotalRounded += orderShippingExclTaxRounded;
                }

                //payment method additional fee
                var paymentMethodAdditionalFeeExclTax        = postProcessPaymentRequest.Order.PaymentMethodAdditionalFeeExclTax;
                var paymentMethodAdditionalFeeExclTaxRounded = Math.Round(paymentMethodAdditionalFeeExclTax, 2);
                if (paymentMethodAdditionalFeeExclTax > decimal.Zero)
                {
                    builder.AppendFormat("&item_name_" + x + "={0}", "Payment method fee");
                    builder.AppendFormat("&amount_" + x + "={0}", paymentMethodAdditionalFeeExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture));
                    builder.AppendFormat("&quantity_" + x + "={0}", 1);
                    x++;
                    cartTotal        += paymentMethodAdditionalFeeExclTax;
                    cartTotalRounded += paymentMethodAdditionalFeeExclTaxRounded;
                }

                //tax
                var orderTax        = postProcessPaymentRequest.Order.OrderTax;
                var orderTaxRounded = Math.Round(orderTax, 2);
                if (orderTax > decimal.Zero)
                {
                    //builder.AppendFormat("&tax_1={0}", orderTax.ToString("0.00", CultureInfo.InvariantCulture));

                    //add tax as item
                    builder.AppendFormat("&item_name_" + x + "={0}", HttpUtility.UrlEncode("Sales Tax"));                          //name
                    builder.AppendFormat("&amount_" + x + "={0}", orderTaxRounded.ToString("0.00", CultureInfo.InvariantCulture)); //amount
                    builder.AppendFormat("&quantity_" + x + "={0}", 1);                                                            //quantity

                    cartTotal        += orderTax;
                    cartTotalRounded += orderTaxRounded;
                    x++;
                }

                if (cartTotal > postProcessPaymentRequest.Order.OrderTotal)
                {
                    /* Take the difference between what the order total is and what it should be and use that as the "discount".
                     * The difference equals the amount of the gift card and/or reward points used.
                     */
                    decimal discountTotal = cartTotal - postProcessPaymentRequest.Order.OrderTotal;
                    discountTotal     = Math.Round(discountTotal, 2);
                    cartTotalRounded -= discountTotal;
                    //gift card or rewared point amount applied to cart in nopCommerce - shows in MellatBank as "discount"
                    builder.AppendFormat("&discount_amount_cart={0}", discountTotal.ToString("0.00", CultureInfo.InvariantCulture));
                }

                //save order total that actually sent to MellatBank (used for PDT order total validation)
                _genericAttributeService.SaveAttribute(postProcessPaymentRequest.Order, "OrderMellatBankSaleReferenceId", cartTotalRounded);
            }
            else
            {
                //pass order total
                builder.AppendFormat("&item_name=Order Number {0}", postProcessPaymentRequest.Order.Id);
                var orderTotal = Math.Round(postProcessPaymentRequest.Order.OrderTotal, 2);
                builder.AppendFormat("&amount={0}", orderTotal.ToString("0.00", CultureInfo.InvariantCulture));

                //save order total that actually sent to MellatBank (used for PDT order total validation)
                _genericAttributeService.SaveAttribute(postProcessPaymentRequest.Order, "OrderMellatBankSaleReferenceId", orderTotal);
            }

            builder.AppendFormat("&custom={0}", postProcessPaymentRequest.Order.OrderGuid);
            builder.AppendFormat("&charset={0}", "utf-8");
            builder.AppendFormat("&bn={0}", BN_CODE);
            builder.Append(string.Format("&no_note=1&currency_code={0}", HttpUtility.UrlEncode(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode)));
            builder.AppendFormat("&invoice={0}", postProcessPaymentRequest.Order.Id);
            builder.AppendFormat("&rm=2", new object[0]);
            if (postProcessPaymentRequest.Order.ShippingStatus != ShippingStatus.ShippingNotRequired)
            {
                builder.AppendFormat("&no_shipping=2", new object[0]);
            }
            else
            {
                builder.AppendFormat("&no_shipping=1", new object[0]);
            }

            return(builder.ToString());
        }
        public override async Task <(decimal discountAmount, List <Discount> appliedDiscounts, decimal subTotalWithoutDiscount, decimal subTotalWithDiscount, SortedDictionary <decimal, decimal> taxRates)> GetShoppingCartSubTotalAsync(
            IList <ShoppingCartItem> cart,
            bool includingTax)
        {
            var discountAmount          = decimal.Zero;
            var appliedDiscounts        = new List <Discount>();
            var subTotalWithoutDiscount = decimal.Zero;
            var subTotalWithDiscount    = decimal.Zero;
            var taxRates = new SortedDictionary <decimal, decimal>();

            if (!cart.Any())
            {
                return(discountAmount, appliedDiscounts, subTotalWithoutDiscount, subTotalWithDiscount, taxRates);
            }

            //get the customer
            var customer = await _customerService.GetShoppingCartCustomerAsync(cart);

            //sub totals
            var subTotalExclTaxWithoutDiscount = decimal.Zero;
            var subTotalInclTaxWithoutDiscount = decimal.Zero;

            foreach (var shoppingCartItem in cart)
            {
                var sciSubTotal = (await _shoppingCartService.GetSubTotalAsync(shoppingCartItem, true)).subTotal;
                var product     = await _productService.GetProductByIdAsync(shoppingCartItem.ProductId);

                var(sciExclTax, taxRate) = await _taxService.GetProductPriceAsync(product, sciSubTotal, false, customer);

                // custom
                var(_, sciInclTax) = await _warrantyTaxService.CalculateWarrantyTaxAsync(shoppingCartItem, customer, sciExclTax);

                subTotalExclTaxWithoutDiscount += sciExclTax;
                subTotalInclTaxWithoutDiscount += sciInclTax;

                //tax rates
                var sciTax = sciInclTax - sciExclTax;
                if (taxRate <= decimal.Zero || sciTax <= decimal.Zero)
                {
                    continue;
                }

                if (!taxRates.ContainsKey(taxRate))
                {
                    taxRates.Add(taxRate, sciTax);
                }
                else
                {
                    taxRates[taxRate] = taxRates[taxRate] + sciTax;
                }
            }

            //checkout attributes
            if (customer != null)
            {
                var checkoutAttributesXml = await _genericAttributeService.GetAttributeAsync <string>(customer, NopCustomerDefaults.CheckoutAttributes, (await _storeContext.GetCurrentStoreAsync()).Id);

                var attributeValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(checkoutAttributesXml);
                if (attributeValues != null)
                {
                    await foreach (var(attribute, values) in attributeValues)
                    {
                        await foreach (var attributeValue in values)
                        {
                            var(caExclTax, taxRate) = await _taxService.GetCheckoutAttributePriceAsync(attribute, attributeValue, false, customer);

                            var(caInclTax, _) = await _taxService.GetCheckoutAttributePriceAsync(attribute, attributeValue, true, customer);

                            subTotalExclTaxWithoutDiscount += caExclTax;
                            subTotalInclTaxWithoutDiscount += caInclTax;

                            //tax rates
                            var caTax = caInclTax - caExclTax;
                            if (taxRate <= decimal.Zero || caTax <= decimal.Zero)
                            {
                                continue;
                            }

                            if (!taxRates.ContainsKey(taxRate))
                            {
                                taxRates.Add(taxRate, caTax);
                            }
                            else
                            {
                                taxRates[taxRate] = taxRates[taxRate] + caTax;
                            }
                        }
                    }
                }
            }

            //subtotal without discount
            subTotalWithoutDiscount = includingTax ? subTotalInclTaxWithoutDiscount : subTotalExclTaxWithoutDiscount;
            if (subTotalWithoutDiscount < decimal.Zero)
            {
                subTotalWithoutDiscount = decimal.Zero;
            }

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
            {
                subTotalWithoutDiscount = await _priceCalculationService.RoundPriceAsync(subTotalWithoutDiscount);
            }

            //We calculate discount amount on order subtotal excl tax (discount first)
            //calculate discount amount ('Applied to order subtotal' discount)
            decimal discountAmountExclTax;

            (discountAmountExclTax, appliedDiscounts) = await GetOrderSubtotalDiscountAsync(customer, subTotalExclTaxWithoutDiscount);

            if (subTotalExclTaxWithoutDiscount < discountAmountExclTax)
            {
                discountAmountExclTax = subTotalExclTaxWithoutDiscount;
            }
            var discountAmountInclTax = discountAmountExclTax;
            //subtotal with discount (excl tax)
            var subTotalExclTaxWithDiscount = subTotalExclTaxWithoutDiscount - discountAmountExclTax;
            var subTotalInclTaxWithDiscount = subTotalExclTaxWithDiscount;

            //add tax for shopping items & checkout attributes
            var tempTaxRates = new Dictionary <decimal, decimal>(taxRates);

            foreach (var kvp in tempTaxRates)
            {
                var taxRate  = kvp.Key;
                var taxValue = kvp.Value;

                if (taxValue == decimal.Zero)
                {
                    continue;
                }

                //discount the tax amount that applies to subtotal items
                if (subTotalExclTaxWithoutDiscount > decimal.Zero)
                {
                    var discountTax = taxRates[taxRate] * (discountAmountExclTax / subTotalExclTaxWithoutDiscount);
                    discountAmountInclTax += discountTax;
                    taxValue = taxRates[taxRate] - discountTax;
                    if (_shoppingCartSettings.RoundPricesDuringCalculation)
                    {
                        taxValue = await _priceCalculationService.RoundPriceAsync(taxValue);
                    }
                    taxRates[taxRate] = taxValue;
                }

                //subtotal with discount (incl tax)
                subTotalInclTaxWithDiscount += taxValue;
            }

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
            {
                discountAmountInclTax = await _priceCalculationService.RoundPriceAsync(discountAmountInclTax);

                discountAmountExclTax = await _priceCalculationService.RoundPriceAsync(discountAmountExclTax);
            }

            if (includingTax)
            {
                subTotalWithDiscount = subTotalInclTaxWithDiscount;
                discountAmount       = discountAmountInclTax;
            }
            else
            {
                subTotalWithDiscount = subTotalExclTaxWithDiscount;
                discountAmount       = discountAmountExclTax;
            }

            if (subTotalWithDiscount < decimal.Zero)
            {
                subTotalWithDiscount = decimal.Zero;
            }

            if (_shoppingCartSettings.RoundPricesDuringCalculation)
            {
                subTotalWithDiscount = await _priceCalculationService.RoundPriceAsync(subTotalWithDiscount);
            }

            return(discountAmount, appliedDiscounts, subTotalWithoutDiscount, subTotalWithDiscount, taxRates);
        }
        private void AddOrderLines(PayexInterface payex, string orderRef, Order order)
        {
            //get the items in the cart
            decimal cartTotal = decimal.Zero;
            var     cartItems = order.OrderItems;
            int     itemIndex = 1;

            foreach (var item in cartItems)
            {
                AddOrderLine(
                    payex, orderRef, item.Product.Sku ?? string.Format("{0}", itemIndex++), item.Product.Name,
                    item.Quantity, item.PriceInclTax)
                .GetAwaiter().GetResult();
                cartTotal += item.PriceInclTax;
            }

            //the checkout attributes that have a value and send them to PayEx as items to be paid for
            var caValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(order.CheckoutAttributesXml);

            foreach (var val in caValues)
            {
                var caPriceInclTax   = _taxService.GetCheckoutAttributePrice(val, true, order.Customer);
                CheckoutAttribute ca = val.CheckoutAttribute;
                if (caPriceInclTax > decimal.Zero && ca != null) //if it has a price
                {
                    AddOrderLine(payex, orderRef, string.Format("{0}", itemIndex++), ca.Name, 1, caPriceInclTax)
                    .GetAwaiter().GetResult();
                    cartTotal += caPriceInclTax;
                }
            }

            //order totals

            //shipping
            var orderShippingInclTax = order.OrderShippingInclTax;

            if (orderShippingInclTax > decimal.Zero)
            {
                AddOrderLine(
                    payex, orderRef, string.Format("{0}", itemIndex++),
                    _localizationService.GetResource("Order.Shipping"), 1, orderShippingInclTax)
                .GetAwaiter().GetResult();
                cartTotal += orderShippingInclTax;
            }

            //payment method additional fee
            var paymentMethodAdditionalFeeInclTax = order.PaymentMethodAdditionalFeeInclTax;

            if (paymentMethodAdditionalFeeInclTax > decimal.Zero)
            {
                AddOrderLine(
                    payex, orderRef, string.Format("{0}", itemIndex++),
                    _localizationService.GetResource("Order.PaymentMethodAdditionalFee"), 1,
                    paymentMethodAdditionalFeeInclTax)
                .GetAwaiter().GetResult();
                cartTotal += paymentMethodAdditionalFeeInclTax;
            }

            if (cartTotal > order.OrderTotal)
            {
                /* Take the difference between what the order total is and what it should be and use that as the "discount".
                 * The difference equals the amount of the gift card and/or reward points used.
                 */
                decimal discountTotal = cartTotal - order.OrderTotal;
                //gift card or rewared point amount applied to cart in nopCommerce
                AddOrderLine(
                    payex, orderRef, string.Format("{0}", itemIndex++),
                    _localizationService.GetResource("Admin.Orders.Products.Discount"), 1, -discountTotal)
                .GetAwaiter().GetResult();
            }
        }
        /// <summary>
        /// Post process payment (used by payment gateways that require redirecting to a third-party URL)
        /// </summary>
        /// <param name="postProcessPaymentRequest">Payment info required for an order processing</param>
        public void PostProcessPayment(PostProcessPaymentRequest postProcessPaymentRequest)
        {
            var builder = new StringBuilder();

            builder.Append(GetPaypalUrl());
            string cmd = string.Empty;

            if (_paypalStandardPaymentSettings.PassProductNamesAndTotals)
            {
                cmd = "_cart";
            }
            else
            {
                cmd = "_xclick";
            }
            builder.AppendFormat("?cmd={0}&business={1}", cmd, HttpUtility.UrlEncode(_paypalStandardPaymentSettings.BusinessEmail));
            if (_paypalStandardPaymentSettings.PassProductNamesAndTotals)
            {
                builder.AppendFormat("&upload=1");

                //get the items in the cart
                decimal cartTotal = decimal.Zero;
                var     cartItems = postProcessPaymentRequest.Order.OrderProductVariants;
                int     x         = 1;
                foreach (var item in cartItems)
                {
                    var unitPriceExclTax = item.UnitPriceExclTax;
                    var priceExclTax     = item.PriceExclTax;
                    //round
                    var unitPriceExclTaxRounded = Math.Round(unitPriceExclTax, 2);
                    //get the product variant so we can get the name
                    builder.AppendFormat("&item_name_" + x + "={0}", HttpUtility.UrlEncode(item.ProductVariant.FullProductName));
                    builder.AppendFormat("&amount_" + x + "={0}", unitPriceExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture));
                    builder.AppendFormat("&quantity_" + x + "={0}", item.Quantity);
                    x++;
                    cartTotal += priceExclTax;
                }

                //the checkout attributes that have a dollar value and send them to Paypal as items to be paid for
                var caValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(postProcessPaymentRequest.Order.CheckoutAttributesXml);
                foreach (var val in caValues)
                {
                    var attPrice = _taxService.GetCheckoutAttributePrice(val, false, postProcessPaymentRequest.Order.Customer);
                    //round
                    var attPriceRounded = Math.Round(attPrice, 2);
                    if (attPrice > decimal.Zero) //if it has a price
                    {
                        var ca = val.CheckoutAttribute;
                        if (ca != null)
                        {
                            var attName = ca.Name;                                                                                         //set the name
                            builder.AppendFormat("&item_name_" + x + "={0}", HttpUtility.UrlEncode(attName));                              //name
                            builder.AppendFormat("&amount_" + x + "={0}", attPriceRounded.ToString("0.00", CultureInfo.InvariantCulture)); //amount
                            builder.AppendFormat("&quantity_" + x + "={0}", 1);                                                            //quantity
                            x++;
                            cartTotal += attPrice;
                        }
                    }
                }

                //order totals

                //shipping
                var orderShippingExclTax        = postProcessPaymentRequest.Order.OrderShippingExclTax;
                var orderShippingExclTaxRounded = Math.Round(orderShippingExclTax, 2);
                if (orderShippingExclTax > decimal.Zero)
                {
                    builder.AppendFormat("&item_name_" + x + "={0}", "Shipping fee");
                    builder.AppendFormat("&amount_" + x + "={0}", orderShippingExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture));
                    builder.AppendFormat("&quantity_" + x + "={0}", 1);
                    x++;
                    cartTotal += orderShippingExclTax;
                }

                //payment method additional fee
                var paymentMethodAdditionalFeeExclTax        = postProcessPaymentRequest.Order.PaymentMethodAdditionalFeeExclTax;
                var paymentMethodAdditionalFeeExclTaxRounded = Math.Round(paymentMethodAdditionalFeeExclTax, 2);
                if (paymentMethodAdditionalFeeExclTax > decimal.Zero)
                {
                    builder.AppendFormat("&item_name_" + x + "={0}", "Payment method fee");
                    builder.AppendFormat("&amount_" + x + "={0}", paymentMethodAdditionalFeeExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture));
                    builder.AppendFormat("&quantity_" + x + "={0}", 1);
                    x++;
                    cartTotal += paymentMethodAdditionalFeeExclTax;
                }

                //tax
                var orderTax        = postProcessPaymentRequest.Order.OrderTax;
                var orderTaxRounded = Math.Round(orderTax, 2);
                if (orderTax > decimal.Zero)
                {
                    //builder.AppendFormat("&tax_1={0}", orderTax.ToString("0.00", CultureInfo.InvariantCulture));

                    //add tax as item
                    builder.AppendFormat("&item_name_" + x + "={0}", HttpUtility.UrlEncode("Sales Tax"));                          //name
                    builder.AppendFormat("&amount_" + x + "={0}", orderTaxRounded.ToString("0.00", CultureInfo.InvariantCulture)); //amount
                    builder.AppendFormat("&quantity_" + x + "={0}", 1);                                                            //quantity

                    cartTotal += orderTax;
                    x++;
                }

                if (cartTotal > postProcessPaymentRequest.Order.OrderTotal)
                {
                    /* Take the difference between what the order total is and what it should be and use that as the "discount".
                     * The difference equals the amount of the gift card and/or reward points used.
                     */
                    decimal discountTotal = cartTotal - postProcessPaymentRequest.Order.OrderTotal;
                    discountTotal = Math.Round(discountTotal, 2);
                    //gift card or rewared point amount applied to cart in nopCommerce - shows in Paypal as "discount"
                    builder.AppendFormat("&discount_amount_cart={0}", discountTotal.ToString("0.00", CultureInfo.InvariantCulture));
                }
            }
            else
            {
                //pass order total
                builder.AppendFormat("&item_name=Order Number {0}", postProcessPaymentRequest.Order.Id);
                var orderTotal = Math.Round(postProcessPaymentRequest.Order.OrderTotal, 2);
                builder.AppendFormat("&amount={0}", orderTotal.ToString("0.00", CultureInfo.InvariantCulture));
            }

            builder.AppendFormat("&custom={0}", postProcessPaymentRequest.Order.OrderGuid);
            builder.Append(string.Format("&no_note=1&currency_code={0}", HttpUtility.UrlEncode(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId).CurrencyCode)));
            builder.AppendFormat("&invoice={0}", postProcessPaymentRequest.Order.Id);
            builder.AppendFormat("&rm=2", new object[0]);
            if (postProcessPaymentRequest.Order.ShippingStatus != ShippingStatus.ShippingNotRequired)
            {
                builder.AppendFormat("&no_shipping=2", new object[0]);
            }
            else
            {
                builder.AppendFormat("&no_shipping=1", new object[0]);
            }

            string returnUrl       = _webHelper.GetStoreLocation(false) + "Plugins/PaymentPayPalStandard/PDTHandler";
            string cancelReturnUrl = _webHelper.GetStoreLocation(false) + "Plugins/PaymentPayPalStandard/CancelOrder";

            builder.AppendFormat("&return={0}&cancel_return={1}", HttpUtility.UrlEncode(returnUrl), HttpUtility.UrlEncode(cancelReturnUrl));

            //Instant Payment Notification (server to server message)
            if (_paypalStandardPaymentSettings.EnableIpn)
            {
                string ipnUrl;
                if (String.IsNullOrWhiteSpace(_paypalStandardPaymentSettings.IpnUrl))
                {
                    ipnUrl = _webHelper.GetStoreLocation(false) + "Plugins/PaymentPayPalStandard/IPNHandler";
                }
                else
                {
                    ipnUrl = _paypalStandardPaymentSettings.IpnUrl;
                }
                builder.AppendFormat("&notify_url={0}", ipnUrl);
            }

            //address
            builder.AppendFormat("&address_override=1");
            builder.AppendFormat("&first_name={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.FirstName));
            builder.AppendFormat("&last_name={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.LastName));
            builder.AppendFormat("&address1={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.Address1));
            builder.AppendFormat("&address2={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.Address2));
            builder.AppendFormat("&city={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.City));
            //if (!String.IsNullOrEmpty(postProcessPaymentRequest.Order.BillingAddress.PhoneNumber))
            //{
            //    //strip out all non-digit characters from phone number;
            //    string billingPhoneNumber = System.Text.RegularExpressions.Regex.Replace(postProcessPaymentRequest.Order.BillingAddress.PhoneNumber, @"\D", string.Empty);
            //    if (billingPhoneNumber.Length >= 10)
            //    {
            //        builder.AppendFormat("&night_phone_a={0}", HttpUtility.UrlEncode(billingPhoneNumber.Substring(0, 3)));
            //        builder.AppendFormat("&night_phone_b={0}", HttpUtility.UrlEncode(billingPhoneNumber.Substring(3, 3)));
            //        builder.AppendFormat("&night_phone_c={0}", HttpUtility.UrlEncode(billingPhoneNumber.Substring(6, 4)));
            //    }
            //}
            if (postProcessPaymentRequest.Order.BillingAddress.StateProvince != null)
            {
                builder.AppendFormat("&state={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.StateProvince.Abbreviation));
            }
            else
            {
                builder.AppendFormat("&state={0}", "");
            }
            if (postProcessPaymentRequest.Order.BillingAddress.Country != null)
            {
                builder.AppendFormat("&country={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.Country.TwoLetterIsoCode));
            }
            else
            {
                builder.AppendFormat("&country={0}", "");
            }
            builder.AppendFormat("&zip={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.ZipPostalCode));
            builder.AppendFormat("&email={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.Email));
            _httpContext.Response.Redirect(builder.ToString());
        }
Example #22
0
        /// <summary>
        /// Post process payment (used by payment gateways that require redirecting to a third-party URL)
        /// </summary>
        /// <param name="postProcessPaymentRequest">Payment info required for an order processing</param>
        public void PostProcessPayment(PostProcessPaymentRequest postProcessPaymentRequest)
        {
            //Base URL
            var builder = new StringBuilder();

            builder.Append(GetMonerisUrl());

            //Store Id and security token
            builder.AppendFormat("?ps_store_id={0}&hpp_key={1}", HttpUtility.UrlEncode(_monerisStandardPaymentSettings.StoreId), HttpUtility.UrlEncode(_monerisStandardPaymentSettings.PdtToken));

            //OrderId
            builder.AppendFormat("&order_id={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.Id.ToString()));

            //Email
            builder.AppendFormat("&email={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.Customer.Email));

            //UserName
            builder.AppendFormat("&cust_id={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.Customer.Username));

            //Language
            string lang = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName;

            if (lang.Contains("fr"))
            {
                lang = "fr-ca";
            }
            builder.AppendFormat("&lang={0}", HttpUtility.UrlEncode(lang));

            //Billing address
            if (!(postProcessPaymentRequest.Order.BillingAddress == null))
            {
                builder.AppendFormat("&bill_first_name={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.FirstName));
                builder.AppendFormat("&bill_last_name={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.LastName));
                builder.AppendFormat("&bill_address_one={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.Address1 + " " + postProcessPaymentRequest.Order.BillingAddress.Address2));
                builder.AppendFormat("&bill_city={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.City));
                builder.AppendFormat("&bill_state_or_province={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.StateProvince.Abbreviation));
                builder.AppendFormat("&bill_postal_code={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.ZipPostalCode));
                builder.AppendFormat("&bill_country={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.Country.TwoLetterIsoCode));
                builder.AppendFormat("&bill_phone={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.BillingAddress.PhoneNumber));
            }

            //Shipping address
            if (!(postProcessPaymentRequest.Order.ShippingAddress == null))
            {
                builder.AppendFormat("&ship_first_name={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.ShippingAddress.FirstName));
                builder.AppendFormat("&ship_last_name={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.ShippingAddress.LastName));
                builder.AppendFormat("&ship_address_one={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.ShippingAddress.Address1 + " " + postProcessPaymentRequest.Order.ShippingAddress.Address2));
                builder.AppendFormat("&ship_city={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.ShippingAddress.City));
                builder.AppendFormat("&ship_state_or_province={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.ShippingAddress.StateProvince.Abbreviation));
                builder.AppendFormat("&ship_postal_code={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.ShippingAddress.ZipPostalCode));
                builder.AppendFormat("&ship_country={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.ShippingAddress.Country.TwoLetterIsoCode));
                builder.AppendFormat("&ship_phone={0}", HttpUtility.UrlEncode(postProcessPaymentRequest.Order.ShippingAddress.PhoneNumber));
            }

            //Shipping
            var shippingPriceExclTax        = postProcessPaymentRequest.Order.OrderShippingExclTax;
            var shippingPriceExclTaxRounded = Math.Round(shippingPriceExclTax, 2);

            builder.AppendFormat("&shipping_cost={0}", shippingPriceExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture));

            //Send items detail
            if (_monerisStandardPaymentSettings.PassProductNamesAndTotals)
            {
                //Yes

                //get the items in the cart
                var cartItems = postProcessPaymentRequest.Order.OrderItems;
                int x         = 1;
                foreach (var item in cartItems)
                {
                    //round unit price
                    var unitPriceExclTax        = item.UnitPriceExclTax;
                    var unitPriceExclTaxRounded = Math.Round(unitPriceExclTax, 2);

                    //round subtotal
                    var priceExclTax        = item.PriceExclTax;
                    var priceExclTaxRounded = Math.Round(priceExclTax, 2);

                    //id
                    builder.AppendFormat("&id" + x + "={0}", HttpUtility.UrlEncode(item.Product.Sku));

                    //description
                    builder.AppendFormat("&description" + x + "={0}", HttpUtility.UrlEncode(item.Product.Name));

                    //quantity
                    builder.AppendFormat("&quantity" + x + "={0}", item.Quantity);

                    //unitprice
                    builder.AppendFormat("&price" + x + "={0}", unitPriceExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture));

                    //subtotal
                    builder.AppendFormat("&subtotal" + x + "={0}", priceExclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture));

                    //Video project participation
                    if (item.Product.Sku == CameleoEventProducts.PRODUCT_VIDEO_PROJECT)
                    {
                        //Yes
                        //_genericAttributeService.SaveAttribute<ShippingOption>(customer, SystemCustomerAttributeNames.DiscountCouponCode, null);
                    }

                    x++;
                }

                //the checkout attributes that have a dollar value and send them to Moneris as items to be paid for
                var caValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(postProcessPaymentRequest.Order.CheckoutAttributesXml);
                foreach (var val in caValues)
                {
                    var attPrice = _taxService.GetCheckoutAttributePrice(val, false, postProcessPaymentRequest.Order.Customer);
                    //round
                    var attPriceRounded = Math.Round(attPrice, 2);
                    if (attPrice > decimal.Zero) //if it has a price
                    {
                        var ca = val.CheckoutAttribute;
                        if (ca != null)
                        {
                            var attName = ca.Name; //set the name

                            //id
                            builder.AppendFormat("&id" + x + "={0}", HttpUtility.UrlEncode(attName));

                            //description
                            builder.AppendFormat("&description" + x + "={0}", HttpUtility.UrlEncode(attName));

                            //quantity
                            builder.AppendFormat("&quantity" + x + "={0}", 1);

                            //unitprice
                            builder.AppendFormat("&price" + x + "={0}", attPriceRounded.ToString("0.00", CultureInfo.InvariantCulture));

                            //subtotal
                            builder.AppendFormat("&subtotal" + x + "={0}", attPriceRounded.ToString("0.00", CultureInfo.InvariantCulture));


                            x++;
                        }
                    }
                }
            }
            else
            {
                //pass order total only
            }

            //Charge Total
            var totalPriceInclTax        = postProcessPaymentRequest.Order.OrderTotal;
            var totalPriceInclTaxRounded = Math.Round(totalPriceInclTax, 2);

            builder.AppendFormat("&charge_total={0}", totalPriceInclTaxRounded.ToString("0.00", CultureInfo.InvariantCulture));

            var totalPriceExclTax        = postProcessPaymentRequest.Order.OrderTotal - postProcessPaymentRequest.Order.OrderTax;
            var totalPriceExclTaxRounded = Math.Round(totalPriceExclTax, 2);


            string provinceAbbrev = postProcessPaymentRequest.Order.BillingAddress.StateProvince.Abbreviation;

            if (provinceAbbrev.Contains("QC"))
            {
                //Quebec
                //GST
                var totalGST        = totalPriceExclTax * (decimal)0.05;
                var totalGSTRounded = Math.Round(totalGST, 2);
                builder.AppendFormat("&gst={0}", totalGSTRounded.ToString("0.00", CultureInfo.InvariantCulture));

                //PST
                var totalPST        = totalPriceExclTax * (decimal)0.09975;
                var totalPSTRounded = Math.Round(totalPST, 2);
                builder.AppendFormat("&pst={0}", totalPSTRounded.ToString("0.00", CultureInfo.InvariantCulture));
            }
            else if (provinceAbbrev.Contains("ON") || provinceAbbrev.Contains("NL") || provinceAbbrev.Contains("TNL") || provinceAbbrev.Contains("NB"))
            {
                //HST 13
                var totalHST        = totalPriceExclTax * (decimal)0.13;
                var totalHSTRounded = Math.Round(totalHST, 2);
                builder.AppendFormat("&hst={0}", totalHSTRounded.ToString("0.00", CultureInfo.InvariantCulture));
            }
            else if (provinceAbbrev.Contains("NS") || provinceAbbrev.Contains("NE"))
            {
                //HST 15
                var totalHST        = totalPriceExclTax * (decimal)0.15;
                var totalHSTRounded = Math.Round(totalHST, 2);
                builder.AppendFormat("&hst={0}", totalHSTRounded.ToString("0.00", CultureInfo.InvariantCulture));
            }
            else if (provinceAbbrev.Contains("PE") || provinceAbbrev.Contains("PEI") || provinceAbbrev.Contains("IPE"))
            {
                //HST 14
                var totalHST        = totalPriceExclTax * (decimal)0.14;
                var totalHSTRounded = Math.Round(totalHST, 2);
                builder.AppendFormat("&hst={0}", totalHSTRounded.ToString("0.00", CultureInfo.InvariantCulture));
            }
            else if (provinceAbbrev.Contains("BC") || provinceAbbrev.Contains("CB") || provinceAbbrev.Contains("AB") || provinceAbbrev.Contains("SK") || provinceAbbrev.Contains("MB") || provinceAbbrev.Contains("NT") || provinceAbbrev.Contains("TNO") || provinceAbbrev.Contains("NU") || provinceAbbrev.Contains("YT") || provinceAbbrev.Contains("YU"))
            {
                //GST only
                var totalGST        = totalPriceExclTax * (decimal)0.05;
                var totalGSTRounded = Math.Round(totalGST, 2);
                builder.AppendFormat("&gst={0}", totalGSTRounded.ToString("0.00", CultureInfo.InvariantCulture));
            }

            //Redirect
            _httpContext.Response.Redirect(builder.ToString());
        }