Ejemplo n.º 1
0
            /// <summary>
            /// Gets the discount data.
            /// </summary>
            /// <param name="tradeAgreements">Trade agreement collection to calculate on.</param>
            /// <param name="relation">The relation (line, multiline, total).</param>
            /// <param name="itemRelation">The item relation.</param>
            /// <param name="accountRelation">The account relation.</param>
            /// <param name="itemCode">The item code (table, group, all).</param>
            /// <param name="accountCode">The account code (table, group, all).</param>
            /// <param name="quantityAmount">The quantity or amount that sets the minimum quantity or amount needed.</param>
            /// <param name="priceContext">The price context.</param>
            /// <param name="itemDimensions">The item dimensions.</param>
            /// <param name="includeDimensions">A value indicating whether to include item dimensions.</param>
            /// <returns>
            /// A collection of discount agreement arguments.
            /// </returns>
            internal static ReadOnlyCollection <TradeAgreement> GetPriceDiscData(
                List <TradeAgreement> tradeAgreements,
                PriceDiscountType relation,
                string itemRelation,
                string accountRelation,
                PriceDiscountItemCode itemCode,
                PriceDiscountAccountCode accountCode,
                decimal quantityAmount,
                PriceContext priceContext,
                ProductVariant itemDimensions,
                bool includeDimensions)
            {
                accountRelation = accountRelation ?? string.Empty;
                itemRelation    = itemRelation ?? string.Empty;
                string targetCurrencyCode = priceContext.CurrencyCode ?? string.Empty;
                string inventColorId      = (itemDimensions != null && itemDimensions.ColorId != null && includeDimensions) ? itemDimensions.ColorId : string.Empty;
                string inventSizeId       = (itemDimensions != null && itemDimensions.SizeId != null && includeDimensions) ? itemDimensions.SizeId : string.Empty;
                string inventStyleId      = (itemDimensions != null && itemDimensions.StyleId != null && includeDimensions) ? itemDimensions.StyleId : string.Empty;
                string inventConfigId     = (itemDimensions != null && itemDimensions.ConfigId != null && includeDimensions) ? itemDimensions.ConfigId : string.Empty;

                DateTime today  = priceContext.ActiveDate.DateTime;
                DateTime noDate = new DateTime(1900, 1, 1);

                ReadOnlyCollection <TradeAgreement> foundAgreements;

                foundAgreements = GetAgreementsFromCollection(tradeAgreements, relation, itemRelation, accountRelation, itemCode, accountCode, quantityAmount, targetCurrencyCode, inventColorId, inventSizeId, inventStyleId, inventConfigId, today, noDate);

                return(foundAgreements);
            }
Ejemplo n.º 2
0
            /// <summary>
            /// Returns true or false, whether a certain relation is active for a discount search.
            /// </summary>
            /// <param name="relation">The trade agreement relation(price, line discount, multiline discount, total discount).</param>
            /// <param name="accountCode">The account code(table,group,all).</param>
            /// <param name="itemCode">The item code(table,group,all).</param>
            /// <returns>Returns true if the relation is active, else false.</returns>
            public bool Activation(PriceDiscountType relation, PriceDiscountAccountCode accountCode, PriceDiscountItemCode itemCode)
            {
                // if parameters haven't been fetched, return false for all
                if (this.enabledCombinations == null)
                {
                    return(false);
                }

                // look up whether the combination is enabled
                return(this.enabledCombinations.Contains(CreateCombo(relation, accountCode, itemCode)));
            }
Ejemplo n.º 3
0
 /// <summary>
 /// Helper method to create new 3-tuple of trade agreement combination.
 /// </summary>
 /// <param name="relation">The type of trade agreement (price, line discount, etc.).</param>
 /// <param name="accountCode">The type of customer (single, group, all).</param>
 /// <param name="itemCode">The type of item (single, group, all).</param>
 /// <returns>3-tuple containing the given combination.</returns>
 private static Tuple <PriceDiscountType, PriceDiscountAccountCode, PriceDiscountItemCode> CreateCombo(PriceDiscountType relation, PriceDiscountAccountCode accountCode, PriceDiscountItemCode itemCode)
 {
     return(new Tuple <PriceDiscountType, PriceDiscountAccountCode, PriceDiscountItemCode>(relation, accountCode, itemCode));
 }
            /// <summary>
            /// Find and total all multiline discount trade agreements that match the given relations and quantity.
            /// </summary>
            /// <param name="tradeAgreements">Trade agreement collection to calculate on.</param>
            /// <param name="itemCode">The item code to search by (item group or all).</param>
            /// <param name="retailTransaction">The transaction context with Id and customer Id.</param>
            /// <param name="priceGroup">Multiline price group.</param>
            /// <param name="salesQuantity">Aggregated quantity for multiline price group.</param>
            /// <param name="percent1">Percentage one.</param>
            /// <param name="percent2">Percentage two.</param>
            /// <param name="discountAmount">Discount amount.</param>
            private void GetMultiLineDiscountLine(
                List <TradeAgreement> tradeAgreements,
                PriceDiscountItemCode itemCode,
                SalesTransaction retailTransaction,
                string priceGroup,
                decimal salesQuantity,
                out decimal percent1,
                out decimal percent2,
                out decimal discountAmount)
            {
                PriceDiscountType relation  = PriceDiscountType.MultilineDiscountSales; // Sales multiline discount - 6
                ProductVariant    dimension = new ProductVariant();

                percent1       = decimal.Zero;
                percent2       = decimal.Zero;
                discountAmount = decimal.Zero;

                bool searchAgain = true;
                var  codes       = new PriceDiscountAccountCode[] { PriceDiscountAccountCode.Customer, PriceDiscountAccountCode.CustomerGroup, PriceDiscountAccountCode.AllCustomers };

                foreach (var accountCode in codes)
                {
                    // skip to next configuration if this one isn't enabled
                    if (!this.discountParameters.Activation(relation, accountCode, itemCode))
                    {
                        continue;
                    }

                    // get item relation based on item code
                    string itemRelation = (itemCode == PriceDiscountItemCode.ItemGroup) ? priceGroup : string.Empty;
                    itemRelation = itemRelation ?? string.Empty;

                    // get customer relation based on account code
                    string accountRelation = string.Empty;
                    if (accountCode == PriceDiscountAccountCode.Customer)
                    {
                        accountRelation = retailTransaction.CustomerId;
                    }
                    else if (accountCode == PriceDiscountAccountCode.CustomerGroup)
                    {
                        accountRelation = this.priceContext.CustomerMultipleLinePriceGroup;
                    }

                    accountRelation = accountRelation ?? string.Empty;

                    // if both relations are valid for the given item and account codes, look for trade agreements matching these relations
                    if (DiscountParameters.ValidRelation(accountCode, accountRelation) &&
                        DiscountParameters.ValidRelation(itemCode, itemRelation))
                    {
                        // get any active multiline discount trade agreement matching relations and quantity
                        var priceDiscTable = Discount.GetPriceDiscData(tradeAgreements, relation, itemRelation, accountRelation, itemCode, accountCode, salesQuantity, this.priceContext, dimension, false);

                        // compute running sum of discount values found
                        foreach (TradeAgreement row in priceDiscTable)
                        {
                            percent1       += row.PercentOne;
                            percent2       += row.PercentTwo;
                            discountAmount += row.Amount;

                            // stop search when we find a trade agreement set to not find next trade agreement
                            if (!row.ShouldSearchAgain)
                            {
                                searchAgain = false;
                            }
                        }
                    }

                    // stop search if we found a discount without "find next" marked
                    if (!searchAgain)
                    {
                        break;
                    }
                }
            }
Ejemplo n.º 5
0
            private static ReadOnlyCollection <TradeAgreement> GetAgreementsFromCollection(List <TradeAgreement> tradeAgreements, PriceDiscountType relation, string itemRelation, string accountRelation, PriceDiscountItemCode itemCode, PriceDiscountAccountCode accountCode, decimal quantityAmount, string targetCurrencyCode, string inventColorId, string inventSizeId, string inventStyleId, string inventConfigId, DateTime today, DateTime noDate)
            {
                ReadOnlyCollection <TradeAgreement> foundAgreements;

                foundAgreements = tradeAgreements
                                  .Where(ta =>
                                         ta.Relation == relation &&
                                         ta.ItemCode == itemCode &&
                                         string.Equals(ta.ItemRelation, itemRelation, StringComparison.OrdinalIgnoreCase) &&
                                         ta.AccountCode == accountCode &&
                                         string.Equals(ta.AccountRelation, accountRelation, StringComparison.OrdinalIgnoreCase) &&
                                         string.Equals(ta.Currency, targetCurrencyCode, StringComparison.OrdinalIgnoreCase) &&
                                         ta.QuantityAmountFrom <= Math.Abs(quantityAmount) &&
                                         (ta.QuantityAmountTo >= Math.Abs(quantityAmount) || ta.QuantityAmountTo == 0) &&
                                         ((ta.FromDate <= today || ta.FromDate <= noDate) &&
                                          (ta.ToDate >= today || ta.ToDate <= noDate)) &&
                                         (string.IsNullOrWhiteSpace(ta.ColorId) || ta.ColorId.Equals(inventColorId, StringComparison.OrdinalIgnoreCase)) &&
                                         (string.IsNullOrWhiteSpace(ta.SizeId) || ta.SizeId.Equals(inventSizeId, StringComparison.OrdinalIgnoreCase)) &&
                                         (string.IsNullOrWhiteSpace(ta.StyleId) || ta.StyleId.Equals(inventStyleId, StringComparison.OrdinalIgnoreCase)) &&
                                         (string.IsNullOrWhiteSpace(ta.ConfigId) || ta.ConfigId.Equals(inventConfigId, StringComparison.OrdinalIgnoreCase)))
                                  .AsReadOnly();

                return(foundAgreements);
            }
Ejemplo n.º 6
0
            private void GetLineDiscountLines(
                List <TradeAgreement> tradeAgreements,
                SalesLine saleItem,
                ref decimal absQty,
                ref decimal discountAmount,
                ref decimal percent1,
                ref decimal percent2,
                ref decimal minQty)
            {
                int idx = 0;

                while (idx < 9)
                {
                    PriceDiscountItemCode    itemCode    = (PriceDiscountItemCode)(idx % 3); // Mod divsion
                    PriceDiscountAccountCode accountCode = (PriceDiscountAccountCode)(idx / 3);

                    string accountRelation = string.Empty;
                    if (accountCode == PriceDiscountAccountCode.Customer)
                    {
                        accountRelation = this.priceContext.CustomerAccount;
                    }
                    else if (accountCode == PriceDiscountAccountCode.CustomerGroup)
                    {
                        accountRelation = this.priceContext.CustomerLinePriceGroup;
                    }

                    accountRelation = accountRelation ?? string.Empty;

                    string itemRelation;
                    if (itemCode == PriceDiscountItemCode.Item)
                    {
                        itemRelation = saleItem.ItemId;
                    }
                    else
                    {
                        Item item = PriceContextHelper.GetItem(this.priceContext, saleItem.ItemId);
                        itemRelation = item != null ? item.LineDiscountGroupId : string.Empty;
                    }

                    itemRelation = itemRelation ?? string.Empty;

                    PriceDiscountType relation = PriceDiscountType.LineDiscountSales; // Sales line discount - 5

                    if (this.discountParameters.Activation(relation, accountCode, itemCode))
                    {
                        if (DiscountParameters.ValidRelation(accountCode, accountRelation) &&
                            DiscountParameters.ValidRelation(itemCode, itemRelation))
                        {
                            bool dimensionDiscountFound = false;

                            if (saleItem.Variant != null && !string.IsNullOrEmpty(saleItem.Variant.VariantId))
                            {
                                var dimensionPriceDiscTable = Discount.GetPriceDiscData(tradeAgreements, relation, itemRelation, accountRelation, itemCode, accountCode, absQty, this.priceContext, saleItem.Variant, true);

                                foreach (TradeAgreement row in dimensionPriceDiscTable)
                                {
                                    bool unitsAreUndefinedOrEqual =
                                        string.IsNullOrEmpty(row.UnitOfMeasureSymbol) ||
                                        string.Equals(row.UnitOfMeasureSymbol, saleItem.SalesOrderUnitOfMeasure, StringComparison.OrdinalIgnoreCase);

                                    if (unitsAreUndefinedOrEqual)
                                    {
                                        percent1       += row.PercentOne;
                                        percent2       += row.PercentTwo;
                                        discountAmount += row.Amount;
                                        minQty         += row.QuantityAmountFrom;
                                    }

                                    if (percent1 > 0M || percent2 > 0M || discountAmount > 0M)
                                    {
                                        dimensionDiscountFound = true;
                                    }

                                    if (!row.ShouldSearchAgain)
                                    {
                                        idx = 9;
                                    }
                                }
                            }

                            if (!dimensionDiscountFound)
                            {
                                var priceDiscTable = Discount.GetPriceDiscData(tradeAgreements, relation, itemRelation, accountRelation, itemCode, accountCode, absQty, this.priceContext, saleItem.Variant, false);

                                foreach (TradeAgreement row in priceDiscTable)
                                {
                                    // Apply default if the unit of measure is not set from the cart.
                                    string unitOfMeasure = Discount.GetUnitOfMeasure(saleItem);

                                    bool unitsAreUndefinedOrEqual =
                                        string.IsNullOrEmpty(row.UnitOfMeasureSymbol) ||
                                        string.Equals(row.UnitOfMeasureSymbol, unitOfMeasure, StringComparison.OrdinalIgnoreCase);

                                    if (unitsAreUndefinedOrEqual)
                                    {
                                        percent1       += row.PercentOne;
                                        percent2       += row.PercentTwo;
                                        discountAmount += row.Amount;
                                        minQty         += row.QuantityAmountFrom;
                                    }

                                    if (!row.ShouldSearchAgain)
                                    {
                                        idx = 9;
                                    }
                                }
                            }
                        }
                    }

                    idx++;
                }
            }
Ejemplo n.º 7
0
            /// <summary>
            /// The calculation of the total customer discount.
            /// </summary>
            /// <param name="tradeAgreements">Trade agreement collection to calculate on. If null, uses the pricing data manager to find agreements.</param>
            /// <param name="retailTransaction">The retail transaction which needs total discounts.</param>
            /// <returns>
            /// The retail transaction.
            /// </returns>
            public SalesTransaction CalcTotalCustomerDiscount(
                List <TradeAgreement> tradeAgreements,
                SalesTransaction retailTransaction)
            {
                if (tradeAgreements != null && tradeAgreements.Any())
                {
                    decimal totalAmount = 0;

                    // Find the total amount as a basis for the total discount
                    // Consider calculable lines only. Ignore voided or return-by-receipt lines.
                    var clonedTransaction = retailTransaction.Clone <SalesTransaction>();

                    foreach (var clonedSalesLine in clonedTransaction.PriceCalculableSalesLines)
                    {
                        if (this.IsTotalDiscountAllowed(clonedSalesLine.ItemId))
                        {
                            SalesLineTotaller.CalculateLine(clonedTransaction, clonedSalesLine, d => this.priceContext.CurrencyAndRoundingHelper.Round(d));
                            totalAmount += clonedSalesLine.NetAmountWithAllInclusiveTax;
                        }
                    }

                    decimal absTotalAmount = Math.Abs(totalAmount);

                    // Find the total discounts.
                    PriceDiscountType        relation    = PriceDiscountType.EndDiscountSales; // Total sales discount - 7
                    PriceDiscountItemCode    itemCode    = PriceDiscountItemCode.AllItems;     // All items - 2
                    PriceDiscountAccountCode accountCode = 0;
                    string         itemRelation          = string.Empty;
                    decimal        percent1       = 0m;
                    decimal        percent2       = 0m;
                    decimal        discountAmount = 0m;
                    ProductVariant dimension      = new ProductVariant();

                    int idx = 0;
                    while (idx < /* Max(PriceDiscAccountCode) */ 3)
                    {   // Check discounts for Store Currency
                        accountCode = (PriceDiscountAccountCode)idx;

                        string accountRelation = string.Empty;
                        if (accountCode == PriceDiscountAccountCode.Customer)
                        {
                            accountRelation = retailTransaction.CustomerId;
                        }
                        else if (accountCode == PriceDiscountAccountCode.CustomerGroup)
                        {
                            accountRelation = this.priceContext.CustomerTotalPriceGroup;
                        }

                        accountRelation = accountRelation ?? string.Empty;

                        // Only get Active discount combinations
                        if (this.discountParameters.Activation(relation, (PriceDiscountAccountCode)accountCode, (PriceDiscountItemCode)itemCode))
                        {
                            var priceDiscTable = Discount.GetPriceDiscData(tradeAgreements, relation, itemRelation, accountRelation, itemCode, accountCode, absTotalAmount, this.priceContext, dimension, false);

                            foreach (TradeAgreement row in priceDiscTable)
                            {
                                percent1       += row.PercentOne;
                                percent2       += row.PercentTwo;
                                discountAmount += row.Amount;

                                if (!row.ShouldSearchAgain)
                                {
                                    idx = 3;
                                }
                            }
                        }

                        idx++;
                    }

                    decimal totalPercentage = DiscountLine.GetCompoundedPercentage(percent1, percent2);

                    if (discountAmount != decimal.Zero)
                    {
                        this.AddTotalDiscAmountLines(retailTransaction, DiscountLineType.CustomerDiscount, discountAmount);
                    }

                    if (totalPercentage != 0)
                    {
                        // Update the sale items.
                        // Consider calculable lines only. Ignore voided or return-by-receipt lines.
                        foreach (var saleItem in retailTransaction.PriceCalculableSalesLines)
                        {
                            if (this.IsTotalDiscountAllowed(saleItem.ItemId))
                            {
                                DiscountLine discountItem = GetCustomerDiscountItem(saleItem, CustomerDiscountType.TotalDiscount, DiscountLineType.CustomerDiscount);
                                discountItem.Percentage = totalPercentage;
                            }
                        }
                    }
                }

                return(retailTransaction);
            }