/// <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 } } }