Example #1
0
            /// <summary>
            /// Calculates all of the discount lines for the transactions.
            /// </summary>
            /// <param name="pricingDataManager">Provides data access to the calculation.</param>
            /// <param name="transaction">The sales transaction.</param>
            /// <param name="shouldTotalLines">True if discount lines should be totaled for each line. False if they should be left as raw discount lines.</param>
            /// <param name="priceContext">Price context.</param>
            /// <remarks>Each sales line will have a collection of DiscountLines and a net discount total in DiscountAmount property (if totaling is enabled).</remarks>
            public static void CalculateDiscountsForLines(
                IPricingDataAccessor pricingDataManager,
                SalesTransaction transaction,
                bool shouldTotalLines,
                PriceContext priceContext)
            {
                if (transaction == null)
                {
                    throw new ArgumentNullException("transaction");
                }

                List <SalesLine> existingSalesLines = new List <SalesLine>();
                List <SalesLine> newSalesLines      = new List <SalesLine>();

                if (priceContext.CalculateForNewSalesLinesOnly)
                {
                    foreach (SalesLine salesLine in transaction.SalesLines)
                    {
                        if (priceContext.NewSalesLineIdSet.Contains(salesLine.LineId))
                        {
                            newSalesLines.Add(salesLine);
                        }
                        else
                        {
                            existingSalesLines.Add(salesLine);
                        }
                    }

                    // Calculate for new sales lines only.
                    transaction.SalesLines.Clear();
                    transaction.SalesLines.AddRange(newSalesLines);
                }

                Discount discountEngine = InitializeDiscountEngine(pricingDataManager);

                discountEngine.CalculateDiscount(pricingDataManager, transaction, priceContext);

                if (priceContext.CalculateForNewSalesLinesOnly)
                {
                    // Add existing sales lines back after calculating for new sales lines only.
                    List <SalesLine> newSalesLinesFromCalculation = new List <SalesLine>();
                    foreach (SalesLine salesLine in transaction.SalesLines)
                    {
                        if (!priceContext.NewSalesLineIdSet.Contains(salesLine.LineId))
                        {
                            newSalesLinesFromCalculation.Add(salesLine);
                        }
                    }

                    transaction.SalesLines.Clear();
                    transaction.SalesLines.AddRange(existingSalesLines);
                    transaction.SalesLines.AddRange(newSalesLines);
                    transaction.SalesLines.AddRange(newSalesLinesFromCalculation);
                }

                if (shouldTotalLines)
                {
                    // Consider calculable lines only. Ignore voided or return-by-receipt lines.
                    foreach (var salesLine in transaction.PriceCalculableSalesLines)
                    {
                        SalesLineTotaller.CalculateLine(transaction, salesLine, d => priceContext.CurrencyAndRoundingHelper.Round(d)); // technically rounding rule should be "sales rounding" rule
                    }
                }
            }