示例#1
0
        /// <summary>
        /// Returns calculated price and rounded price
        /// </summary>
        /// <param name="productID"></param>
        /// <param name="formula"></param>
        /// <param name="connectorID"></param>
        /// <returns></returns>
        public KeyValuePair <decimal, decimal> RoundPrice(int productID, string formula, int connectorID)
        {
            var f = new PriceRoundingFormulaParser(formula);

            var connector = _scope.Repository <Connector>().GetSingle(c => c.ConnectorID == connectorID);

            var     calculatedPrice = CalculatePrice(productID, 1, connector, PriceRuleType.UnitPrice);
            var     costPrice       = CalculatePrice(productID, 1, connector, PriceRuleType.CostPrice);
            decimal price           = calculatedPrice;

            if (costPrice == 0)
            {
                var vendorPrices = _scope.Repository <VendorAssortment>().GetSingle(c => c.ProductID == productID).VendorPrices;
                vendorPrices.ThrowIfNull("This product contains no vendor prices.");
                costPrice = vendorPrices.FirstOrDefault(c => c.MinimumQuantity == 0 || c.MinimumQuantity == 1).Price.Try(c => c.Value, 0);
            }
            costPrice.ThrowIf(c => c == 0, "The cost price of this product is 0");

            if (f.IsMargin)
            {
                var margin = (calculatedPrice - costPrice) / (costPrice / 100);
                //apply formula and round
                var condition = f.Formula.Replace("m", margin.ToString());

                var isTrue = (Boolean)EvalHelper.Eval(condition);
                if (isTrue)
                {
                    //round price
                    int p = (int)calculatedPrice;
                    price = (decimal)p + f.RoundValue;
                }
            }
            else
            {
                //apply formula to fixed value && round
                var condition = f.Formula.Replace("x", calculatedPrice.ToString());
                condition = condition.Replace("*", ((int)calculatedPrice).ToString()); //replace * with whole number
                var isTrue = (Boolean)EvalHelper.Eval(condition);
                if (isTrue)
                {
                    //round price
                    int p = (int)calculatedPrice;
                    price = (decimal)p + f.RoundValue;
                }
            }
            return(new KeyValuePair <decimal, decimal>(calculatedPrice, price));
        }
    private static void EnsureAllTypesAreHandled(IEnumerable <object[]> supportedResults, IEnumerable <object[]> unsupportedTypes, string operatorName)
    {
        var data = supportedResults.Concat(unsupportedTypes);

        var knownTypes = TypeCoercer.SignedIntegerLengthByType.Keys
                         .Concat(TypeCoercer.UnsignedIntegerLengthByType.Keys)
                         .Concat(TypeCoercer.FloatIntegerLengthByType.Keys).ToList();

        var seenTypeCombinations = new HashSet <(Type, Type)>();

        foreach (object[] objects in data)
        {
            Type leftType  = EvalHelper.Eval((string)objects[0]).GetType();
            Type rightType = EvalHelper.Eval((string)objects[1]).GetType();

            seenTypeCombinations.Add((leftType, rightType));
        }

        var unhandledTypeCombinations = new HashSet <(Type LeftType, Type RightType)>();

        foreach (Type knownLeftType in knownTypes)
        {
            foreach (Type knownRightType in knownTypes)
            {
                (Type, Type)knownTypesTuple = (knownLeftType, knownRightType);

                if (!seenTypeCombinations.Contains(knownTypesTuple))
                {
                    unhandledTypeCombinations.Add(knownTypesTuple);
                }
            }
        }

        unhandledTypeCombinations.Should()
        .BeEmpty($"'{operatorName}' operator test data contains all possible type combinations");
    }