private FeeCondition ResolveFeeBenefits(PriceCalculationParameters calculationParameters, FeeCondition fee) { var feeKind = ((EnumMemberAttribute[])(typeof(FeeConditionKind)).GetField(fee.Kind.ToString()) .GetCustomAttributes(typeof(EnumMemberAttribute), true))?.FirstOrDefault()?.Value; fee.Variations = fee.Variations ?? new List <FeeVariation>(); fee.Variations = fee.Variations.Where(nv => nv.Origin != PriceVariationOrigins.Campaign).ToList(); if (calculationParameters.Campaign?.Benefits != null) { var benefitsForFee = calculationParameters.Campaign.Benefits.Where(b => b.Kind == feeKind)?.ToList(); if (benefitsForFee != null && benefitsForFee.Count() > 0) { foreach (var benefit in benefitsForFee) { fee.Variations.Add(new FeeVariation { BenefitId = benefit.Code, BenefitSourceId = calculationParameters.Campaign.CampaignCode, Origin = PriceVariationOrigins.Campaign, Percentage = benefit.Value, VariationDescription = benefit.Description, VariationGroup = calculationParameters.Campaign.Description }); } } } return(fee); }
public ActionResult GunPage(int Id, bool Tracer, bool Hollowpoint, bool Incendiary, string firstName, string lastName, int resId) { var ggun = gunrepo.GetGun(Id); var parameters = new PriceCalculationParameters() { gun = ggun, Tracer = Tracer, Hollowpoint = Hollowpoint, Incendiary = Incendiary }; var model = new IndexPageViewModel() { _Gun = gunrepo.GetGun(Id), PriceComponents = price.CalculatePrice(parameters) }; var order = new Order(); order.FirstName = firstName; order.LastName = lastName; order.GunId = Id; this.orderrep.Create(order); Gun gun = gunrepo.GetGun(Id); gunrepo.UpdateCount(gun); Reservation reservation = resrepo.Get(resId); resserv.RemoveReservation(reservation); return(View(model)); }
public PriceCalculationParameters GetPriceCalculationParameters(string productCode) { var defaultArrangementRequest = ArrangementRequests? .Where(x => x.ProductCode.Equals(ProductCode)).FirstOrDefault(); var priceCalc = new PriceCalculationParameters { RequestDate = RequestDate, Channel = ChannelCode, RiskScore = RiskScore, CustomerSegment = CustomerSegment, CustomerValue = CustomerValue, CreditRating = CreditRating, DebtToIncome = DebtToIncome }; if (defaultArrangementRequest != null && defaultArrangementRequest.ProductSnapshot != null && defaultArrangementRequest.ProductSnapshot.IsPackage) { priceCalc.AdditionalProperties = ArrangementRequests? .Where(r => !r.ProductCode.Equals(ProductCode)) .Select(b => new { b.ProductCode, Enabled = b.Enabled ?? false }) .Distinct() .ToDictionary(k => k.ProductCode, v => (JToken)v.Enabled); } return(priceCalc); }
public List <PriceComponent> CalculatePrice(PriceCalculationParameters parameters) { var gun = _gunRepository.GetPrice(parameters.gun.Price); var newPriceComponents = new List <PriceComponent>(); if (parameters.Tracer == true) { newPriceComponents.Add(new PriceComponent { Name = "Tracet", Value = 100 }); } if (parameters.Hollowpoint == true) { newPriceComponents.Add(new PriceComponent { Name = "Hollowpoint", Value = 110 }); } if (parameters.Incendiary == true) { newPriceComponents.Add(new PriceComponent { Name = "Incendiary", Value = 120 }); } return(newPriceComponents); }
private FeeCondition ResolveFeeOptions(PriceCalculationParameters calculationParameters, FeeCondition fee) { var feeKind = ((EnumMemberAttribute[])(typeof(FeeConditionKind)).GetField(fee.Kind.ToString()) .GetCustomAttributes(typeof(EnumMemberAttribute), true))?.FirstOrDefault()?.Value; fee.Variations = fee.Variations ?? new List <FeeVariation>(); fee.Variations = fee.Variations.Where(nv => nv.Origin != PriceVariationOrigins.ProductOptions).ToList(); if (calculationParameters.Options != null && calculationParameters.Options.Count() > 0) { foreach (var option in calculationParameters.Options) { var effectsForFee = option.Effects.Where(b => b.Kind == feeKind)?.ToList(); if (effectsForFee != null && effectsForFee.Count() > 0) { foreach (var effect in effectsForFee) { fee.Variations.Add(new FeeVariation { BenefitId = effect.Code, BenefitSourceId = option.Code, Origin = PriceVariationOrigins.ProductOptions, Percentage = effect.Value, VariationDescription = option.Description, VariationGroup = effect.Description }); } } } } return(fee); }
public async Task <ArrangementRequest> CalculateAsCalculationService( ArrangementRequest arrangementRequest, PriceCalculationParameters priceCalculationParameters) { List <PricedScheduledPeriod> pricedAndScheduledPeriods = null; if (priceCalculationParameters.ScheduledPeriods != null) { // var conversionMethod = await _configurationService.GetEffective("offer/fee-currency-conversion-method", "Buy to middle"); pricedAndScheduledPeriods = SchedulingPeriodsResolver.PricePeriods(arrangementRequest, priceCalculationParameters, _offerPriceCalculation); } // Perform price calculation for main conditions (whole repayment period) List <ScheduledPeriod> scheduledPeriods = new List <ScheduledPeriod>(); var hasPeriods = priceCalculationParameters.ScheduledPeriods != null && priceCalculationParameters.ScheduledPeriods.Count() > 0; if (hasPeriods) { priceCalculationParameters.ScheduledPeriods.ForEach(p => scheduledPeriods.Add(p)); priceCalculationParameters.ScheduledPeriods.Clear(); } _ = await _offerPriceCalculation.CalculatePrice(arrangementRequest, priceCalculationParameters); if (hasPeriods) { priceCalculationParameters.ScheduledPeriods = scheduledPeriods; } var request = new CalculateInstallmentPlanRequestCS { Amount = (double)(arrangementRequest is FinanceServiceArrangementRequest fR ? fR.Amount : 0), RegularInterestPercentage = (double)(arrangementRequest?.Conditions?.InterestRates?.Where(r => r.Kind == InterestRateKinds.RegularInterest && string.IsNullOrEmpty(r.Periods)).Select(r => r.CalculatedRate).FirstOrDefault() ?? 0), // todo check StartDate = priceCalculationParameters.RequestDate, Currency = arrangementRequest is FinanceServiceArrangementRequest fRc?GetCurrencyCode(fRc.Currency) : "978", RegularInterestUnitOfTime = CalculationService.Services.SimpleUnitOfTime.Y, Term = arrangementRequest is FinanceServiceArrangementRequest fRt ? fRt.Term : "0", Periods = pricedAndScheduledPeriods }; request = AppendFees(request, arrangementRequest); request = AppendPredefinedPeriods(request, arrangementRequest); var plan = _calculator.CalculateInstallmentPlan(request); arrangementRequest.CalculationDate = priceCalculationParameters.RequestDate; arrangementRequest.NumberOfInstallments = (int)(plan.NumberOfInstallments ?? 0); arrangementRequest.InstallmentPlan = AggregatesModel.ApplicationAggregate.InstallmentPlanRow.FromInstallmentPlanCSList(plan.Installments); // TODO Think about this casts if (arrangementRequest is FinanceServiceArrangementRequest fSR) { fSR.Eapr = (decimal)(plan.EffectiveInterestRate ?? 0); if (arrangementRequest is TermLoanRequest trl) { trl.Annuity = (decimal)(plan.Annuity ?? 0); } } return(arrangementRequest); }
private async Task <ResolvedFeesResult> CalculateFees(PriceCalculationParameters calculationParameters, VariationDefinitionParams definitionParams) { // TODO Include all fee parameters (limits and percentage) in DMN and in calculation var result = new ResolvedFeesResult { ResultChanged = false }; if (calculationParameters.Fees != null) { var arrFees = calculationParameters.Fees; result.Fees = new List <FeeCondition>(); foreach (FeeCondition fee in arrFees) { if (fee == null || fee.EffectiveDate > DateTime.Today || (fee.Currencies != null && !fee.Currencies.Contains(calculationParameters.Currency))) { continue; } var newFee = fee.Copy(); newFee = ResolveFeeBenefits(calculationParameters, newFee); newFee = ResolveFeeOptions(calculationParameters, newFee); if (!string.IsNullOrEmpty(newFee.VariationsDefinitionDMN)) { var newVars = await priceCalculationService.ResolveFeeVariationDmn(newFee.VariationsDefinitionDMN, definitionParams, newFee.VariationsDefinition);; if (newVars != null && newVars.Count > 0) { if (newFee.Variations != null || newFee.Variations.Count > 0) { newFee.Variations = newFee.Variations.Where(nv => nv.Origin != PriceVariationOrigins.Product).ToList(); } else { newFee.Variations = new List <FeeVariation>(); } newFee.Variations.AddRange(newVars); } } var calculatedFixedAmount = newFee.CalculatedFixedAmount; var calculatedLowerLimit = newFee.CalculatedLowerLimit; var calculatedUpperLimit = newFee.CalculatedUpperLimit; var calculatedPercentage = newFee.CalculatedPercentage; var calculatedFee = SolveFeeCondition(newFee); if (calculatedFee.CalculatedPercentage != calculatedPercentage || calculatedFee.CalculatedFixedAmount != calculatedFixedAmount || calculatedFee.CalculatedLowerLimit != calculatedLowerLimit || calculatedFee.CalculatedUpperLimit != calculatedUpperLimit) { result.ResultChanged = true; } result.Fees.Add(calculatedFee); } } return(result); }
public List <PriceComponent> CalculatePrice(PriceCalculationParameters parameters) { var allPriceComponents = new List <PriceComponent>(); foreach (var s in _strategies) { allPriceComponents.AddRange(s.CalculatePrice(parameters)); } return(allPriceComponents); }
public List <PriceComponent> CalculatePrice(PriceCalculationParameters parameters) { var components = new List <PriceComponent>(); var gun = _gunRepository.GetGun(parameters.gun.Id); var placeComponent = new PriceComponent() { Name = "Main price" }; placeComponent.Value = gun.Price; components.Add(placeComponent); return(components); }
public async Task <PriceCalculationResult> CalculatePrice(PriceCalculationParameters calculationParameters) { var definitionParams = GetVariationDefinitionParams(calculationParameters); var resultChanged = false; var ratesResult = await CalculateInterestRates(calculationParameters, definitionParams); var feesResult = await CalculateFees(calculationParameters, definitionParams); return(new PriceCalculationResult { InterestRates = ratesResult.Rates, Fees = feesResult.Fees, Napr = ratesResult.Napr, ResultChanged = resultChanged || ratesResult.ResultChanged || feesResult.ResultChanged }); }
public Order CreateOrder(int Id, string firstName, string lastName, PriceCalculationParameters parameters) { var guns = gunRepository.GetGun(Id); var newOrder = new Order { GunId = guns.Id, FirstName = firstName, LastName = lastName, PriceComponents = new List <PriceComponent>(), }; newOrder.PriceComponents = _priceCalculation.CalculatePrices(parameters); guns.Id = newOrder.GunId; orderRepository.Create(newOrder); return(newOrder); }
private VariationDefinitionParams GetVariationDefinitionParams(PriceCalculationParameters parameters) { var defaultParamsString = configurationService.GetEffective("offer/price-calculation/default-parameters").Result; var defaultParams = (VariationDefinitionParams)CaseUtil.ConvertFromJsonToObject(defaultParamsString, typeof(VariationDefinitionParams)); var defParams = new VariationDefinitionParams { Channel = parameters.Channel ?? defaultParams.Channel, Amount = parameters.Amount, Currency = parameters.Currency }; defParams.CustomerSegment = parameters.CustomerSegment ?? defaultParams.CustomerSegment; defParams.RiskScore = parameters.RiskScore ?? defaultParams.RiskScore; defParams.PartOfBundle = parameters.PartOfBundle ?? defaultParams.PartOfBundle; defParams.CollateralModel = parameters.CollateralModel ?? defaultParams.CollateralModel; defParams.HasCampaignInculded = parameters.Campaign != null; defParams.DebtToIncome = parameters.DebtToIncome ?? defaultParams.DebtToIncome; defParams.CustomerValue = parameters.CustomerValue ?? defaultParams.CustomerValue; defParams.CreditRating = parameters.CreditRating ?? defaultParams.CreditRating; var bundledComponentns = parameters.AdditionalProperties ?? defaultParams.AdditionalProperties; defParams.AdditionalProperties = new Dictionary <string, JToken>(); var jsonData = JsonConvert.SerializeObject(bundledComponentns); if (jsonData.Equals("{}")) { Console.WriteLine( new System.Diagnostics.StackTrace().ToString() ); } foreach (var item in bundledComponentns) { defParams.AdditionalProperties.Add("bundledComponent_" + item.Key, item.Value); } try { defParams.Term = Utility.GetMonthsFromPeriod(parameters.Term); } catch (Exception e) { Console.WriteLine(e); defParams.Term = 0; } return(defParams); }
/*public static List<PricedScheduledPeriod> ScheduleAndPricePeriods(ResolveSchedulingPeriodsRequest request, * ArrangementRequest arrangementRequest, PriceCalculationParameters priceParams, OfferPriceCalculation priceCalc, * string conversionMethod) * { * var scheduledAndPricedPeriods = new List<PricedScheduledPeriod>(); * ArrangementRequest arrangementRequestTemp; * foreach (var period in priceParams.ScheduledPeriods) * { * arrangementRequestTemp = Mapper.Map<ArrangementRequest, ArrangementRequest>(arrangementRequest); * arrangementRequestTemp.CalculateOffer(priceParams, priceCalc, conversionMethod); * scheduledAndPricedPeriods.Add(new PricedScheduledPeriod * { * Percentage = (double)(arrangementRequestTemp?.Conditions?.InterestRates?.Where(r => r.Kind == InterestRateKinds.RegularInterest).Select(r => r.CalculatedRate).FirstOrDefault() ?? 0), * PeriodType = period.PeriodType, * StartDate = period.StartDate, * EndDate = period.EndDate, * // TODO To be resolved from DMN maybe? * UnitOfTime = CalculationService.Services.SimpleUnitOfTime.Y * }); * } * return scheduledAndPricedPeriods; * }*/ public static List <PricedScheduledPeriod> PricePeriods( ArrangementRequest arrangementRequest, PriceCalculationParameters priceParams, OfferPriceCalculation priceCalc) { var scheduledAndPricedPeriods = new List <PricedScheduledPeriod>(); var scheduledPeriods = new List <ScheduledPeriod>(); var rates = new List <InterestRateCondition>(); if (priceParams.ScheduledPeriods != null) { priceParams.ScheduledPeriods.ForEach(p => scheduledPeriods.Add(p)); } if (priceParams.InterestRates != null) { priceParams.InterestRates.ForEach(r => rates.Add(r)); } foreach (var period in scheduledPeriods) { priceParams.ScheduledPeriods.Clear(); priceParams.ScheduledPeriods.Add(period); _ = priceCalc.CalculatePrice(arrangementRequest, priceParams).Result; // arrangementRequest.CalculateOffer(priceParams, priceCalc, conversionMethod); scheduledAndPricedPeriods.Add(new PricedScheduledPeriod { Percentage = (double)(arrangementRequest?.Conditions?.InterestRates?.Where(r => r.Kind == InterestRateKinds.RegularInterest).Select(r => r.CalculatedRate).FirstOrDefault() ?? 0), PeriodType = period.PeriodType, StartDate = period.StartDate, EndDate = period.EndDate, // TODO To be resolved from DMN maybe? UnitOfTime = CalculationService.Services.SimpleUnitOfTime.Y }); } if (scheduledPeriods != null) { priceParams.ScheduledPeriods = scheduledPeriods; } if (rates != null) { priceParams.InterestRates = rates; } return(scheduledAndPricedPeriods); }
public ActionResult ReserveGun(int gunId) { var ggun = gunrepo.GetGun(gunId); var date = DateTime.Now; var parameters = new PriceCalculationParameters() { gun = ggun }; var reservation = resserv.Reserve(ggun); var model = new ReservationViewModel() { Reservation = reservation, gun = ggun, PriceComponents = price.CalculatePrice(parameters), Date = date, }; return(View(model)); }
public async Task <PriceCalculationResponse> Handle(InitiatePriceCalculationCommand message, CancellationToken cancellationToken) { ProductConditions conditions = await _priceCalculation.ReadVariationDefinitions(new ProductConditions { Fees = message.Fees == null ? null : new List <FeeCondition>(message.Fees), InterestRates = message.InterestRates == null ? null : new List <InterestRateCondition>(message.InterestRates) }); var calcParams = new PriceCalculationParameters { InterestRates = conditions.InterestRates, Fees = conditions.Fees, Amount = message.Amount, Term = message.Term, Currency = message.Currency, Channel = message.Channel, RiskScore = message.RiskScore, CustomerSegment = message.CustomerSegment, CollateralModel = message.CollateralModel, PartOfBundle = message.ProductBundling, Campaign = message.Campaign, Options = message.ProductOptions, CreditRating = message.CreditRating, CustomerValue = message.CustomerValue, DebtToIncome = message.DebtToIncome, AdditionalProperties = message.BundledComponents }; var calcResult = await _priceCalculator.CalculatePrice(calcParams); var result = new PriceCalculationResponse { Fees = calcResult.Fees, InterestRates = calcResult.InterestRates, Napr = calcResult.Napr }; return(result); }
public override void CalculateOffer(PriceCalculationParameters calculationParameters, OfferPriceCalculation priceCalculator, string conversionMethod) { _ = priceCalculator.CalculatePrice(this, calculationParameters).Result; CalculateInstallmentPlan(conversionMethod); }
private ArrangementRequest CalculateBySimpleCalculation(ArrangementRequest request, PriceCalculationParameters priceCalculationParameters) { if (!(request is FinanceServiceArrangementRequest)) { return(request); } var priceCalc = (OfferPriceCalculation)_serviceProvider.GetService(typeof(OfferPriceCalculation)); var priceArrangementRequest = priceCalc.CalculatePriceBySimpleCalculation(request, priceCalculationParameters).Result; request.Conditions = priceArrangementRequest.Conditions; priceCalculationParameters.InterestRates = request.Conditions.InterestRates; priceCalculationParameters.Fees = request.Conditions.Fees; priceCalculationParameters.OtherConditions = request.Conditions.Other; var basicCalculation = Mapper.Map <ArrangementRequest, SimpleLoanCalculationRequest>(request); basicCalculation.Fees = new List <FeeEntry>(); basicCalculation.StardDate = new DateTime(basicCalculation.StardDate.Year, basicCalculation.StardDate.Month, basicCalculation.StardDate.Day, 0, 0, 0); priceCalculationParameters.Fees.ForEach(x => { basicCalculation.Fees.Add(new FeeEntry { Kind = x.Kind, Name = x.Title, Frequency = x.Frequency, Percentage = x.Percentage, Currency = x.FixedAmount?.Code ?? "", FixedAmount = x.FixedAmount?.Amount ?? 0, LowerLimit = x.LowerLimit?.Amount ?? 0, UpperLimit = x.UpperLimit?.Amount ?? 0, ServiceCode = x.ServiceCode, Date = basicCalculation.StardDate, CalculationBasisType = CalculationBasisType.AccountBalance }); }); basicCalculation.RegularInterest = priceCalculationParameters.InterestRates .Where(i => i.Currencies.Contains(priceCalculationParameters.Currency) && i.Kind == InterestRateKinds.RegularInterest) .Select(x => new InterestRateEntry { Date = basicCalculation.StardDate, RatePercentage = (double)x.CalculatedRate, IsCompound = x.IsCompound, CalendarBasis = x.CalendarBasis, Name = x.Title, RateUnitOfTime = Domain.Calculations.SimpleUnitOfTime.Y }) .ToList(); if (basicCalculation.RegularInterest.Count == 0) { throw new NotImplementedException("Interest rate is not in product currency"); } var conversionMethod = _configurationService.GetEffective("offer/exposure/currency-conversion-method", "Buy to middle").Result; basicCalculation.FeeCurrencyConversionMethod = conversionMethod; if (basicCalculation.InstallmentSchedule.FrequencyPeriod == 0) { basicCalculation.InstallmentSchedule.FrequencyPeriod = 1; basicCalculation.InstallmentSchedule.FrequencyUnitOfTime = SimpleUnitOfTime.M; } if (basicCalculation.Amount > 0 && basicCalculation.Annuity > 0 && basicCalculation.NumberOfInstallments == 0) { basicCalculation.CalculationTarget = CalculationTarget.Term; basicCalculation.NumberOfInstallments = 0; } else if (basicCalculation.Annuity > 0 && basicCalculation.NumberOfInstallments > 0 && basicCalculation.Amount == 0) { basicCalculation.CalculationTarget = CalculationTarget.Amount; } else { basicCalculation.CalculationTarget = CalculationTarget.Annuity; basicCalculation.Annuity = 0; } var adjustFirstInst = _configurationService.GetEffective("offer/calculation/adjust-first-installment", "false").Result; basicCalculation.AdjustFirstInstallment = Boolean.Parse(adjustFirstInst); var resultBasicCalculation = CalculateInstallmentPlan(basicCalculation); if (request is TermLoanRequest termLoanRequest && resultBasicCalculation != null) { termLoanRequest.Annuity = resultBasicCalculation.Annuity; termLoanRequest.Amount = resultBasicCalculation.Amount; termLoanRequest.Eapr = resultBasicCalculation.APR; termLoanRequest.InstallmentPlan = resultBasicCalculation.Rows; termLoanRequest.NumberOfInstallments = resultBasicCalculation.NumberOfInstallments; termLoanRequest.InstallmentPlan = resultBasicCalculation.Rows; termLoanRequest.RepaymentType = basicCalculation.RepaymentType; termLoanRequest.InstallmentScheduleDayOfMonth = basicCalculation.InstallmentSchedule?.DayOfMonth ?? 1; if (basicCalculation.CalculationTarget == CalculationTarget.Term) { termLoanRequest.Term = resultBasicCalculation.NumberOfInstallments.ToString(); } }
private ArrangementRequest CalculateAsBasic(ArrangementRequest arrangementRequest, PriceCalculationParameters priceCalculationParameters) { var priceCalc = (OfferPriceCalculation)_serviceProvider.GetService(typeof(OfferPriceCalculation)); var conversionMethod = _configurationService.GetEffective("offer/fee-currency-conversion-method", "Buy to middle").Result; arrangementRequest.CalculateOffer(priceCalculationParameters, priceCalc, conversionMethod); return(arrangementRequest); }
public virtual void CalculateOffer(PriceCalculationParameters calculationParameters, OfferPriceCalculation priceCalculator, string conversionMethod) { // To be implemented for each arrangement request subtype }
private async Task <ResolvedRatesResult> CalculateInterestRates(PriceCalculationParameters calculationParameters, VariationDefinitionParams definitionParams) { var bundleVariationGroup = await configurationService .GetEffective("offer/price-calculation/bundle-variation-group", "PRODUCT-BUNDLING-DISCOUNT"); bundleVariationGroup = bundleVariationGroup.ToLower(); var result = new ResolvedRatesResult { ResultChanged = false }; if (calculationParameters.InterestRates != null) { result.Rates = new List <InterestRateCondition>(); var arrRates = calculationParameters.InterestRates; decimal napr = -1; foreach (InterestRateCondition rate in arrRates) { var oldCalculatedRate = rate.CalculatedRate; if ( // check if rate is defined at all rate == null || // check if rate is effective on request date rate.EffectiveDate > calculationParameters.RequestDate || // check if rate is defined for main currency (rate.Currencies != null && !rate.Currencies.Contains(calculationParameters.Currency)) || // check if rate is defined for scheduled periods (if scheduled periods exist at all) (string.IsNullOrEmpty(rate.Periods) && calculationParameters.ScheduledPeriods != null && calculationParameters.ScheduledPeriods.Count() > 0) || (!string.IsNullOrEmpty(rate.Periods) && (calculationParameters.ScheduledPeriods == null || calculationParameters.ScheduledPeriods.Count() == 0)) || (!string.IsNullOrEmpty(rate.Periods) && calculationParameters.ScheduledPeriods != null && calculationParameters.ScheduledPeriods.Count() > 0 && rate.Periods.Replace(" ", "").Split(",").Intersect(calculationParameters.ScheduledPeriods.Select(p => p.PeriodType)).Count() == 0)) { continue; } if (calculationParameters.Amount.HasValue) { definitionParams.AmountInRuleCurrency = GetAmountInRuleCurrency(rate, calculationParameters.Currency, calculationParameters.Amount.Value); } var newRate = rate.Copy(); newRate = ResolveRateBenefits(calculationParameters, newRate); newRate = ResolveRateOptions(calculationParameters, newRate); if (!string.IsNullOrEmpty(newRate.VariationsDefinitionDMN)) { var newVars = await priceCalculationService.ResolveInterestRateVariationDmn(newRate.VariationsDefinitionDMN, definitionParams, newRate.VariationsDefinition); if (newVars != null && newVars.Count > 0) { if (newRate.Variations != null || newRate.Variations.Count > 0) { newRate.Variations = newRate.Variations.Where(nv => nv.Origin != PriceVariationOrigins.Product).ToList(); } else { newRate.Variations = new List <InterestRateVariation>(); } newRate.Variations.AddRange(newVars); } } if (!string.IsNullOrEmpty(newRate.UpperLimitVariationsDefinitionDMN)) { var newVars = await priceCalculationService.ResolveInterestRateVariationDmn(newRate.UpperLimitVariationsDefinitionDMN, definitionParams, newRate.UpperLimitVariationsDefinition); if (newVars != null && newVars.Count > 0) { if (newRate.UpperLimitVariations != null || newRate.UpperLimitVariations.Count > 0) { newRate.UpperLimitVariations = newRate.UpperLimitVariations.Where(nv => nv.Origin != PriceVariationOrigins.Product).ToList(); } else { newRate.UpperLimitVariations = new List <InterestRateVariation>(); } newRate.UpperLimitVariations.AddRange(newVars); } } if (!string.IsNullOrEmpty(newRate.LowerLimitVariationsDefinitionDMN)) { var newVars = await priceCalculationService.ResolveInterestRateVariationDmn(newRate.LowerLimitVariationsDefinitionDMN, definitionParams, newRate.LowerLimitVariationsDefinition); if (newVars != null && newVars.Count > 0) { if (newRate.LowerLimitVariations != null || newRate.LowerLimitVariations.Count > 0) { newRate.LowerLimitVariations = newRate.LowerLimitVariations.Where(nv => nv.Origin != PriceVariationOrigins.Product).ToList(); } else { newRate.LowerLimitVariations = new List <InterestRateVariation>(); } newRate.LowerLimitVariations.AddRange(newVars); } } var newPrice = GetPrice(newRate, calculationParameters.RequestDate ?? DateTime.Today); if (newPrice != oldCalculatedRate) { result.ResultChanged = true; } var rateWoBundle = GetInterestRateWithoutBundle(newRate, bundleVariationGroup, calculationParameters.RequestDate); if (rateWoBundle > 0) { newRate.RateWithoutBundle = rateWoBundle; } if (newRate.Variations.Any(v => v.Origin == PriceVariationOrigins.SalesDiscount)) { newRate.Variations.Reverse(); } result.Rates.Add(newRate); if (newRate.Kind == InterestRateKinds.RegularInterest && napr < 0) { napr = newRate.CalculatedRate; result.Napr = napr; } } } return(result); }
public override void CalculateOffer(PriceCalculationParameters calculationParameters, OfferPriceCalculation priceCalculator, string feeCurrencyConversionMethod) { var ignore = priceCalculator.CalculatePrice(this, calculationParameters).Result; // isCompound i calendarBasis izvuci tokom CalculatePrice da dodatno opisu Napr bool isCompound = false; CalendarBasisKind calendarBasis = CalendarBasisKind.CalendarActActISDA; double yearlyRate = Convert.ToDouble(Napr) / 100; var ir = Conditions.InterestRates.FirstOrDefault(it => it.Kind == InterestRateKinds.RegularInterest); if (ir != null) { isCompound = ir.IsCompound; calendarBasis = ir.CalendarBasis; yearlyRate = Convert.ToDouble(ir.CalculatedRate); Napr = Convert.ToDecimal(yearlyRate); } var startDate = calculationParameters.RequestDate ?? DateTime.Today; List <InstallmentPlanRow> rows = new List <InstallmentPlanRow>(); List <FeeCondition> rowFeeList = new List <FeeCondition>(); List <FeeCondition> fees = Conditions.Fees; fees = FeeCalculation.PrepareFees(fees, Currency, feeCurrencyConversionMethod); decimal runningAmount = Math.Round(Amount, 2); DateTime runningDate = startDate; if (CalculationDate > DateTime.Today) { CalculationDate = runningDate; } else { runningDate = CalculationDate ?? DateTime.Today; } // SLOBA: Fee scheduling, and scheduling in general has to be improved in advanced calculator. decimal totalFeeAmount = 0; if (fees != null) { List <FeeCondition> feeList = fees.FindAll(f => f.Frequency == FeeConditionFrequency.EventTriggered && f.EffectiveDate <= DateTime.Today && f.Currencies.Contains(Currency)); totalFeeAmount = Math.Round(FeeCalculation.CalculateFee(Amount, feeList), 4); } NumberOfInstallments = 1; /* Disbursment */ InstallmentPlanRow rowDisbursement = new InstallmentPlanRow(); rowDisbursement.Date = runningDate; rowDisbursement.Ordinal = 0; rowDisbursement.ActivityKind = ActivityKind.Disbursement; rowDisbursement.Description = "Loan disbursement"; rowDisbursement.Disbursement = Amount; rowDisbursement.StartingBalance = 0; rowDisbursement.OutstandingBalance = Amount; rowDisbursement.PrincipalRepayment = 0; rowDisbursement.InterestRepayment = 0; rowDisbursement.NetCashFlow = Amount - totalFeeAmount; rowDisbursement.Fee = totalFeeAmount; rowDisbursement.YearFrac = 0; rows.Add(rowDisbursement); int i = -1; InstallmentPlanRow rowInterest; var intrStartDate = startDate; runningDate = runningDate.AddMonths(1); while (runningDate <= MaturityDate.Value) { i++; var interest = Math.Round(InterestCalculation.CalculateInterest(intrStartDate, runningDate, runningDate, Convert.ToDouble(yearlyRate), 'Y', isCompound, calendarBasis, Convert.ToDouble(runningAmount)) .Sum(it => it.Interest), 2); rowInterest = new InstallmentPlanRow(); rowInterest.Ordinal = i + 1; rowInterest.Date = runningDate; rowInterest.ActivityKind = ActivityKind.Repayment; rowInterest.Description = "Interest and fee repayment"; rowInterest.InterestRepayment = Convert.ToDecimal(interest); rowInterest.PrincipalRepayment = 0; rowInterest.Annuity = rowInterest.InterestRepayment; rowInterest.StartingBalance = Math.Round(runningAmount, 2); rowInterest.OutstandingBalance = Math.Round(runningAmount, 2); #region Fee calculation if (fees != null) { decimal totalRowFee = 0; rowFeeList = fees.FindAll(f => f.Frequency == FeeConditionFrequency.Monthly && f.EffectiveDate <= DateTime.Today && f.Currencies.Contains(Currency)); if (rowFeeList.Count > 0) { totalRowFee += FeeCalculation.CalculateFee(runningAmount, rowFeeList); } if ((i + 1) % 4 == 0) { rowFeeList = fees.FindAll(f => f.Frequency == FeeConditionFrequency.Quarterly && f.EffectiveDate <= DateTime.Today && f.Currencies.Contains(Currency)); if (rowFeeList.Count > 0) { totalRowFee += FeeCalculation.CalculateFee(runningAmount, rowFeeList); } } if ((i + 1) % 6 == 0) { rowFeeList = fees.FindAll(f => f.Frequency == FeeConditionFrequency.Semiyearly && f.EffectiveDate <= DateTime.Today && f.Currencies.Contains(Currency)); if (rowFeeList.Count > 0) { totalRowFee += FeeCalculation.CalculateFee(runningAmount, rowFeeList); } } if ((i + 1) % 12 == 0) { rowFeeList = fees.FindAll(f => f.Frequency == FeeConditionFrequency.Yearly && f.EffectiveDate <= DateTime.Today && f.Currencies.Contains(Currency)); if (rowFeeList.Count > 0) { totalRowFee += FeeCalculation.CalculateFee(runningAmount, rowFeeList); } } rowInterest.Fee = Math.Round(totalRowFee, 4); } #endregion rowInterest.NetCashFlow = rowInterest.Disbursement - rowInterest.PrincipalRepayment - rowInterest.InterestRepayment - rowInterest.Fee - rowInterest.OtherExpenses; rowInterest.YearFrac = Convert.ToDecimal(InterestCalculation.YearFrac(startDate, runningDate)); //, calendarBasis); rows.Add(rowInterest); intrStartDate = runningDate; runningDate = runningDate.AddMonths(1); } i++; rowInterest = new InstallmentPlanRow(); rowInterest.Ordinal = i + 1; rowInterest.Date = runningDate; rowInterest.ActivityKind = ActivityKind.Repayment; rowInterest.Description = "Principal repayment"; rowInterest.InterestRepayment = 0; rowInterest.PrincipalRepayment = Amount; rowInterest.Annuity = Amount; rowInterest.StartingBalance = Amount; rowInterest.OutstandingBalance = 0; #region Fee calculation rowInterest.Fee = 0; #endregion rowInterest.NetCashFlow = rowInterest.Disbursement - rowInterest.PrincipalRepayment - rowInterest.InterestRepayment - rowInterest.Fee - rowInterest.OtherExpenses; rowInterest.YearFrac = Convert.ToDecimal(InterestCalculation.YearFrac(startDate, runningDate)); //, calendarBasis); rows.Add(rowInterest); NumberOfInstallments = 1; // arrangementRequest.InstallmentPlan = rows; CalculateAPR(rows); }
public async Task <ArrangementRequest> CalculatePriceBySimpleCalculation(ArrangementRequest request, PriceCalculationParameters calcParams) { decimal amount = 0; string term = null; decimal annuity = 0; if (request is TermLoanRequest termLoanRequest) { amount = termLoanRequest.Amount; term = termLoanRequest.Term; annuity = termLoanRequest.Annuity; } var res = await CalculatePrice(calcParams); request.MergePriceCalculationResults(res); if (request is TermLoanRequest tlRequest) { #region TermLoanRequest handling calcParams.InterestRates = res.InterestRates; calcParams.Fees = res.Fees; calcParams.OtherConditions = res.OtherConditions; var priceCalcualtionChanged = res.ResultChanged; var iterations = 1; // One iteration already happend (in initial calculation) while (priceCalcualtionChanged) { if (iterations > maxNumberOfIterations) { throw new MaxNumberOfIterationsException("Maximum number of iterations exceeded."); } res = await CalculatePrice(calcParams); priceCalcualtionChanged = res.ResultChanged; iterations++; } #endregion } return(request); }