/// <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"); }