/// <summary> /// Get struct PriceResult from active trade agreement. /// Struct PriceResult contains India MaxRetailPrice. Currently there is a field �Max. retail price� in the form price/discount agreement journal /// (Navigation path: Main Menu > Sales and marketing > Journal > price/discount agreement journal). /// The field will be visible only when the logged on company is an India company. And it is optional. /// User can use this field to specify different MRP values on different sites and warehouses for the same item. And when the trade agreement applies to a transaction, /// the MRP value should flow to the MRP field of the transaction as the default value. /// So current change is when fetching the superset of trade agreements which could apply to all of these items and customer for the given date, /// also takes field MAXIMUMRETAILPRICE_IN through the stored procedures GETALLDISCOUNTTRADEAGREEMENTS/ GETALLTRADEAGREEMENTS/ GETTRADEAGREEMENTS. /// Then return the whole struct PriceResult rather than PriceResult.Price. /// </summary> /// <param name="tradeAgreementRules">The trade agreement rules.</param> /// <param name="priceParameters">The price parameters.</param> /// <param name="currencyCode">The currency code.</param> /// <param name="itemId">The item Id.</param> /// <param name="defaultSalesUnit">The default sales unit.</param> /// <param name="salesUnit">The sales unit.</param> /// <param name="variantLine">The variant line.</param> /// <param name="unitOfMeasureConversion">The UnitOfMeasure Conversion.</param> /// <param name="quantity">The quantity.</param> /// <param name="customerId">The customer Id.</param> /// <param name="customerPriceGroup">The customer price group.</param> /// <param name="channelPriceGroupIds">The channel price group Ids.</param> /// <param name="salesLines">Optional sales lines.</param> /// <param name="priceContext">Price context.</param> /// <param name="activeDate">The active date.</param> /// <returns>The PriceResult of active trade agreement.</returns> internal static PriceResult GetPriceResultOfActiveTradeAgreement( IDictionary <string, IList <TradeAgreement> > tradeAgreementRules, DiscountParameters priceParameters, string currencyCode, string itemId, string defaultSalesUnit, string salesUnit, ProductVariant variantLine, UnitOfMeasureConversion unitOfMeasureConversion, decimal quantity, string customerId, string customerPriceGroup, IEnumerable <string> channelPriceGroupIds, IEnumerable <SalesLine> salesLines, PriceContext priceContext, DateTimeOffset activeDate) { PriceResult result; variantLine = variantLine ?? new ProductVariant(); // Get basic arguments for Price evaluation RetailPriceArgs args = new RetailPriceArgs() { Barcode = string.Empty, CurrencyCode = currencyCode, CustomerId = customerId, Dimensions = variantLine, DefaultSalesUnitOfMeasure = defaultSalesUnit, ItemId = itemId, PriceGroups = channelPriceGroupIds.AsReadOnly(), Quantity = quantity, SalesUOM = salesUnit, UnitOfMeasureConversion = unitOfMeasureConversion, }; // Get the active retail price - checks following prices brackets in order: Customer TAs, Store price group TAs, 'All' TAs. // First bracket to return a price 'wins'. Each bracket returns the lowest price it can find. result = FindPriceAgreement(tradeAgreementRules, priceParameters, args, salesLines, priceContext, activeDate); // Direct customer TA price would have been caught above. // Compare against customer price group TAs now and override if lower than previously found price (or if previously found price was 0). if (!string.IsNullOrEmpty(customerId) && !string.IsNullOrEmpty(customerPriceGroup) && !channelPriceGroupIds.Contains(customerPriceGroup)) { // Customer price group args.PriceGroups = new ReadOnlyCollection <string>(new[] { customerPriceGroup }); PriceResult customerResult = FindPriceAgreement(tradeAgreementRules, priceParameters, args, salesLines, priceContext, activeDate); // Pick the Customer price if either the Retail price is ZERO, or the Customer Price is non-zero AND lower if ((result.Price == decimal.Zero) || ((customerResult.Price > decimal.Zero) && (customerResult.Price <= result.Price))) { result = customerResult; } } return(result); }
public void CheckZeroVolForward(AssetMarket assetMkt) { var zcCurve = assetMkt.RiskFreeDiscount; var market = new Market(new[] { zcCurve }, new[] { assetMkt }); var zeroVol = new MapRawDatas <DateOrDuration, double>(new[] { new DateOrDuration(assetMkt.RefDate) }, new[] { 0.0 }); var blackScholesDesc = new BlackScholesModelDescription(assetMkt.Asset.Name, zeroVol, true); var mcConfig = new MonteCarloConfig(1, RandomGenerators.GaussianSobol(SobolDirection.Kuo3)); var blackScholesModel = ModelFactory.Instance.Build(blackScholesDesc, market); var fwdDates = new[] { Duration.Month, 6 * Duration.Month, Duration.Year, 2 * Duration.Year, 5 * Duration.Year } .Map(d => assetMkt.RefDate + d); IProduct fwdLeg = ForwardLeg(fwdDates); PriceResult priceResult = (PriceResult)McPricer.WithDetails(mcConfig).Price(fwdLeg, blackScholesModel, market); double[] fwds = priceResult.Details.Map(kv => kv.Item3.Value); var assetFwdCurve = assetMkt.Forward(); double[] refFwds = fwdDates.Map(d => assetFwdCurve.Fwd(d) * zcCurve.Zc(d)); foreach (var i in Enumerable.Range(0, fwdDates.Length)) { var err = Math.Abs(fwds[i] / refFwds[i] - 1.0); Assert.LessOrEqual(err, 20.0 * DoubleUtils.MachineEpsilon); } }
/// <summary> /// Gets maximum retail price from trade agreement. /// </summary> /// <param name="salesLine">The sales line.</param> /// <param name="context">The request context.</param> /// <returns>Maximum retail price from trade agreement.</returns> public decimal GetMaximumRetailPriceFromTradeAgreement(SalesLine salesLine, RequestContext context) { if (salesLine == null) { throw new ArgumentNullException("salesLine"); } decimal quantity = this.salesTransaction.ActiveSalesLines.Where(x => (x.ItemId == salesLine.ItemId) && (x.InventoryDimensionId == salesLine.InventoryDimensionId)).Sum(x => x.Quantity); if (quantity == decimal.Zero) { quantity = 1; } if (!salesLine.BeginDateTime.IsValidAxDateTime()) { salesLine.BeginDateTime = context.GetNowInChannelTimeZone(); } PriceResult priceResult = PricingEngine.GetActiveTradeAgreement( this.pricingDataManager, DiscountParameters.CreateAndInitialize(this.pricingDataManager), this.channelConfiguration.Currency, salesLine, quantity, this.customerId, this.priceGroup, salesLine.BeginDateTime); this.maxRetailPrice = priceResult.MaximumRetailPriceIndia; return(this.maxRetailPrice); }
private static PriceResult FindPriceAgreement( IDictionary <string, IList <TradeAgreement> > tradeAgreementRules, DiscountParameters priceParameters, RetailPriceArgs args, IEnumerable <SalesLine> salesLines, PriceContext priceContext, DateTimeOffset activeDate) { // First we get the price according to the base UOM PriceAgreementArgs p = args.AgreementArgsForDefaultSales(); PriceResult result = ApplyPriceTradeAgreements(tradeAgreementRules, p, priceParameters, salesLines, priceContext, activeDate); // Is the current UOM something different than the base UOM? if (args.SalesUOM != args.DefaultSalesUnitOfMeasure) { // Then let's see if we find some price agreement for that UOM p = args.ArgreementArgsForSale(); PriceResult salesUOMResult = ApplyPriceTradeAgreements(tradeAgreementRules, p, priceParameters, salesLines, priceContext, activeDate); // If there is a price found then we return that as the price if (salesUOMResult.Price > decimal.Zero) { return(salesUOMResult); } else { return(new PriceResult(result.Price * args.UnitOfMeasureConversion.GetFactorForQuantity(args.Quantity), result.IncludesTax, custPriceGroup: result.CustPriceGroup)); } } // else we return baseUOM price mulitplied with the unit qty factor. return(result); }
public void DescribeIsCorrect(decimal baseAmount, decimal taxRate, decimal afterTax, string expectedDescription) { string filename = "The Little Prince"; int upc = 12345; PriceResult priceResult = new PriceResult(filename, upc, new MoneyCurrency(baseAmount), taxRate, new MoneyCurrency(afterTax)); Assert.Equal(expectedDescription, priceResult.Describe()); }
public void DescribeIsCorrect(decimal taxRate) { PriceCalculator priceCalculator = new PriceCalculator(taxRate); PriceResult priceResult = priceCalculator.Calculate(product); Assert.Equal(product.Title, priceResult.Title); Assert.Equal(product.UPC, priceResult.Upc); Assert.Equal(product.Amount, priceResult.BaseAmount); Assert.Equal(taxRate, priceResult.TaxRate); Assert.Equal(product.Amount + product.Amount * taxRate, priceResult.AfterTax); }
public void SubTotal_IsCorrect() { // arrange var product = new Product("Widget", 12345, Money.USDollar(12.35)); var pr = new PriceResult(); pr.Product = product; // act var result = pr.Subtotal(); // assert Assert.True(result == Money.USDollar(12.35)); }
public void Discount_IsCorrect() { // arrange var product = new Product("Widget", 12345, Money.USDollar(12.35)); var pr = new PriceResult(); pr.Product = product; pr.DiscountRatePercent = 0.15M; // act var result = pr.Discount(); // assert Assert.True(result == Money.USDollar(1.85)); }
public void Total_IsCorrect() { // arrange var product = new Product("Widget", 12345, Money.USDollar(12.35)); var pr = new PriceResult(); pr.Product = product; pr.TaxRatePercent = 0.07M; // act var result = pr.Total(); // assert Assert.True(result == Money.USDollar(13.21)); }
/// <summary> /// This function takes arguments (customer, item, currency, etc.) related to price (trade) agreement /// as well as the set of currently enabled trade agreement types. It returns the best trade agreement /// price for the given constraints. /// As in AX, the method searches for a price on the given item which has been given to a /// customer, price group, or anyone (in given precedence order). If a price is found and marked as /// SearchAgain=False, the search will terminate. Otherwise, search for lowest price will continue. /// To recap, the logic is that three searches are done for customer, price group, and all, each bracket /// will return the lowest price it has for the constraints. If it has SearchAgain=True, then the search /// for lowest price continues to the next bracket. /// </summary> /// <param name="tradeAgreementRules">Trade agreements applicable to each item, keyed by item relation (i.e. item Id).</param> /// <param name="args">Arguments for price agreement search.</param> /// <param name="priceParameters">Set of enabled price agreement types.</param> /// <param name="salesLines">Sales lines.</param> /// <param name="priceContext">Price context.</param> /// <param name="activeDate">Date to use for querying trade agreement rules.</param> /// <returns> /// Most applicable price for the given price agreement constraints. /// </returns> private static PriceResult ApplyPriceTradeAgreements( IDictionary <string, IList <TradeAgreement> > tradeAgreementRules, PriceAgreementArgs args, DiscountParameters priceParameters, IEnumerable <SalesLine> salesLines, PriceContext priceContext, DateTimeOffset activeDate) { PriceResult priceResult = new PriceResult(0M, PriceGroupIncludesTax.NotSpecified); var itemCodes = new PriceDiscountItemCode[] { PriceDiscountItemCode.Item, PriceDiscountItemCode.ItemGroup, PriceDiscountItemCode.AllItems }; var accountCodes = new PriceDiscountAccountCode[] { PriceDiscountAccountCode.Customer, PriceDiscountAccountCode.CustomerGroup, PriceDiscountAccountCode.AllCustomers }; // Search through combinations of item/account codes from most to least specific. // This needs to match the behavior of AX code PriceDisc.findPriceAgreement(). foreach (var accountCode in accountCodes) { foreach (var itemCode in itemCodes) { if (priceParameters.Activation(PriceDiscountType.PriceSales, accountCode, itemCode)) { IList <string> accountRelations = args.GetAccountRelations(accountCode); string itemRelation = args.GetItemRelation(itemCode); if (accountRelations.All(a => ValidRelation(accountCode, a)) && ValidRelation(itemCode, itemRelation)) { bool searchAgain; IEnumerable <TradeAgreement> tradeAgreements = FindPriceAgreements(tradeAgreementRules, args, itemCode, accountCode, salesLines, priceContext, activeDate); PriceResult currentPriceResult = GetBestPriceAgreement(tradeAgreements, out searchAgain); if (priceResult.Price == 0M || (currentPriceResult.Price > 0M && currentPriceResult.Price < priceResult.Price)) { priceResult = currentPriceResult; } if (!searchAgain) { break; } } } } } return(priceResult); }
public void TotalWithDiscountAndTax_IsCorrect() { // arrange var product = new Product("Widget", 12345, Money.USDollar(20.25)); var pr = new PriceResult(); pr.Product = product; pr.TaxRatePercent = 0.20M; pr.DiscountRatePercent = 0.15M; // act // assert Assert.True(pr.Tax() == Money.USDollar(4.05)); Assert.True(pr.Discount() == Money.USDollar(3.04)); Assert.True(pr.Total() == Money.USDollar(21.26)); }
public object[,] PublishPriceResult(PriceResult priceResult) { var price = priceResult.Price; var result = PublisherServices.PublishScalar(string.Format("Price ({0})", price.Currency), price.Value); DateTime[] payDates; Currency[] payCurrencies; double[,] detailValues; PricingDetails(priceResult.Details, out payDates, out payCurrencies, out detailValues); var details = new object[payDates.Length + 1, payCurrencies.Length + 1]; details[0, 0] = "PricingDetails"; ArrayUtils.SetSubArray(ref details, 1, 1, detailValues.Map(v => (object)v)); ArrayUtils.SetSubArray(ref details, 1, 0, payDates.Cast <object>().ToArray().AsColumn()); ArrayUtils.SetSubArray(ref details, 0, 1, payCurrencies.Map(c => (object)c.ToString()).AsRow()); result = result.AppendUnder(details, 1); return(result); }
public IActionResult GetPrices() { xServer.Stats.IncrementPublicRequest(); if (xServer.Stats.TierLevel == ServerNode.Tier.TierLevel.Three) { var priceResults = new List <PriceResult>(); foreach (var pair in priceFeature.FiatPairs) { PriceResult priceResult = new PriceResult() { Price = pair.GetMytPrice(), Pair = (int)pair.Currency }; priceResults.Add(priceResult); } return(Json(priceResults)); } else { return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "Tier 3 requirement not meet", "The node you requested is not a tier 3 node.")); } }
public static void GetPriceList() { modelData = new List <ModelData>(); priceList.Rows.Clear(); string responseFromServer = GenerateRequest("Home", "GetPriceList", "GET", null); if (responseFromServer == null) { return; } PriceResult result = JsonConvert.DeserializeObject <PriceResult>(responseFromServer); List <ModelData> data = new List <ModelData>(); foreach (var jsonData in result.JsonDatas) { try { data.Add(JsonConvert.DeserializeObject <ModelData>(jsonData)); } catch (Exception) { throw; } } foreach (var item in result.Items) { ParseAndAddItem(item, data); } foreach (var d in modelData) { priceList.Rows.Add(AddRow(d)); } }
public IActionResult GetPrice(int fiatPairId) { xServer.Stats.IncrementPublicRequest(); if (xServer.Stats.TierLevel == ServerNode.Tier.TierLevel.Three) { var fiatPair = priceFeature.FiatPairs.Where(f => (int)f.Currency == fiatPairId).FirstOrDefault(); if (fiatPair != null) { PriceResult priceResult = new PriceResult() { Price = fiatPair.GetMytPrice() }; return(Json(priceResult)); } else { return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "Invalid Pair", "The pair supplied does not exist.")); } } else { return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "Tier 3 requirement not meet", "The node you requested is not a tier 3 node.")); } }
private static Tuple <decimal, string> GetActiveTradeAgreementPriceAndGroup( IDictionary <string, IList <TradeAgreement> > tradeAgreementRules, DiscountParameters priceParameters, string currencyCode, string itemId, string defaultSalesUnit, string salesUnit, ProductVariant variantLine, UnitOfMeasureConversion unitOfMeasureConversion, decimal quantity, string customerId, string customerPriceGroup, IEnumerable <string> channelPriceGroupIds, IEnumerable <SalesLine> salesLines, PriceContext priceContext, DateTimeOffset activeDate) { PriceResult result = GetPriceResultOfActiveTradeAgreement( tradeAgreementRules, priceParameters, currencyCode, itemId, defaultSalesUnit, salesUnit, variantLine, unitOfMeasureConversion, quantity, customerId, customerPriceGroup, channelPriceGroupIds, salesLines, priceContext, activeDate); return(new Tuple <decimal, string>(result.Price, result.CustPriceGroup)); }
public static EnergyQuote ToEnergyQuote(this PriceResult priceResult) { return(new EnergyQuote { KeyFeatures = priceResult.KeyFeatures.Select( x => new Models.PriceFeature { Category = x.Category.ToString(), ClassName = x.ClassName, Description = x.Description }).ToList(), Id = priceResult.Id, ResultId = priceResult.ResultId, SupplierId = priceResult.SupplierId, SupplierName = priceResult.SupplierName, SupplierRating = priceResult.SupplierRating, SupplierCss = priceResult.SupplierCss, TariffId = priceResult.TariffId, TariffName = priceResult.TariffName, TariffDetailsUrl = priceResult.TariffDetailsUrl, HasTariffCustomFeature = priceResult.HasTariffCustomFeature, CustomFeatureText = priceResult.CustomFeatureText, PaymentMethod = (int)priceResult.PaymentMethod, PaymentMethodId = priceResult.PaymentMethodId, CanApply = priceResult.CanApply, AnnualSavings = priceResult.AnnualSavings, AnnualSpend = priceResult.AnnualSpend, ElectricityAnnualSavings = priceResult.ElectricityAnnualSavings, ElectricityAnnualSpend = priceResult.ElectricityAnnualSpend, GasAnnualSavings = priceResult.GasAnnualSavings, GasAnnualSpend = priceResult.GasAnnualSpend, RenewableFuelPercentage = priceResult.RenewableFuelPercentage, PaperLessBilling = priceResult.PaperLessBilling, PaperBilling = priceResult.PaperBilling, NoStandingCharges = priceResult.NoStandingCharges, CappedOrFixed = priceResult.CappedOrFixed, Green = priceResult.Green, AccurateMonthlyBilling = priceResult.AccurateMonthlyBilling, StayWarm = priceResult.StayWarm, Economy10 = priceResult.Economy10, Cashback = priceResult.Cashback, Hide = priceResult.Hide, TotalExitFees = priceResult.TotalExitFees, ElectricityEstimatedMonthlyCost = priceResult.ElectricityEstimatedMonthlyCost, GasEstimatedMonthlyCost = priceResult.GasEstimatedMonthlyCost, IsMostPopularTariffForUser = priceResult.IsMostPopularTariffForUser, IsCollectiveTariff = priceResult.IsCollectiveTariff, IsExclusiveTariff = priceResult.IsExclusiveTariff, ShowInRelevancyBox = priceResult.ShowInRelevancyBox, ShowStrapline = priceResult.ShowStrapline, CheapestBigSupplier = priceResult.CheapestBigSupplier, CheapestLongFixed = priceResult.CheapestLongFixed, Cheapest = priceResult.Cheapest, CheapestMediumFixed = priceResult.CheapestMediumFixed, CheapestCanApply = priceResult.CheapestCanApply, CheapestGreen = priceResult.CheapestGreen, CheapestHighestRated = priceResult.CheapestHighestRated, CheapestShortFixed = priceResult.CheapestShortFixed }); }
public static List <PriceResult> MapToPriceResults(this FutureSupplies ehlResults, GetPricesRequest request) { var mappedResults = new List <PriceResult>(); var ehlResultsSet = ehlResults.Results.First(r => r.SupplyType.Id.Equals(request.CompareType.EhlSupplyType())); foreach (var supply in ehlResultsSet.EnergySupplies) { var paymentMethod = int.Parse(supply.SupplyDetails.PaymentMethod.Id); var priceResult = new PriceResult { AnnualSavings = decimal.Round(supply.ExpectedAnnualSavings, 0), AnnualSpend = decimal.Round(supply.ExpectedAnnualSpend, 0), ElectricityAnnualSavings = supply.ExpectedElecAnnualSavings, ElectricityAnnualSpend = supply.ExpectedElecAnnualSpend, ElectricityEstimatedMonthlyCost = supply.EstimatedElecMonthlyCost, GasAnnualSavings = supply.ExpectedGasAnnualSavings, GasAnnualSpend = supply.ExpectedGasAnnualSpend, GasEstimatedMonthlyCost = supply.EstimatedGasMonthlyCost, ResultId = supply.Id, SupplierId = int.Parse(supply.Supplier.Id), SupplierName = supply.Supplier.Name, SupplierRating = supply.Supplier.ServiceStarRating, TariffId = int.Parse(supply.SupplyDetails.Id), TariffName = supply.SupplyDetails.Name, TariffDetailsUrl = supply.SupplyDetails.FurtherDetails.Uri, PaymentMethod = (PaymentMethodType)paymentMethod, PaymentMethodId = paymentMethod, CanApply = supply.CanApply, CappedOrFixed = supply.SupplyDetails.Attributes.Any(a => a.Equals("CappedOrFixed", StringComparison.InvariantCultureIgnoreCase)), Green = supply.SupplyDetails.Attributes.Any(a => a.Equals("Green", StringComparison.InvariantCultureIgnoreCase)), AccurateMonthlyBilling = supply.SupplyDetails.Attributes.Any(a => a.Equals("AccurateMonthlyBilling", StringComparison.InvariantCultureIgnoreCase)), StayWarm = supply.SupplyDetails.Attributes.Any(a => a.Equals("StayWarm", StringComparison.InvariantCultureIgnoreCase)), Economy10 = supply.SupplyDetails.Attributes.Any(a => a.Equals("Economy10", StringComparison.InvariantCultureIgnoreCase)), PaperLessBilling = supply.SupplyDetails.Attributes.Any(a => a.Equals("PaperlessBilling", StringComparison.InvariantCultureIgnoreCase)), PaperBilling = supply.SupplyDetails.Attributes.Any(a => a.Equals("PaperBilling", StringComparison.InvariantCultureIgnoreCase)), NoStandingCharges = supply.SupplyDetails.Attributes.Any(a => a.Equals("NoStandingCharges", StringComparison.InvariantCultureIgnoreCase)), RenewableFuelPercentage = supply.SupplyDetails.RenewableFuelPercentage, TotalExitFees = CalculateTotalExitFees(request.CompareType, supply.SupplyDetails.ExitFeesGas, supply.SupplyDetails.ExitFeesElectricity), CheapestBigSupplier = PromotionsValidator(supply.Promotions, "CheapestBigSupplier"), CheapestLongFixed = PromotionsValidator(supply.Promotions, "CheapestLongFixed"), CheapestShortFixed = PromotionsValidator(supply.Promotions, "CheapestShortFixed"), Cheapest = PromotionsValidator(supply.Promotions, "Cheapest"), CheapestMediumFixed = PromotionsValidator(supply.Promotions, "CheapestMediumFixed"), CheapestCanApply = PromotionsValidator(supply.Promotions, "CheapestCanApply"), CheapestGreen = PromotionsValidator(supply.Promotions, "CheapestGreen"), CheapestHighestRated = PromotionsValidator(supply.Promotions, "CheapestHighestRated") }; priceResult.SupplierRating = priceResult.SupplierRating > 5 ? 5 : priceResult.SupplierRating; // Key features priceResult.KeyFeatures = supply.SupplyDetails.KeyFeatures.ToPriceFeatures(); // Set CTM custom feature text if (request.TariffCustomFeatureEnabled) { priceResult.CustomFeatureText = SetCustomFeatureText(string.Concat(priceResult.SupplierName, priceResult.TariffName).ToLowerInvariant(), request.CustomFeatures); priceResult.HasTariffCustomFeature = !string.IsNullOrWhiteSpace(priceResult.CustomFeatureText); } mappedResults.Add(priceResult); } return(mappedResults); }