Пример #1
0
            internal static void ClearDiscountLinesOfType(SalesLine salesLine, DiscountLineType lineType)
            {
                var remainingDiscounts = salesLine.DiscountLines.Where(l => l.DiscountLineType != lineType).ToList();

                salesLine.DiscountLines.Clear();
                foreach (var discount in remainingDiscounts)
                {
                    salesLine.DiscountLines.Add(discount);
                }

                if (lineType == DiscountLineType.PeriodicDiscount)
                {
                    salesLine.PeriodicDiscountPossibilities.Clear();
                    salesLine.QuantityDiscounted = 0;
                }
            }
Пример #2
0
            private static void ClearDiscountLinesOfType(SalesLine salesLine, DiscountLineType lineType)
            {
                var remainingDiscounts = salesLine.DiscountLines.Where(l => l.DiscountLineType != lineType).ToList();

                salesLine.DiscountLines.Clear();
                foreach (var discount in remainingDiscounts)
                {
                    salesLine.DiscountLines.Add(discount);
                }

                if (lineType == DiscountLineType.PeriodicDiscount)
                {
                    salesLine.PeriodicDiscountPossibilities.Clear();
                    salesLine.QuantityDiscounted = 0;
                }

                if (lineType == DiscountLineType.CustomerDiscount)
                {
                    salesLine.LineMultilineDiscOnItem = LineMultilineDiscountOnItem.None;
                }
            }
Пример #3
0
            /// <summary>
            /// This method will distribute the amountToDiscount across all the sale items in the transaction
            ///   proportionally except for the line item with the largest amount.  The remainder will be distributed
            ///   to the line item with the largest amount to ensure the amount to discount is exactly applied.
            /// This method currently works for either the customer discount or when the total discount button is applied.
            /// </summary>
            /// <param name="transaction">The transaction receiving total discount lines.</param>
            /// <param name="discountType">Whether this discount is for a customer or for the total discount item.</param>
            /// <param name="amountToDiscount">The amount to discount the transaction.</param>
            private void AddTotalDiscAmountLines(
                SalesTransaction transaction,
                DiscountLineType discountType,
                decimal amountToDiscount)
            {
                decimal totalAmtAvailableForDiscount = decimal.Zero;

                // Build a list of the discountable items with the largest value item last.
                // Consider calculable lines only. Ignore voided or return-by-receipt lines.
                var discountableSaleItems = (from s in transaction.PriceCalculableSalesLines
                                             where s.IsEligibleForDiscount() && s.Quantity > 0 &&
                                             PriceContextHelper.IsDiscountAllowed(this.priceContext, s.ItemId)
                                             orderby Math.Abs(s.NetAmount), s.LineId
                                             select s).ToList();

                // Iterate through all non voided items whether we are going to discount or not so that they get added
                // back to the totals
                // Consider calculable lines only. Ignore voided or return-by-receipt lines.
                foreach (var saleItem in transaction.PriceCalculableSalesLines)
                {
                    // We can clear the discount line for total discount because a total manual amount discount
                    // will override a total manual percent discount, whereas customer discount can have both
                    // amount and percentage applied simultaneously.
                    if (discountType == DiscountLineType.ManualDiscount)
                    {
                        Discount.ClearManualDiscountLinesOfType(saleItem, ManualDiscountType.TotalDiscountAmount);
                        Discount.ClearManualDiscountLinesOfType(saleItem, ManualDiscountType.TotalDiscountPercent);
                    }

                    SalesLineTotaller.CalculateLine(transaction, saleItem, d => this.priceContext.CurrencyAndRoundingHelper.Round(d));

                    if (saleItem.IsEligibleForDiscount() && saleItem.Quantity > 0)
                    {
                        // Calculate the total amount that is available for discount
                        totalAmtAvailableForDiscount += Math.Abs(saleItem.NetAmountWithAllInclusiveTax);
                    }
                }

                // Calculate the percentage (as a fraction) that we should attempt to discount each discountable item
                // to reach the total.
                decimal discountFactor = totalAmtAvailableForDiscount != decimal.Zero ? (amountToDiscount / totalAmtAvailableForDiscount) : decimal.Zero;

                decimal totalAmtDistributed = decimal.Zero;

                // Iterate through all discountable items.
                foreach (var saleItem in discountableSaleItems)
                {
                    decimal amountToDiscountForThisItem = decimal.Zero;

                    if (saleItem != discountableSaleItems.Last())
                    {
                        // for every item except for the last in the list (which will have the largest value)
                        // discount by the rounded amount that is closest to the percentage desired for the transaction
                        decimal itemPrice = saleItem.NetAmount;
                        amountToDiscountForThisItem = this.priceContext.CurrencyAndRoundingHelper.Round(discountFactor * Math.Abs(itemPrice));
                        totalAmtDistributed        += amountToDiscountForThisItem;
                    }
                    else
                    {
                        // Discount the last item by the remainder to ensure that the exact desired discount is applied
                        amountToDiscountForThisItem = amountToDiscount - totalAmtDistributed;
                    }

                    DiscountLine discountItem;
                    if (amountToDiscountForThisItem != decimal.Zero)
                    {
                        if (discountType == DiscountLineType.ManualDiscount)
                        {
                            // Add a new total discount item
                            discountItem = new DiscountLine();
                            discountItem.DiscountLineType   = DiscountLineType.ManualDiscount;
                            discountItem.ManualDiscountType = ManualDiscountType.TotalDiscountAmount;
                            saleItem.DiscountLines.Add(discountItem);
                        }
                        else
                        {
                            // for customer discounts we need to either update the existing one, or add a new one.
                            discountItem = GetCustomerDiscountItem(saleItem, CustomerDiscountType.TotalDiscount, DiscountLineType.CustomerDiscount);
                        }

                        discountItem.Amount = saleItem.Quantity != 0 ? amountToDiscountForThisItem / saleItem.Quantity : amountToDiscountForThisItem;
                    }

                    SalesLineTotaller.CalculateLine(transaction, saleItem, d => this.priceContext.CurrencyAndRoundingHelper.Round(d));
                }
            }
Пример #4
0
            /// <summary>
            /// Retrieves a customer discount item of the indicated type if it exists and creates one if not.
            /// </summary>
            /// <param name="salesLine">The sales line from which to find customer discount lines.</param>
            /// <param name="customerDiscountType">The customer discount type.</param>
            /// <param name="lineDiscountType">The line discount type.</param>
            /// <returns>
            /// The discount line.
            /// </returns>
            private static DiscountLine GetCustomerDiscountItem(SalesLine salesLine, CustomerDiscountType customerDiscountType, DiscountLineType lineDiscountType)
            {
                DiscountLine discount;
                var          discounts = from d in salesLine.DiscountLines
                                         where
                                         d.DiscountLineType == lineDiscountType &&
                                         d.CustomerDiscountType == customerDiscountType
                                         select d;

                // If the discount doesn't exist create a new one
                if (discounts.Count() == 0)
                {
                    discount = new DiscountLine
                    {
                        DiscountLineType     = lineDiscountType,
                        CustomerDiscountType = customerDiscountType,
                    };

                    salesLine.DiscountLines.Add(discount);
                }
                else
                {
                    // otherwise select it.
                    discount = discounts.First();
                }

                return(discount);
            }
Пример #5
0
 public DiscountLine(DiscountLineType type)
 {
     Type = type.ToString().ToLower();
 }