Esempio n. 1
0
        protected async override Task MoveShoppingCartItemsToOrderItemsAsync(
            PlaceOrderContainer details,
            Order order
            )
        {
            foreach (var sc in details.Cart)
            {
                var product = await _productService.GetProductByIdAsync(sc.ProductId);

                //prices
                var scUnitPrice = (await _shoppingCartService.GetUnitPriceAsync(sc, true)).unitPrice;
                var(scSubTotal, discountAmount, scDiscounts, _) = await _shoppingCartService.GetSubTotalAsync(sc, true);

                // var scUnitPriceInclTax =
                //     await _taxService.GetProductPriceAsync(product, scUnitPrice, true, details.Customer);
                var scUnitPriceExclTax =
                    await _taxService.GetProductPriceAsync(product, scUnitPrice, false, details.Customer);

                // var scSubTotalInclTax =
                //     await _taxService.GetProductPriceAsync(product, scSubTotal, true, details.Customer);
                var scSubTotalExclTax =
                    await _taxService.GetProductPriceAsync(product, scSubTotal, false, details.Customer);

                // custom - getting warranty tax
                var(_, scSubTotalInclTax, scUnitPriceInclTax, _, _) = await _warrantyTaxService.CalculateWarrantyTaxAsync(sc, details.Customer, scSubTotalExclTax.price, scUnitPriceExclTax.price);

                var discountAmountInclTax =
                    await _taxService.GetProductPriceAsync(product, discountAmount, true, details.Customer);

                var discountAmountExclTax =
                    await _taxService.GetProductPriceAsync(product, discountAmount, false, details.Customer);

                foreach (var disc in scDiscounts)
                {
                    if (!_discountService.ContainsDiscount(details.AppliedDiscounts, disc))
                    {
                        details.AppliedDiscounts.Add(disc);
                    }
                }



                //attributes
                var attributeDescription =
                    await _productAttributeFormatter.FormatAttributesAsync(product, sc.AttributesXml, details.Customer);

                var itemWeight = await _shippingService.GetShoppingCartItemWeightAsync(sc);

                //save order item
                var orderItem = new OrderItem
                {
                    OrderItemGuid         = Guid.NewGuid(),
                    OrderId               = order.Id,
                    ProductId             = product.Id,
                    UnitPriceInclTax      = scUnitPriceInclTax,
                    UnitPriceExclTax      = scUnitPriceExclTax.price,
                    PriceInclTax          = scSubTotalInclTax,
                    PriceExclTax          = scSubTotalExclTax.price,
                    OriginalProductCost   = await _priceCalculationService.GetProductCostAsync(product, sc.AttributesXml),
                    AttributeDescription  = attributeDescription,
                    AttributesXml         = sc.AttributesXml,
                    Quantity              = sc.Quantity,
                    DiscountAmountInclTax = discountAmountInclTax.price,
                    DiscountAmountExclTax = discountAmountExclTax.price,
                    DownloadCount         = 0,
                    IsDownloadActivated   = false,
                    LicenseDownloadId     = 0,
                    ItemWeight            = itemWeight,
                    RentalStartDateUtc    = sc.RentalStartDateUtc,
                    RentalEndDateUtc      = sc.RentalEndDateUtc
                };

                await _orderService.InsertOrderItemAsync(orderItem);

                //gift cards
                await AddGiftCardsAsync(product, sc.AttributesXml, sc.Quantity, orderItem, scUnitPriceExclTax.price);

                //inventory
                await _productService.AdjustInventoryAsync(product, -sc.Quantity, sc.AttributesXml,
                                                           string.Format(await _localizationService.GetResourceAsync("Admin.StockQuantityHistory.Messages.PlaceOrder"), order.Id));
            }

            //clear shopping cart
            details.Cart.ToList().ForEach(async sci => await _shoppingCartService.DeleteShoppingCartItemAsync(sci, false));
        }
        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);
        }