Пример #1
0
        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);
        }
Пример #2
0
        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));
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        public List <PriceComponent> CalculatePrice(PriceCalculationParameters parameters)
        {
            var allPriceComponents = new List <PriceComponent>();

            foreach (var s in _strategies)
            {
                allPriceComponents.AddRange(s.CalculatePrice(parameters));
            }

            return(allPriceComponents);
        }
Пример #9
0
        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);
        }
Пример #10
0
        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
            });
        }
Пример #11
0
        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);
        }
Пример #12
0
        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);
        }
Пример #13
0
        /*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);
        }
Пример #14
0
        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));
        }
Пример #15
0
        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);
        }
Пример #16
0
 public override void CalculateOffer(PriceCalculationParameters calculationParameters,
                                     OfferPriceCalculation priceCalculator, string conversionMethod)
 {
     _ = priceCalculator.CalculatePrice(this, calculationParameters).Result;
     CalculateInstallmentPlan(conversionMethod);
 }
Пример #17
0
        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();
                }
            }
Пример #18
0
        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);
        }
Пример #19
0
 public virtual void CalculateOffer(PriceCalculationParameters calculationParameters, OfferPriceCalculation priceCalculator, string conversionMethod)
 {
     // To be implemented for each arrangement request subtype
 }
Пример #20
0
        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);
        }
Пример #21
0
        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);
        }