Пример #1
0
        /// <summary>
        /// Precompute the line item vat and discounts and attach it inside the order info node
        /// </summary>
        /// <param name="nav">The XPathNavigator</param>
        private void PreComputeLineItemIntrinsics(XPathNavigator nav)
        {
            XmlNode           orderInfoNode        = GetXmlNode(nav.SelectSingleNode("Order/OrderInfo"));
            XPathNodeIterator lineItemNodeIterator = nav.Select("OrderItems/Item");
            CultureInfo       cultureInfo;
            var orderCultureInfo = CommonLogic.Application("DBSQLServerLocaleSetting");

            cultureInfo = string.IsNullOrEmpty(orderCultureInfo)
                                ? CultureInfo.InvariantCulture
                                : new CultureInfo(orderCultureInfo);

            decimal allLineItemDiscounts = decimal.Zero;

            while (lineItemNodeIterator.MoveNext())
            {
                XmlNode lineItemNode = GetXmlNode(lineItemNodeIterator.Current);

                bool isAKit = XmlCommon.XmlFieldBool(lineItemNode, "IsAKit");

                int quantity = 1;
                int.TryParse(XmlCommon.XmlField(lineItemNode, "Quantity"), out quantity);

                decimal price = 0;
                Decimal.TryParse(XmlCommon.XmlField(lineItemNode, "OrderedProductRegularPrice"), NumberStyles.AllowDecimalPoint, cultureInfo, out price);

                decimal orderedExtendedPrice = 0;
                Decimal.TryParse(XmlCommon.XmlField(lineItemNode, "OrderedProductPrice"), NumberStyles.AllowDecimalPoint, cultureInfo, out orderedExtendedPrice);

                decimal taxRate = Decimal.Parse(XmlCommon.XmlField(lineItemNode, "TaxRate"), NumberStyles.AllowDecimalPoint, cultureInfo);

                decimal vatAmount         = decimal.Zero;
                decimal extendedVatAmount = decimal.Zero;

                bool applyVat = AppLogic.AppConfigBool("VAT.Enabled") == true &&
                                XmlCommon.XmlFieldBool(orderInfoNode, "LevelHasNoTax") == false &&
                                XmlCommon.XmlFieldBool(lineItemNode, "IsTaxable") == true &&
                                string.IsNullOrEmpty(XmlCommon.XmlField(orderInfoNode, "VATRegistrationID"));

                if (applyVat)
                {
                    if (AppLogic.AppConfigBool("VAT.RoundPerItem"))
                    {
                        vatAmount         = (((price / quantity) * taxRate) / 100M) * quantity;
                        extendedVatAmount = (((orderedExtendedPrice / quantity) * taxRate) / 100M) * quantity;
                    }
                    else
                    {
                        vatAmount         = (price * taxRate) / 100M;
                        extendedVatAmount = (orderedExtendedPrice * taxRate) / 100M;
                    }

                    if (isAKit)
                    {
                        vatAmount = extendedVatAmount / quantity;
                    }
                }
                // let's save these as decimal values, leave out formatting on a later call
                XmlNode vatAmountNode = lineItemNode.OwnerDocument.CreateNode(XmlNodeType.Element, "VatAmount", string.Empty);
                vatAmountNode.InnerText = XmlCommon.XmlEncode(vatAmount.ToString(cultureInfo));

                XmlNode extVatAmountNode = lineItemNode.OwnerDocument.CreateNode(XmlNodeType.Element, "ExtVatAmount", string.Empty);
                extVatAmountNode.InnerText = XmlCommon.XmlEncode(extendedVatAmount.ToString(cultureInfo));

                // insert these nodes on the bottom
                lineItemNode.InsertAfter(vatAmountNode, lineItemNode.LastChild);
                lineItemNode.InsertAfter(extVatAmountNode, lineItemNode.LastChild);

                decimal regularExtendedPrice = decimal.Zero;
                decimal discount             = decimal.Zero;

                // kit products don't save the regular price only the sales price
                // we won't be supporting line item discounts on these item types then
                if (isAKit)
                {
                    regularExtendedPrice = decimal.Zero;
                    discount             = decimal.Zero;

                    price = orderedExtendedPrice / quantity;
                }
                else
                {
                    // make sure to round to 2 decimal places
                    price = Math.Round(price, 2, MidpointRounding.AwayFromZero);
                    regularExtendedPrice = price * quantity;
                    discount             = (regularExtendedPrice - orderedExtendedPrice);
                }

                bool showPriceVatInclusive = ThisCustomer.VATSettingReconciled == VATSettingEnum.ShowPricesInclusiveOfVAT;

                decimal displayPrice = price;
                if (applyVat && showPriceVatInclusive)
                {
                    displayPrice += vatAmount;
                }

                decimal displayExtPrice = orderedExtendedPrice;
                if (applyVat && showPriceVatInclusive)
                {
                    displayExtPrice += extendedVatAmount;
                }

                // let's save these as decimal values, leave out formatting on a later call
                XmlNode extRegularPriceNode = lineItemNode.OwnerDocument.CreateNode(XmlNodeType.Element, "ExtendedRegularPrice", string.Empty);
                extRegularPriceNode.InnerText = XmlCommon.XmlEncode(regularExtendedPrice.ToString(cultureInfo));
                // insert these nodes on the bottom
                lineItemNode.InsertAfter(extRegularPriceNode, lineItemNode.LastChild);

                XmlNode discountNode = lineItemNode.OwnerDocument.CreateNode(XmlNodeType.Element, "DiscountAmount", string.Empty);
                discountNode.InnerText = XmlCommon.XmlEncode(discount.ToString(cultureInfo));
                // insert these nodes on the bottom
                lineItemNode.InsertAfter(discountNode, lineItemNode.LastChild);

                // price column
                XmlNode priceNode = lineItemNode.OwnerDocument.CreateNode(XmlNodeType.Element, "Price", string.Empty);
                priceNode.InnerText = XmlCommon.XmlEncode(price.ToString(cultureInfo));
                // insert these nodes on the bottom
                lineItemNode.InsertAfter(priceNode, lineItemNode.LastChild);

                XmlNode displayPriceNode = lineItemNode.OwnerDocument.CreateNode(XmlNodeType.Element, "DisplayPrice", string.Empty);
                displayPriceNode.InnerText = XmlCommon.XmlEncode(displayPrice.ToString(cultureInfo));
                // insert these nodes on the bottom
                lineItemNode.InsertAfter(displayPriceNode, lineItemNode.LastChild);

                XmlNode displayExtPriceNode = lineItemNode.OwnerDocument.CreateNode(XmlNodeType.Element, "DisplayExtPrice", string.Empty);
                displayExtPriceNode.InnerText = XmlCommon.XmlEncode(displayExtPrice.ToString(cultureInfo));
                // insert these nodes on the bottom
                lineItemNode.InsertAfter(displayExtPriceNode, lineItemNode.LastChild);

                XmlNode discountWithVATNode = lineItemNode.OwnerDocument.CreateNode(XmlNodeType.Element, "DiscountWithVAT", string.Empty);
                discountWithVATNode.InnerText = XmlCommon.XmlEncode((displayPrice - displayExtPrice).ToString(cultureInfo));
                // insert these nodes on the bottom
                lineItemNode.InsertAfter(discountWithVATNode, lineItemNode.LastChild);

                // store the line item discounts
                allLineItemDiscounts += XmlCommon.XmlFieldNativeDecimal(lineItemNode, "DiscountAmount");
            }

            bool hasLineItemDiscounts = false;

            hasLineItemDiscounts = allLineItemDiscounts > decimal.Zero;

            XmlNode hasLineItemDiscountsNode = orderInfoNode.OwnerDocument.CreateNode(XmlNodeType.Element, "HasLineItemDiscounts", string.Empty);

            hasLineItemDiscountsNode.InnerText = XmlCommon.XmlEncode(hasLineItemDiscounts.ToString(cultureInfo));
            orderInfoNode.InsertAfter(hasLineItemDiscountsNode, orderInfoNode.LastChild);
        }
Пример #2
0
        /// <summary>
        /// Precompute the order discounts and attach it to the OrderInfo node
        /// </summary>
        /// <param name="nav">The XPathNavigator</param>
        private void PreComputeDiscounts(XPathNavigator nav)
        {
            // Precompute the totals
            XmlNode           orderInfoNode    = GetXmlNode(nav.SelectSingleNode("Order/OrderInfo"));
            decimal           rawSubTotal      = decimal.Zero;
            decimal           rawSubTotalVat   = decimal.Zero;
            XPathNodeIterator lineItemIterator = nav.Select("OrderItems/Item");

            bool incVat = ThisCustomer.VATSettingReconciled == VATSettingEnum.ShowPricesInclusiveOfVAT;

            while (lineItemIterator.MoveNext())
            {
                XmlNode lineItemNode = GetXmlNode(lineItemIterator.Current);
                rawSubTotal += XmlCommon.XmlFieldNativeDecimal(lineItemNode, "OrderedProductPrice");

                if (incVat)
                {
                    rawSubTotalVat += XmlCommon.XmlFieldNativeDecimal(lineItemNode, "ExtVatAmount");
                }
            }

            XPathNodeIterator orderOptionIterator = nav.Select("Order/OrderInfo/OrderOptionsXml/OrderOption");

            while (orderOptionIterator.MoveNext())
            {
                XmlNode orderOptionNode = GetXmlNode(orderOptionIterator.Current);
                rawSubTotal += XmlCommon.XmlFieldNativeDecimal(orderOptionNode, "Price");
            }

            decimal appliedSubTotal = rawSubTotal;
            decimal subTotal        = XmlCommon.XmlFieldNativeDecimal(orderInfoNode, "OrderSubtotal");

            XmlNode rawSubTotalNode   = orderInfoNode.OwnerDocument.CreateNode(XmlNodeType.Element, "RawSubTotal", string.Empty);
            decimal actualRawSubTotal = rawSubTotal + rawSubTotalVat;

            rawSubTotalNode.InnerText = XmlCommon.XmlEncode(actualRawSubTotal.ToString());
            orderInfoNode.InsertAfter(rawSubTotalNode, orderInfoNode.LastChild);

            XmlNode discountsNode = orderInfoNode.OwnerDocument.CreateNode(XmlNodeType.Element, "Discounts", string.Empty);

            orderInfoNode.InsertAfter(discountsNode, orderInfoNode.LastChild);

            string couponCode = XmlCommon.XmlField(orderInfoNode, "CouponCode");

            int  couponType       = XmlCommon.XmlFieldNativeInt(orderInfoNode, "CouponType");
            bool hasCouponApplied = !string.IsNullOrEmpty(couponCode) && couponType != GIFTCARD_COUPONTYPE;

            decimal couponDiscountPercent = XmlCommon.XmlFieldNativeDecimal(orderInfoNode, "CouponDiscountPercent");
            decimal couponDiscountAmount  = XmlCommon.XmlFieldNativeDecimal(orderInfoNode, "CouponDiscountAmount");

            if (hasCouponApplied)
            {
                // were only interested in the amount
                if (couponDiscountPercent > decimal.Zero)
                {
                    XmlNode      discountNode  = orderInfoNode.OwnerDocument.CreateNode(XmlNodeType.Element, "Discount", string.Empty);
                    XmlAttribute typeAttribute = orderInfoNode.OwnerDocument.CreateAttribute("type");
                    typeAttribute.Value = "Coupon";                    //"Coupon Percent";
                    discountNode.Attributes.Append(typeAttribute);

                    decimal couponDiscountPercentAmount = decimal.Zero;

                    // check whether the coupon type is by percent
                    // if it is, compute by line items included only
                    string validProductIdCommaSeparated = XmlCommon.XmlField(orderInfoNode, "ValidProductsForCoupon");
                    if (!string.IsNullOrEmpty(validProductIdCommaSeparated) &&
                        couponType == PRODUCT_COUPONTYPE)
                    {
                        string[] validProductsIds = validProductIdCommaSeparated.Split(',');

                        foreach (string productId in validProductsIds)
                        {
                            // let's find the line item this product is mapped to
                            string         xpath           = string.Format("OrderItems/Item[ProductID={0}]", productId);
                            XPathNavigator validProductNav = nav.SelectSingleNode(xpath);
                            if (validProductNav != null)
                            {
                                XmlNode validProductNode = GetXmlNode(validProductNav);
                                if (validProductNode != null)
                                {
                                    decimal lineItemExtPrice = XmlCommon.XmlFieldNativeDecimal(validProductNode, "OrderedProductPrice");
                                    if (incVat)
                                    {
                                        lineItemExtPrice += XmlCommon.XmlFieldNativeDecimal(validProductNode, "ExtVatAmount");
                                    }
                                    decimal lineItemCouponDiscountAmount = lineItemExtPrice * (couponDiscountPercent / 100M);

                                    couponDiscountPercentAmount += lineItemCouponDiscountAmount;
                                }
                            }
                        }
                    }
                    else
                    {
                        // coupon is applied to order
                        if (couponDiscountPercent == 100M && subTotal == decimal.Zero)
                        {
                            couponDiscountPercentAmount = appliedSubTotal;
                        }
                        else
                        {
                            couponDiscountPercentAmount = (appliedSubTotal * (couponDiscountPercent / 100M));
                        }
                    }

                    XmlAttribute valueAttribute = orderInfoNode.OwnerDocument.CreateAttribute("value");
                    valueAttribute.Value = couponDiscountPercentAmount.ToString();
                    discountNode.Attributes.Append(valueAttribute);

                    discountsNode.AppendChild(discountNode);

                    // apply the discount at this one
                    appliedSubTotal -= couponDiscountPercentAmount;
                }

                if (couponDiscountAmount > decimal.Zero &&
                    appliedSubTotal > decimal.Zero)
                {
                    // check whether the coupon type is by percent
                    // if it is, compute by line items included only
                    string validProductIdCommaSeparated = XmlCommon.XmlField(orderInfoNode, "ValidProductsForCoupon");
                    if (!string.IsNullOrEmpty(validProductIdCommaSeparated) &&
                        couponType == PRODUCT_COUPONTYPE)
                    {
                        string[] validProductsIds = validProductIdCommaSeparated.Split(',');

                        foreach (string productId in validProductsIds)
                        {
                            // let's find the line item this product is mapped to
                            string         xpath           = string.Format("OrderItems/Item[ProductID={0}]", productId);
                            XPathNavigator validProductNav = nav.SelectSingleNode(xpath);
                            if (validProductNav != null)
                            {
                                XmlNode validProductNode = GetXmlNode(validProductNav);
                                if (validProductNode != null)
                                {
                                    decimal lineItemExtPrice = XmlCommon.XmlFieldNativeDecimal(validProductNode, "OrderedProductPrice");

                                    decimal lineItemDiscountAmount = couponDiscountAmount;
                                    if (couponDiscountAmount > lineItemExtPrice)
                                    {
                                        couponDiscountAmount += lineItemExtPrice;
                                    }

                                    // need to take into account the quantity
                                    int qty = XmlCommon.XmlFieldNativeInt(validProductNode, "Quantity");
                                    couponDiscountAmount *= qty;
                                }
                            }
                        }
                    }
                    else if (couponDiscountAmount > appliedSubTotal)
                    {
                        couponDiscountAmount = appliedSubTotal;
                    }

                    XmlNode      discountNode  = orderInfoNode.OwnerDocument.CreateNode(XmlNodeType.Element, "Discount", string.Empty);
                    XmlAttribute typeAttribute = orderInfoNode.OwnerDocument.CreateAttribute("type");
                    typeAttribute.Value = "Coupon Amount";                     // "Coupon Amount";
                    discountNode.Attributes.Append(typeAttribute);

                    XmlAttribute valueAttribute = orderInfoNode.OwnerDocument.CreateAttribute("value");
                    valueAttribute.Value = couponDiscountAmount.ToString();
                    discountNode.Attributes.Append(valueAttribute);

                    discountsNode.AppendChild(discountNode);

                    appliedSubTotal -= couponDiscountAmount;
                }
            }

            decimal levelDiscountAmount = XmlCommon.XmlFieldNativeDecimal(orderInfoNode, "LevelDiscountAmount");

            if (XmlCommon.XmlFieldNativeInt(orderInfoNode, "LevelID") > 0 &&
                levelDiscountAmount > 0)
            {
                if (levelDiscountAmount > decimal.Zero &&
                    appliedSubTotal > decimal.Zero)
                {
                    if (levelDiscountAmount > appliedSubTotal)
                    {
                        levelDiscountAmount = appliedSubTotal;
                    }
                }
                // were only interested in the amount
                XmlNode      discountNode  = orderInfoNode.OwnerDocument.CreateNode(XmlNodeType.Element, "Discount", string.Empty);
                XmlAttribute typeAttribute = orderInfoNode.OwnerDocument.CreateAttribute("type");
                typeAttribute.Value = "Level";                //"Level"
                discountNode.Attributes.Append(typeAttribute);

                XmlAttribute valueAttribute = orderInfoNode.OwnerDocument.CreateAttribute("value");
                valueAttribute.Value = levelDiscountAmount.ToString();
                discountNode.Attributes.Append(valueAttribute);

                discountsNode.AppendChild(discountNode);

                appliedSubTotal -= levelDiscountAmount;
            }

            // gift card discount{shown as payment}
            decimal giftCardPaymentAppliedAmount = couponDiscountAmount;             // we save the applied gift card value on the coupon discount amount col

            bool hasGiftCardApplied = (couponType == GIFTCARD_COUPONTYPE) && giftCardPaymentAppliedAmount > decimal.Zero;

            decimal orderTotal = XmlCommon.XmlFieldNativeDecimal(orderInfoNode, "OrderTotal");
            decimal netTotal   = orderTotal;

            if (hasGiftCardApplied)
            {
                // we have Gift Card Applied
                netTotal = orderTotal - giftCardPaymentAppliedAmount;
            }

            XmlNode hasgiftCardAppliedNode = orderInfoNode.OwnerDocument.CreateNode(XmlNodeType.Element, "HasGiftCardApplied", string.Empty);

            hasgiftCardAppliedNode.InnerText = XmlCommon.XmlEncode(hasGiftCardApplied.ToString());
            orderInfoNode.InsertAfter(hasgiftCardAppliedNode, orderInfoNode.LastChild);

            XmlNode netTotalNode = orderInfoNode.OwnerDocument.CreateNode(XmlNodeType.Element, "NetTotal", string.Empty);

            netTotalNode.InnerText = XmlCommon.XmlEncode(netTotal.ToString());
            orderInfoNode.InsertAfter(netTotalNode, orderInfoNode.LastChild);
        }