public void RateInInterestRateNull()
        {
            ConfigurationServiceMock       configurationService = new ConfigurationServiceMock();
            PriceCalculationDMNServiceMock priceCalCService     = new PriceCalculationDMNServiceMock(configurationService);
            MarketRatesServiceMock         marketRatesService   = new MarketRatesServiceMock();
            var OfferPriceCalculation     = new OfferPriceCalculation(priceCalCService, marketRatesService, configurationService, null);
            InterestRateCondition intRate = new InterestRateCondition
            {
                Kind       = InterestRateKinds.RegularInterest,
                Rate       = null,
                Title      = "regular-interest",
                Currencies = new List <string> {
                    "RSD"
                }
            };

            ProductConditions conditions = new ProductConditions
            {
                InterestRates = new List <InterestRateCondition> {
                    intRate
                }
            };
            Application application                = Utility.GetApplication(conditions);
            var         arrangementRequest         = application.ArrangementRequests[0] as TermLoanRequest;
            var         priceCalculationConditions = Utility.GetPriceCalculationParameterFromTermLoanRequest(arrangementRequest);


            var result = OfferPriceCalculation.CalculatePrice(application, arrangementRequest);

            Assert.Equal("RanToCompletion", result.Status.ToString());
            Assert.Single(result.Result.Conditions.InterestRates);
        }
Example #2
0
        public static TermLoanRequest GetArangementRequest(ProductConditions conditions)
        {
            var currency = "RSD";

            if (conditions.InterestRates != null && conditions.InterestRates.Count > 0)
            {
                currency = conditions.InterestRates[0].Currencies[0];
            }
            if (conditions.Fees != null && conditions.Fees.Count > 0)
            {
                currency = conditions.Fees[0].Currencies[0];
            }
            return(new TermLoanRequest()
            {
                Amount = 50000,
                Napr = 10,
                Term = "P30M",
                Annuity = 325,
                Currency = currency,
                DownpaymentAmount = 10000,
                CalculationDate = DateTime.Today,
                ProductSnapshot = new ProductSnapshot
                {
                    Conditions = conditions
                }
            });
        }
        public void InterestRateListNullInConditions()
        {
            ConfigurationServiceMock       configurationService = new ConfigurationServiceMock();
            PriceCalculationDMNServiceMock priceCalCService     = new PriceCalculationDMNServiceMock(configurationService);
            MarketRatesServiceMock         marketRatesService   = new MarketRatesServiceMock();
            var OfferPriceCalculation = new OfferPriceCalculation(priceCalCService, marketRatesService, configurationService, null);

            ProductConditions conditions = new ProductConditions
            {
                Fees          = new List <FeeCondition> {
                },
                InterestRates = new List <InterestRateCondition> {
                    null
                }
            };
            Application application                = Utility.GetApplication(conditions);
            var         arrangementRequest         = application.ArrangementRequests[0] as TermLoanRequest;
            var         priceCalculationConditions = Utility.GetPriceCalculationParameterFromTermLoanRequest(arrangementRequest);


            var result = OfferPriceCalculation.CalculatePrice(application, arrangementRequest);

            Assert.Equal("RanToCompletion", result.Status.ToString());
            Assert.Empty(result.Result.Conditions.Fees);
        }
Example #4
0
        public ActionResult Index(ProductConditions condition)
        {
            return(RedirectToAction("Index", "Template1"));

            // Check Cost

            // Product type
            condition.ListProductType = productService.ListProductType();

            // List Limited
            List <SelectListItem> listLimit = new List <SelectListItem>();

            listLimit.Add(new SelectListItem()
            {
                Text = "20", Value = "20"
            });
            listLimit.Add(new SelectListItem()
            {
                Text = "30", Value = "30", Selected = true
            });
            listLimit.Add(new SelectListItem()
            {
                Text = "40", Value = "40"
            });
            listLimit.Add(new SelectListItem()
            {
                Text = "50", Value = "50"
            });
            condition.ListLimit = listLimit;

            return(View(condition));
        }
Example #5
0
        /// <summary>
        /// Hiển thị danh sách sản phẩm dưới dạng Grid
        /// </summary>
        /// <returns></returns>
        public ActionResult BoxProductGrid(ProductConditions condition)
        {
            // Get List City
            condition.ListCity = placeService.List(0);

            // Get List District
            if (condition.CityId > 0)
            {
                condition.ListDistrict = placeService.List(condition.CityId);
            }
            else
            {
                condition.DistrictId = 0;
                //condition.ListDistrict = placeService.List(1);
            }


            // Get List Ward
            if (condition.DistrictId > 0)
            {
                condition.ListWard = placeService.List(condition.DistrictId);
            }
            else
            {
                condition.WardId = 0;
                //condition.ListWard = placeService.List(condition.ListDistrict[0].Id);
            }
            condition.ListCity.Insert(0, new Entities.Place()
            {
                Text = "Chọn tỉnh/thành phố", Id = 0
            });
            condition.ListDistrict.Insert(0, new Entities.Place()
            {
                Text = "Chọn quận/huyện", Id = 0
            });
            condition.ListWard.Insert(0, new Entities.Place()
            {
                Text = "Chọn xã/phường", Id = 0
            });


            Entities.ProductCondtions e = new Entities.ProductCondtions();
            condition.MapFrom(condition, ref e);


            var lstTemp     = productService.List(e);
            int totalRecord = 0;

            if (lstTemp.Count > 0)
            {
                totalRecord = lstTemp[0].Total.Value;
                Paging(condition.Page, totalRecord, condition.Limit);
            }

            ViewBag.ListProduct = lstTemp;
            return(PartialView("BoxProductGrid", condition));
        }
Example #6
0
        public void IterativeBaseRateInInterestRateNull()
        {
            var OfferPriceCalculation = new OfferPriceCalculation(priceCalCService, marketRatesService, configurationService, null);
            InterestRateCondition regularInterestEuribor = new InterestRateCondition
            {
                //market-rates api ima bazne vrednosti za interest rates - odavde uzeti primere
                //Regular interest moze da bude definisan posebno za svaku valutu
                Kind = InterestRateKinds.RegularInterest,
                Rate = new InterestRate
                {
                    BaseRateId      = null,
                    SpreadRateValue = 10
                },
                EffectiveDate = DateTime.Now.AddDays(-1),
                Title         = "regular-interest",
                Currencies    = new List <string> {
                    "RSD"
                }
            };

            ProductConditions conditions = new ProductConditions
            {
                InterestRates = new List <InterestRateCondition> {
                    regularInterestEuribor
                }
            };
            var arrangementRequest = Utility.GetArangementRequest(conditions);

            Application application = new Application
            {
                //U DMN-u pogledati podatke kje uticu na skor iz configa
                //Ovo ce promeniti broj Percentage za fee i za interest-rate
                ArrangementNumber = "1",
                CustomerName      = "Tester",
                StatusInformation = new StatusInformation
                {
                    Description = "Works as a tester"
                },
                CustomerSegment = "student",
                CollateralModel = "two-co-debtors",

                RiskScore   = 55,
                ChannelCode = "web",
                RequestDate = DateTime.Now
            };

            var result = OfferPriceCalculation.CalculatePrice(application, arrangementRequest);

            Assert.Equal("RanToCompletion", result.Status.ToString());
            Assert.Single(result.Result.Conditions.InterestRates);
            var interestRate = result.Result.Conditions.InterestRates[0];

            Assert.Null(interestRate.Rate.BaseRateId);
            Assert.Equal(0, interestRate.Rate.BaseRateValue);
            Assert.Equal((decimal)10.0, interestRate.Rate.SpreadRateValue);
        }
        //Percentage and FixedAmount have two variations that sets them over upper limit and calculated should be equal to upper limit
        public void CalculatedOverUpperLimitMultipleVariations()
        {
            ConfigurationServiceMock       configurationService = new ConfigurationServiceMock();
            PriceCalculationDMNServiceMock priceCalCService     = new PriceCalculationDMNServiceMock(configurationService);
            MarketRatesServiceMock         marketRatesService   = new MarketRatesServiceMock();
            var          OfferPriceCalculation = new OfferPriceCalculation(priceCalCService, marketRatesService, configurationService, null);
            FeeCondition regularFee            = new FeeCondition
            {
                Percentage  = (decimal)0.1,
                FixedAmount = new Currency {
                    Amount = 20, Code = "EUR"
                },
                LowerLimit = new Currency {
                    Amount = 20, Code = "EUR"
                },
                UpperLimit = new Currency {
                    Amount = 200, Code = "EUR"
                },
                VariationsDefinitionDMN = "product/price-variations/multiple-fee-var-over-range.dmn",
                PercentageLowerLimit    = (decimal)0.05,
                PercentageUpperLimit    = 1,
                Title         = "Origination-fee1",
                EffectiveDate = DateTime.Now.AddDays(-1),
                Currencies    = new List <string> {
                    "RSD", "EUR"
                }
            };

            ProductConditions conditions = new ProductConditions
            {
                Fees = new List <FeeCondition> {
                    regularFee
                },
                InterestRates = new List <InterestRateCondition> {
                }
            };
            Application application                = Utility.GetApplication(conditions);
            var         arrangementRequest         = application.ArrangementRequests[0] as TermLoanRequest;
            var         priceCalculationConditions = Utility.GetPriceCalculationParameterFromTermLoanRequest(arrangementRequest);


            var result     = OfferPriceCalculation.CalculatePrice(application, arrangementRequest);
            var resultFees = result.Result.Conditions.Fees[0];
            var variation  = result.Result.Conditions.Fees[0].Variations;

            Assert.Equal("2", variation.Count.ToString());

            var variationOne = variation[0];
            var variationTwo = variation[1];

            Assert.Equal("RanToCompletion", result.Status.ToString());
            Assert.Equal(1, resultFees.CalculatedPercentage);
            Assert.Equal((decimal)0.4, variationOne.Percentage);
            Assert.Equal((decimal)0.6, variationTwo.Percentage);
            Assert.Equal("product/price-variations/multiple-fee-var-over-range.dmn", resultFees.VariationsDefinitionDMN);
        }
 public InitiateCalculateOfferCommand(ArrangementKind arrangementKind, string currency, decimal amount, decimal annuity,
                                      string term, decimal interestRate, decimal downpaymentAmount, decimal invoiceAmount, decimal minimalDownpaymentPercentage,
                                      string channel, decimal?riskScore, string creditRating, decimal?customerValue, decimal?debtToIncome, string customerSegment,
                                      string partOfBundle, string collateralModel, ProductConditions productConditions, Conditions conditions, LeadModel campaign,
                                      List <ProductOption> productOptions, Dictionary <string, JToken> bundledComponents, decimal downpaymentPercentage,
                                      List <ScheduledPeriod> scheduledPeriods, DateTime?calculationDate, DateTime?requestDate, DateTime?approvalDate,
                                      DateTime?signingDate, DateTime?disbursmentDate, DateTime?firstInstallmentDate, DateTime?maturityDate,
                                      string gracePeriod, DateTime?gracePeriodStartDate, string drawdownPeriod, DateTime?drawdownPeriodStartDate,
                                      RepaymentType?repaymentType, int numberOfInstallments, int minimumDaysForFirstInstallment, bool adjustFirstInstallment, bool payFeeFromDisbursement,
                                      SimpleSchedule installmentSchedule, IntercalarInterestRepaymentType intercalarInterestRepaymentType)
 {
     ArrangementKind                 = arrangementKind;
     Currency                        = currency;
     Amount                          = amount;
     Annuity                         = annuity;
     Term                            = term;
     InterestRate                    = interestRate;
     DownpaymentAmount               = downpaymentAmount;
     InvoiceAmount                   = invoiceAmount;
     MinimalDownpaymentPercentage    = minimalDownpaymentPercentage;
     Channel                         = channel;
     RiskScore                       = riskScore;
     CreditRating                    = creditRating;
     CustomerValue                   = customerValue;
     DebtToIncome                    = debtToIncome;
     CustomerSegment                 = customerSegment;
     PartOfBundle                    = partOfBundle;
     CollateralModel                 = collateralModel;
     ProductConditions               = productConditions;
     Conditions                      = conditions;
     Campaign                        = campaign;
     ProductOptions                  = productOptions;
     BundledComponents               = bundledComponents;
     DownpaymentPercentage           = downpaymentPercentage;
     ScheduledPeriods                = scheduledPeriods;
     CalculationDate                 = calculationDate ?? DateTime.Now;
     RequestDate                     = requestDate ?? DateTime.Now;
     ApprovalDate                    = approvalDate;
     SigningDate                     = signingDate;
     DisbursmentDate                 = disbursmentDate;
     FirstInstallmentDate            = firstInstallmentDate;
     MaturityDate                    = maturityDate;
     GracePeriod                     = gracePeriod;
     GracePeriodStartDate            = gracePeriodStartDate;
     DrawdownPeriod                  = drawdownPeriod;
     DrawdownPeriodStartDate         = drawdownPeriodStartDate;
     RepaymentType                   = repaymentType ?? Domain.Calculations.InstallmentPlanCalculation.RepaymentType.FixedAnnuity;
     NumberOfInstallments            = numberOfInstallments;
     MinimumDaysForFirstInstallment  = minimumDaysForFirstInstallment;
     AdjustFirstInstallment          = adjustFirstInstallment;
     PayFeeFromDisbursement          = payFeeFromDisbursement;
     InstallmentSchedule             = installmentSchedule;
     IntercalarInterestRepaymentType = intercalarInterestRepaymentType;
 }
Example #9
0
 public ActionResult BoxProduct(ProductConditions condition)
 {
     if (condition.displayType == "Grid")
     {
         return(BoxProductGrid(condition));
     }
     else
     {
         return(BoxProductList(condition));
     }
 }
        public void BaseRateInInterestRateNull()
        {
            ConfigurationServiceMock       configurationService = new ConfigurationServiceMock();
            PriceCalculationDMNServiceMock priceCalCService     = new PriceCalculationDMNServiceMock(configurationService);
            MarketRatesServiceMock         marketRatesService   = new MarketRatesServiceMock();
            var OfferPriceCalculation = new OfferPriceCalculation(priceCalCService, marketRatesService, configurationService, null);
            InterestRateCondition regularInterestEuribor = new InterestRateCondition
            {
                //market-rates api ima bazne vrednosti za interest rates - odavde uzeti primere
                //Regular interest moze da bude definisan posebno za svaku valutu
                Kind = InterestRateKinds.RegularInterest,
                Rate = new InterestRate
                {
                    BaseRateId      = null,
                    SpreadRateValue = 10
                },
                EffectiveDate = DateTime.Now.AddDays(-1),
                Title         = "regular-interest",
                Currencies    = new List <string> {
                    "RSD"
                }
            };

            ProductConditions conditions = new ProductConditions
            {
                InterestRates = new List <InterestRateCondition> {
                    regularInterestEuribor
                }
            };
            Application application                = Utility.GetApplication(conditions);
            var         arrangementRequest         = application.ArrangementRequests[0] as TermLoanRequest;
            var         priceCalculationConditions = Utility.GetPriceCalculationParameterFromTermLoanRequest(arrangementRequest);


            var result = OfferPriceCalculation.CalculatePrice(application, arrangementRequest);

            Assert.Equal("RanToCompletion", result.Status.ToString());
            Assert.Single(result.Result.Conditions.InterestRates);
            var interestRate = result.Result.Conditions.InterestRates[0];

            Assert.Null(interestRate.Rate.BaseRateId);
            Assert.Equal(0, interestRate.Rate.BaseRateValue);
            Assert.Equal((decimal)10.0, interestRate.Rate.SpreadRateValue);
        }
Example #11
0
        public void IterativeRateInInterestRateNull()
        {
            var OfferPriceCalculation     = new OfferPriceCalculation(priceCalCService, marketRatesService, configurationService, null);
            InterestRateCondition intRate = new InterestRateCondition
            {
                Kind       = InterestRateKinds.RegularInterest,
                Rate       = null,
                Title      = "regular-interest",
                Currencies = new List <string> {
                    "RSD"
                }
            };

            ProductConditions conditions = new ProductConditions
            {
                InterestRates = new List <InterestRateCondition> {
                    intRate
                }
            };
            var arrangementRequest = Utility.GetArangementRequest(conditions);

            Application application = new Application
            {
                //U DMN-u pogledati podatke kje uticu na skor iz configa
                //Ovo ce promeniti broj Percentage za fee i za interest-rate
                ArrangementNumber = "1",
                CustomerName      = "Tester",
                StatusInformation = new StatusInformation
                {
                    Description = "Works as a tester"
                },
                CustomerSegment = "student",
                CollateralModel = "two-co-debtors",

                RiskScore   = 55,
                ChannelCode = "web",
                RequestDate = DateTime.Now
            };

            var result = OfferPriceCalculation.CalculatePrice(application, arrangementRequest);

            Assert.Equal("RanToCompletion", result.Status.ToString());
            Assert.Single(result.Result.Conditions.InterestRates);
        }
Example #12
0
        public static Application GetApplication(ProductConditions conditions)
        {
            return(new  Application
            {
                ArrangementNumber = "1",
                CustomerName = "Tester",
                StatusInformation = new StatusInformation
                {
                    Description = "Works as a tester"
                },
                CustomerSegment = "student",
                CollateralModel = "two-co-debtors",

                RiskScore = 55,
                ChannelCode = "web",
                RequestDate = DateTime.Now,
                ArrangementRequests = new List <ArrangementRequest>
                {
                    GetArangementRequest(conditions)
                }
            });
        }
Example #13
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);
        }
Example #14
0
        public async Task <ProductConditions> ReadVariationDefinitions(ProductConditions conditions)
        {
            if (conditions == null)
            {
                return(null);
            }
            if (conditions.InterestRates != null)
            {
                foreach (InterestRateCondition rate in conditions.InterestRates)
                {
                    if (rate.VariationsDefinition != null)
                    {
                        rate.VariationsDefinitionDMN = await configurationService.GetEffective(rate.VariationsDefinition);
                    }
                    if (rate.UpperLimitVariationsDefinition != null)
                    {
                        rate.UpperLimitVariationsDefinitionDMN = await configurationService.GetEffective(rate.UpperLimitVariationsDefinition);
                    }
                    if (rate.LowerLimitVariationsDefinition != null)
                    {
                        rate.LowerLimitVariationsDefinitionDMN = await configurationService.GetEffective(rate.LowerLimitVariationsDefinition);
                    }
                }
            }
            if (conditions.Fees != null)
            {
                foreach (FeeCondition fee in conditions.Fees)
                {
                    if (fee.VariationsDefinition != null)
                    {
                        fee.VariationsDefinitionDMN = await configurationService.GetEffective(fee.VariationsDefinition);
                    }
                }
            }

            return(conditions.Copy());
        }
Example #15
0
        //No variations, calc rates should be as they are set in the request
        //Rate is within limits
        public void NoVariationsBelowLimitWithoutMarketRate()
        {
            ConfigurationServiceMock       configurationService = new ConfigurationServiceMock();
            PriceCalculationDMNServiceMock priceCalCService     = new PriceCalculationDMNServiceMock(configurationService);
            MarketRatesServiceMock         marketRatesService   = new MarketRatesServiceMock();
            var OfferPriceCalculation = new OfferPriceCalculation(priceCalCService, marketRatesService, configurationService, null);
            InterestRateCondition regularInterestEuribor = new InterestRateCondition
            {
                //This base rate id removes -1.5 from spreadRateValue, making rate under limit
                Kind = InterestRateKinds.RegularInterest,
                Rate = new InterestRate
                {
                    BaseRateId      = "EURIBOR-6M",
                    SpreadRateValue = (decimal)9.9
                },
                UpperLimit = new InterestRate
                {
                    BaseRateId      = "EURIBOR-6M",
                    SpreadRateValue = 18
                },
                LowerLimit = new InterestRate
                {
                    BaseRateId      = "EURIBOR-6M",
                    SpreadRateValue = 10
                },
                Title      = "regular-interest",
                Currencies = new List <string> {
                    "EUR"
                }
            };

            ProductConditions conditions = new ProductConditions
            {
                Fees          = new List <FeeCondition> {
                },
                InterestRates = new List <InterestRateCondition> {
                    regularInterestEuribor
                }
            };
            Application application                = Utility.GetApplication(conditions);
            var         arrangementRequest         = application.ArrangementRequests[0] as TermLoanRequest;
            var         priceCalculationConditions = Utility.GetPriceCalculationParameterFromTermLoanRequest(arrangementRequest);

            var variationsDefinition = Utility.GetVariationDefinitionParamsFromApplication(application);
            var result         = OfferPriceCalculation.CalculatePrice(application, arrangementRequest);
            var resultInterest = result.Result.Conditions.InterestRates[0];

            //Basic assertions
            Assert.Equal("RanToCompletion", result.Status.ToString());
            Assert.Equal("0", resultInterest.Variations.Count.ToString());

            //Asserting input parameters
            Assert.Equal("EURIBOR-6M", resultInterest.Rate.BaseRateId);
            Assert.Equal(0, resultInterest.Rate.BaseRateValue);
            Assert.Equal((decimal)9.9, resultInterest.Rate.SpreadRateValue);

            Assert.Equal("EURIBOR-6M", resultInterest.UpperLimit.BaseRateId);
            Assert.Equal(0, resultInterest.UpperLimit.BaseRateValue);
            Assert.Equal((decimal)18.0, resultInterest.UpperLimit.SpreadRateValue);

            Assert.Equal("EURIBOR-6M", resultInterest.LowerLimit.BaseRateId);
            Assert.Equal(0, resultInterest.LowerLimit.BaseRateValue);
            Assert.Equal((decimal)10.0, resultInterest.LowerLimit.SpreadRateValue);

            //Asserting Napr and calculation results
            Assert.Equal((decimal)10.0, ((TermLoanRequest)result.Result).Napr);
            Assert.Equal((decimal)10.0, resultInterest.CalculatedRate);
            Assert.Equal((decimal)10.0, resultInterest.CalculatedLowerLimit);
            Assert.Equal((decimal)18.0, resultInterest.CalculatedUpperLimit);
        }
        //Percentage and FixedAmount have a variation that sets them to near lower limit but still above
        public void CalculatedNearLowerLimit()
        {
            ConfigurationServiceMock       configurationService = new ConfigurationServiceMock();
            PriceCalculationDMNServiceMock priceCalCService     = new PriceCalculationDMNServiceMock(configurationService);
            MarketRatesServiceMock         marketRatesService   = new MarketRatesServiceMock();
            var          OfferPriceCalculation = new OfferPriceCalculation(priceCalCService, marketRatesService, configurationService, null);
            FeeCondition regularFee            = new FeeCondition
            {
                //Samo % se testira za sada jer trenutno nema za fixedAmount
                //Samo varijacije uticu na PercentageKind = FeeConditionKinds.OriginationFee,
                Percentage  = (decimal)0.1,
                FixedAmount = new Currency {
                    Amount = 200, Code = "EUR"
                },
                LowerLimit = new Currency {
                    Amount = 20, Code = "EUR"
                },
                UpperLimit = new Currency {
                    Amount = 200, Code = "EUR"
                },
                VariationsDefinitionDMN = "product/price-variations/fee-in-range-lower.dmn",
                PercentageLowerLimit    = (decimal)0.01,
                PercentageUpperLimit    = 1,
                Title         = "Origination-fee1",
                EffectiveDate = DateTime.Now.AddDays(-1),
                Currencies    = new List <string> {
                    "RSD", "EUR"
                }
            };

            ProductConditions conditions = new ProductConditions
            {
                Fees = new List <FeeCondition> {
                    regularFee
                },
                InterestRates = new List <InterestRateCondition> {
                }
            };

            Application application                = Utility.GetApplication(conditions);
            var         arrangementRequest         = application.ArrangementRequests[0] as TermLoanRequest;
            var         priceCalculationConditions = Utility.GetPriceCalculationParameterFromTermLoanRequest(arrangementRequest);


            var result = OfferPriceCalculation.CalculatePrice(application, arrangementRequest);

            //Basic assertions
            Assert.Equal("RanToCompletion", result.Status.ToString());

            Assert.Single(result.Result.Conditions.Fees);
            var resultFees = result.Result.Conditions.Fees[0];

            Assert.Single(resultFees.Variations);
            var variation = resultFees.Variations[0];


            //Asserting input
            Assert.Equal(200, resultFees.FixedAmount.Amount);
            Assert.Equal((decimal)0.1, resultFees.Percentage);

            //Asserting output
            Assert.Equal("product/price-variations/fee-in-range-lower.dmn", resultFees.VariationsDefinitionDMN);
            Assert.Equal((decimal)0.02, resultFees.CalculatedPercentage);
            Assert.Equal((decimal) - 0.08, variation.Percentage);
            Assert.Equal(21, resultFees.CalculatedFixedAmount);
            Assert.Equal(-179, variation.FixedAmount);
        }
Example #17
0
        //Arrangement Request is set to EUR
        //There are no defined variations - Application data does not matter
        //There are two fees, both accounted because they're in the same currency
        public void IterativeTwoInterestRatesDiferentKind()
        {
            var          OfferPriceCalculation = new OfferPriceCalculation(priceCalCService, marketRatesService, configurationService, null);
            FeeCondition regularFee            = new FeeCondition
            {
                //Samo % se testira za sada jer trenutno nema za fixedAmount
                //Samo varijacije uticu na Percentage
                Kind        = FeeConditionKinds.OriginationFee,
                Percentage  = (decimal)0.2,
                FixedAmount = new Currency {
                    Amount = 200, Code = "EUR"
                },
                LowerLimit = new Currency {
                    Amount = 200, Code = "EUR"
                },
                UpperLimit = new Currency {
                    Amount = 4000, Code = "EUR"
                },
                PercentageLowerLimit = (decimal)0.01,
                PercentageUpperLimit = 1,
                Title         = "Origination-fee1",
                EffectiveDate = DateTime.Now.AddDays(-1),
                Currencies    = new List <string> {
                    "RSD", "EUR"
                }
            };

            InterestRateCondition regularInterestEuribor = new InterestRateCondition
            {
                Kind = InterestRateKinds.RegularInterest,
                Rate = new InterestRate
                {
                    BaseRateId      = "EURIBOR-3M",
                    SpreadRateValue = 10
                },
                Title      = "regular-interest",
                Currencies = new List <string> {
                    "EUR"
                }
            };

            InterestRateCondition earlyWithdrawalInterest = new InterestRateCondition
            {
                Kind = InterestRateKinds.EarlyWithdrawalInterest,
                Rate = new InterestRate
                {
                    BaseRateId      = "EARLY-EUR",
                    SpreadRateValue = 2
                },
                Title      = "early-withdrawal-interest",
                Currencies = new List <string> {
                    "EUR"
                }
            };

            ProductConditions conditions = new ProductConditions
            {
                Fees = new List <FeeCondition> {
                    regularFee
                },
                InterestRates = new List <InterestRateCondition> {
                    regularInterestEuribor, earlyWithdrawalInterest
                }
            };
            var arrangementRequest = Utility.GetArangementRequest(conditions);

            Application application = new Application
            {
                ArrangementNumber = "1",
                CustomerName      = "Tester",
                StatusInformation = new StatusInformation
                {
                    Description = "Works as a tester"
                },
                CustomerSegment = "student",
                CollateralModel = "two-co-debtors",

                RiskScore   = 55,
                ChannelCode = "web",
                RequestDate = DateTime.Now
            };

            var result = OfferPriceCalculation.CalculatePrice(application, arrangementRequest);

            Assert.Single(result.Result.Conditions.Fees);
            Assert.Equal("RanToCompletion", result.Status.ToString());

            var resultInterest = result.Result.Conditions.InterestRates[0];
            var resultEarlyWithdrawalInterest = result.Result.Conditions.InterestRates[1];

            Assert.Equal("EURIBOR-3M", resultInterest.Rate.BaseRateId);
            Assert.Equal((decimal)8.5, resultInterest.CalculatedRate);
            Assert.Equal((decimal) - 1.5, resultInterest.Rate.BaseRateValue);
            Assert.Equal((decimal)10.0, resultInterest.Rate.SpreadRateValue);
            //C# won't let this be asserted in any other way
            Assert.Equal("0", resultInterest.Variations.Count.ToString());

            Assert.Equal("EARLY-EUR", resultEarlyWithdrawalInterest.Rate.BaseRateId);
            Assert.Equal((decimal)3.5, resultEarlyWithdrawalInterest.CalculatedRate);
            Assert.Equal((decimal)1.5, resultEarlyWithdrawalInterest.Rate.BaseRateValue);
            Assert.Equal((decimal)2.0, resultEarlyWithdrawalInterest.Rate.SpreadRateValue);

            Assert.Equal(0, resultInterest.CalculatedLowerLimit);
            Assert.Equal(100, resultInterest.CalculatedUpperLimit);
        }
        public async Task <ArrangementRequest> Handle(InitiateCalculateOfferCommand message, CancellationToken cancellationToken)
        {
            ProductConditions conditions = await _priceCalculation.ReadVariationDefinitions(message.ProductConditions);

            var parameters = Mapper.Map <InitiateCalculateOfferCommand, ArrangementRequestInitializationParameters>(message);

            try
            {
                parameters.MaturityDate = Utility.GetEndDateFromPeriod(parameters.Term, message.CalculationDate);
            }
            catch (InvalidTermException)
            {
                // do nothing
            }
            ArrangementRequest result = _requestFactory.GetForArrangementKind(parameters, message.ArrangementKind);

            if (parameters.MaturityDate.HasValue && result.IsFinanceService())
            {
                FinanceServiceArrangementRequest fsr = result as FinanceServiceArrangementRequest;
                fsr.MaturityDate = parameters.MaturityDate.Value;
            }

            result.ParentProductCode = message.PartOfBundle;
            result.Campaign          = message.Campaign;
            result.Options           = message.ProductOptions;
            if (result is FinanceServiceArrangementRequest finRequest)
            {
                finRequest.CollateralModel = message.CollateralModel;
            }
            Dictionary <string, OptionGroup> productShapsotOptions = new Dictionary <string, OptionGroup>();

            if (message.ProductOptions != null)
            {
                foreach (var option in message.ProductOptions)
                {
                    if (productShapsotOptions.TryGetValue(option.GroupCode, out OptionGroup optionGroup))
                    {
                        optionGroup.Options.Add(new Option
                        {
                            Code        = option.Code,
                            Description = option.Description,
                            Effects     = option.Effects
                        });
                    }
                    else
                    {
                        productShapsotOptions.Add(option.GroupCode, new OptionGroup
                        {
                            Code        = option.GroupCode,
                            Description = option.GroupDescription,
                            Options     = new List <Option>
                            {
                                new Option
                                {
                                    Code        = option.Code,
                                    Description = option.Description,
                                    Effects     = option.Effects
                                }
                            }
                        });
                    }
                }
            }
            result.ProductSnapshot = new ProductSnapshot
            {
                Conditions   = conditions,
                Campaign     = message.Campaign,
                OptionGroups = productShapsotOptions.Values.ToList(),
                MinimumDaysForFirstInstallment = message.MinimumDaysForFirstInstallment
            };

            OfferApplication application = new OfferApplication
            {
                CustomerSegment = message.CustomerSegment,
                CollateralModel = message.CollateralModel,
                RiskScore       = message.RiskScore ?? null,
                ChannelCode     = message.Channel,
                DebtToIncome    = message.DebtToIncome,
                CustomerValue   = message.CustomerValue,
                CreditRating    = message.CreditRating,
                RequestDate     = message.RequestDate
            };

            try
            {
                _logger.LogInformation("Calculating offer for term: {term}, annuity: {annutiy} and amount {amount} and interest rate: {rate}", message.Term, message.Annuity, message.Amount, message.InterestRate);

                result = _calculatorProvider.Calculate(result, application, message.BundledComponents);
                RemoveDmnFields(result);

                try
                {
                    await _auditClient.WriteLogEntry(AuditLogEntryAction.Execute, AuditLogEntryStatus.Success, "application", application.ApplicationNumber, "Calculating offer for term: " + message.Term + ", annuity: " + message.Annuity + " and amount " + message.Amount, new { });
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Audit error in UpdateApplicationStatusCommandHandler");
                }

                return(result);
            }
            catch (MaxNumberOfIterationsException e)
            {
                _logger.LogInformation("Error in calculation: {calcErr}. Command data: {command}", e.Message, message);
                throw e;
            }
            catch (Exception exp)
            {
                _logger.LogError(exp, "Exception while calculating offer for data, term: {term}, annuity: {annutiy} and amount {amount} and interest rate: {rate}", message.Term, message.Annuity, message.Amount, message.InterestRate);
                throw new NotImplementedException(exp.Message);
            }
        }
Example #19
0
        public void IterativeMultipleOriginationFeesBothCalculated()
        {
            var          OfferPriceCalculation = new OfferPriceCalculation(priceCalCService, marketRatesService, configurationService, null);
            FeeCondition regularFee            = new FeeCondition
            {
                Kind               = FeeConditionKinds.OriginationFee,
                ServiceCode        = "",
                ServiceDescription = "",
                Percentage         = (decimal)0.2,
                FixedAmount        = new Currency {
                    Amount = 200, Code = "RSD"
                },
                LowerLimit = new Currency {
                    Amount = 200, Code = "RSD"
                },
                UpperLimit = new Currency {
                    Amount = 4000, Code = "RSD"
                },
                PercentageLowerLimit = (decimal)0.01,
                PercentageUpperLimit = 1,
                Title         = "Origination-fee1",
                EffectiveDate = DateTime.Now.AddDays(-1),
                Currencies    = new List <string> {
                    "RSD", "EUR"
                }
            };

            FeeCondition regularFee2 = new FeeCondition
            {
                Kind               = FeeConditionKinds.OriginationFee,
                ServiceCode        = "",
                ServiceDescription = "",
                Percentage         = (decimal)0.3,
                FixedAmount        = new Currency {
                    Amount = 300, Code = "RSD"
                },
                LowerLimit = new Currency {
                    Amount = 200, Code = "RSD"
                },
                UpperLimit = new Currency {
                    Amount = 4000, Code = "RSD"
                },
                PercentageLowerLimit = (decimal)0.01,
                PercentageUpperLimit = 1,
                Title         = "Origination-fee2",
                EffectiveDate = DateTime.Now.AddDays(-1),
                Currencies    = new List <string> {
                    "RSD", "EUR"
                }
            };

            ProductConditions conditions = new ProductConditions
            {
                Fees = new List <FeeCondition> {
                    regularFee
                },
                InterestRates = new List <InterestRateCondition> {
                }
            };
            var arrangementRequest = Utility.GetArangementRequest(conditions);

            Application application = new Application
            {
                ArrangementNumber = "1",
                CustomerName      = "Tester",
                StatusInformation = new StatusInformation
                {
                    Description = "Works as a tester"
                },
                CustomerSegment = "student",
                CollateralModel = "two-co-debtors",

                RiskScore   = 55,
                ChannelCode = "web",
                RequestDate = DateTime.Now
            };

            var result = OfferPriceCalculation.CalculatePrice(application, arrangementRequest);

            Assert.Equal("RanToCompletion", result.Status.ToString());
            var resultFees = result.Result.Conditions.Fees;

            //Assert.Equal("2", resultFees.Count.ToString());
            Assert.Equal("1", resultFees.Count.ToString());
            var resultFeeOne = resultFees[0];

            Assert.Empty(resultFeeOne.Variations);
            Assert.Equal((decimal)0.2, resultFeeOne.CalculatedPercentage);
            Assert.Equal(200, resultFeeOne.CalculatedFixedAmount);
            Assert.Null(resultFeeOne.VariationsDefinitionDMN);

            //var resultFeeTwo = resultFees[1];
            //Assert.Empty(resultFeeTwo.Variations);
            //Assert.Equal((decimal)0.3, resultFeeTwo.CalculatedPercentage);
            //Assert.Equal(300, resultFeeTwo.CalculatedFixedAmount);
            //Assert.Null(resultFeeTwo.VariationsDefinitionDMN);
        }
Example #20
0
 public Task <ProductConditions> ReadVariationDefinitions(ProductConditions condition)
 {
     throw new NotImplementedException();
 }
        public void MultipleOriginationFeesBothCalculated()
        {
            ConfigurationServiceMock       configurationService = new ConfigurationServiceMock();
            PriceCalculationDMNServiceMock priceCalCService     = new PriceCalculationDMNServiceMock(configurationService);
            MarketRatesServiceMock         marketRatesService   = new MarketRatesServiceMock();
            var          OfferPriceCalculation = new OfferPriceCalculation(priceCalCService, marketRatesService, configurationService, null);
            FeeCondition regularFee            = new FeeCondition
            {
                Kind               = FeeConditionKinds.OriginationFee,
                ServiceCode        = "",
                ServiceDescription = "",
                Percentage         = (decimal)0.2,
                FixedAmount        = new Currency {
                    Amount = 200, Code = "RSD"
                },
                LowerLimit = new Currency {
                    Amount = 200, Code = "RSD"
                },
                UpperLimit = new Currency {
                    Amount = 4000, Code = "RSD"
                },
                PercentageLowerLimit = (decimal)0.01,
                PercentageUpperLimit = 1,
                Title         = "Origination-fee1",
                EffectiveDate = DateTime.Now.AddDays(-1),
                Currencies    = new List <string> {
                    "RSD", "EUR"
                }
            };

            FeeCondition regularFee2 = new FeeCondition
            {
                Kind               = FeeConditionKinds.OriginationFee,
                ServiceCode        = "",
                ServiceDescription = "",
                Percentage         = (decimal)0.3,
                FixedAmount        = new Currency {
                    Amount = 300, Code = "RSD"
                },
                LowerLimit = new Currency {
                    Amount = 200, Code = "RSD"
                },
                UpperLimit = new Currency {
                    Amount = 4000, Code = "RSD"
                },
                PercentageLowerLimit = (decimal)0.01,
                PercentageUpperLimit = 1,
                Title         = "Origination-fee2",
                EffectiveDate = DateTime.Now.AddDays(-1),
                Currencies    = new List <string> {
                    "RSD", "EUR"
                }
            };

            ProductConditions conditions = new ProductConditions
            {
                Fees = new List <FeeCondition> {
                    regularFee
                },
                InterestRates = new List <InterestRateCondition> {
                }
            };
            Application application                = Utility.GetApplication(conditions);
            var         arrangementRequest         = application.ArrangementRequests[0] as TermLoanRequest;
            var         priceCalculationConditions = Utility.GetPriceCalculationParameterFromTermLoanRequest(arrangementRequest);


            var result = OfferPriceCalculation.CalculatePrice(application, arrangementRequest);

            Assert.Equal("RanToCompletion", result.Status.ToString());
            var resultFees = result.Result.Conditions.Fees;

            Assert.Equal("2", resultFees.Count.ToString());
            var resultFeeOne = resultFees[0];

            Assert.Empty(resultFeeOne.Variations);
            Assert.Equal((decimal)0.2, resultFeeOne.CalculatedPercentage);
            Assert.Equal(200, resultFeeOne.CalculatedFixedAmount);
            Assert.Null(resultFeeOne.VariationsDefinitionDMN);

            var resultFeeTwo = resultFees[1];

            Assert.Empty(resultFeeTwo.Variations);
            Assert.Equal((decimal)0.3, resultFeeTwo.CalculatedPercentage);
            Assert.Equal(300, resultFeeTwo.CalculatedFixedAmount);
            Assert.Null(resultFeeTwo.VariationsDefinitionDMN);
        }
        public void TwoInterestRatesOneUsed()
        {
            ConfigurationServiceMock       configurationService = new ConfigurationServiceMock();
            PriceCalculationDMNServiceMock priceCalCService     = new PriceCalculationDMNServiceMock(configurationService);
            MarketRatesServiceMock         marketRatesService   = new MarketRatesServiceMock();
            var OfferPriceCalculation = new OfferPriceCalculation(priceCalCService, marketRatesService, configurationService, null);

            /*VariationsDefinition (fee.variationsDefinition) utice na fee.percentage (percentage + varijacije)
             * fixedAmount moze da seta u okviru definisanih granica (Upper/LowerLimitAmount ili percentage)
             */
            //moze da postoji samo jedan origination fee
            FeeCondition regularFee = new FeeCondition
            {
                Kind               = FeeConditionKinds.OriginationFee,
                ServiceCode        = "",
                ServiceDescription = "",
                Percentage         = (decimal)0.2,
                FixedAmount        = new Currency {
                    Amount = 200, Code = "RSD"
                },
                LowerLimit = new Currency {
                    Amount = 200, Code = "RSD"
                },
                UpperLimit = new Currency {
                    Amount = 4000, Code = "RSD"
                },
                PercentageLowerLimit = (decimal)0.01,
                PercentageUpperLimit = 1,
                Title         = "Origination-fee1",
                EffectiveDate = DateTime.Now.AddDays(-1),
                Currencies    = new List <string> {
                    "RSD", "EUR"
                }
            };
            //SpreadRateValue + BaseRateValue + SumaVarijacija = interestRate.CalculatedRate
            //Vazi za svaki interest rate
            //Samo jedan RegularInterest moze biti na proizvodu i napr je vezan samo za njegov CalculatedRate
            InterestRateCondition regularInterestEuribor = new InterestRateCondition
            {
                //market-rates api ima bazne vrednosti za interest rates - odavde uzeti primere
                //Regular interest moze da bude definisan posebno za svaku valutu
                Kind = InterestRateKinds.RegularInterest,
                Rate = new InterestRate
                {
                    BaseRateId      = "EURIBOR-3M",
                    SpreadRateValue = 10
                },
                Title      = "regular-interest",
                Currencies = new List <string> {
                    "EUR"
                }
            };

            InterestRateCondition regularInterestBelibor = new InterestRateCondition
            {
                //SpreadRateValue je fiksni deo kamatne stope
                //Base rate id definise prema cemu se gleda promenljivi deo (baseRateBalue) kamatne stope
                //Obuhvati da nema stopu
                //IsFixed
                Kind = InterestRateKinds.RegularInterest,
                Rate = new InterestRate
                {
                    BaseRateId      = "BELIBOR-3M",
                    SpreadRateValue = 12
                },
                Title      = "regular-interest",
                Currencies = new List <string> {
                    "RSD"
                }
            };

            ProductConditions conditions = new ProductConditions {
                Fees = new List <FeeCondition> {
                    regularFee
                },
                InterestRates = new List <InterestRateCondition> {
                    regularInterestEuribor, regularInterestBelibor
                }
            };
            Application application                = Utility.GetApplication(conditions);
            var         arrangementRequest         = application.ArrangementRequests[0] as TermLoanRequest;
            var         priceCalculationConditions = Utility.GetPriceCalculationParameterFromTermLoanRequest(arrangementRequest);


            var result         = OfferPriceCalculation.CalculatePrice(application, arrangementRequest);
            var resultFees     = result.Result.Conditions.Fees[0];
            var resultInterest = result.Result.Conditions.InterestRates[0];

            Assert.Equal("RanToCompletion", result.Status.ToString());
            Assert.Empty(resultFees.Variations);
            Assert.Equal((decimal)0.2, resultFees.CalculatedPercentage);
            Assert.Equal(200, resultFees.CalculatedFixedAmount);
            Assert.Null(resultFees.VariationsDefinitionDMN);

            Assert.Equal("BELIBOR-3M", resultInterest.Rate.BaseRateId);
            Assert.Equal((decimal)9.5, resultInterest.CalculatedRate);
            Assert.Equal((decimal) - 2.5, resultInterest.Rate.BaseRateValue);
            Assert.Equal((decimal)12.0, resultInterest.Rate.SpreadRateValue);
            //C# won't let this be asserted in any other way
            Assert.Equal("0", resultInterest.Variations.Count.ToString());

            Assert.Empty(resultInterest.Variations);
            Assert.Equal(0, resultInterest.CalculatedLowerLimit);
            Assert.Equal(100, resultInterest.CalculatedUpperLimit);
        }
        //Arrangement Request is set to EUR
        //There are no defined variations - Application data does not matter
        //There are two fees, both accounted because they're in the same currency
        public void TwoInterestRatesDiferentKind()
        {
            ConfigurationServiceMock       configurationService = new ConfigurationServiceMock();
            PriceCalculationDMNServiceMock priceCalCService     = new PriceCalculationDMNServiceMock(configurationService);
            MarketRatesServiceMock         marketRatesService   = new MarketRatesServiceMock();
            var          OfferPriceCalculation = new OfferPriceCalculation(priceCalCService, marketRatesService, configurationService, null);
            FeeCondition regularFee            = new FeeCondition
            {
                //Samo % se testira za sada jer trenutno nema za fixedAmount
                //Samo varijacije uticu na Percentage
                Kind        = FeeConditionKinds.OriginationFee,
                Percentage  = (decimal)0.2,
                FixedAmount = new Currency {
                    Amount = 200, Code = "EUR"
                },
                LowerLimit = new Currency {
                    Amount = 200, Code = "EUR"
                },
                UpperLimit = new Currency {
                    Amount = 4000, Code = "EUR"
                },
                PercentageLowerLimit = (decimal)0.01,
                PercentageUpperLimit = 1,
                Title         = "Origination-fee1",
                EffectiveDate = DateTime.Now.AddDays(-1),
                Currencies    = new List <string> {
                    "RSD", "EUR"
                }
            };

            InterestRateCondition regularInterestEuribor = new InterestRateCondition
            {
                Kind = InterestRateKinds.RegularInterest,
                Rate = new InterestRate
                {
                    BaseRateId      = "EURIBOR-3M",
                    SpreadRateValue = 10
                },
                Title      = "regular-interest",
                Currencies = new List <string> {
                    "EUR"
                }
            };

            InterestRateCondition earlyWithdrawalInterest = new InterestRateCondition
            {
                Kind = InterestRateKinds.EarlyWithdrawalInterest,
                Rate = new InterestRate
                {
                    BaseRateId      = "EARLY-EUR",
                    SpreadRateValue = 2
                },
                Title      = "early-withdrawal-interest",
                Currencies = new List <string> {
                    "EUR"
                }
            };

            ProductConditions conditions = new ProductConditions
            {
                Fees = new List <FeeCondition> {
                    regularFee
                },
                InterestRates = new List <InterestRateCondition> {
                    regularInterestEuribor, earlyWithdrawalInterest
                }
            };

            Application application                = Utility.GetApplication(conditions);
            var         arrangementRequest         = application.ArrangementRequests[0] as TermLoanRequest;
            var         priceCalculationConditions = Utility.GetPriceCalculationParameterFromTermLoanRequest(arrangementRequest);


            var result = OfferPriceCalculation.CalculatePrice(application, arrangementRequest);

            Assert.Single(result.Result.Conditions.Fees);
            Assert.Equal("RanToCompletion", result.Status.ToString());

            var resultInterest = result.Result.Conditions.InterestRates[0];
            var resultEarlyWithdrawalInterest = result.Result.Conditions.InterestRates[1];

            Assert.Equal("EURIBOR-3M", resultInterest.Rate.BaseRateId);
            Assert.Equal((decimal)8.5, resultInterest.CalculatedRate);
            Assert.Equal((decimal) - 1.5, resultInterest.Rate.BaseRateValue);
            Assert.Equal((decimal)10.0, resultInterest.Rate.SpreadRateValue);
            //C# won't let this be asserted in any other way
            Assert.Equal("0", resultInterest.Variations.Count.ToString());

            Assert.Equal("EARLY-EUR", resultEarlyWithdrawalInterest.Rate.BaseRateId);
            Assert.Equal((decimal)3.5, resultEarlyWithdrawalInterest.CalculatedRate);
            Assert.Equal((decimal)1.5, resultEarlyWithdrawalInterest.Rate.BaseRateValue);
            Assert.Equal((decimal)2.0, resultEarlyWithdrawalInterest.Rate.SpreadRateValue);

            Assert.Equal(0, resultInterest.CalculatedLowerLimit);
            Assert.Equal(100, resultInterest.CalculatedUpperLimit);
        }
Example #24
0
 public static PriceCalculationParameters GetPriceCalculationParametersFromConditions(ProductConditions conditions)
 {
     return(GetPriceCalculationParameterFromTermLoanRequest(GetArangementRequest(conditions)));
 }
        //Percentage and FixedAmount have two variations that sets them over upper limit and calculated should be equal to upper limit
        public void IterativeCalculatedOverUpperLimitMultipleVariations()
        {
            ConfigurationServiceMock       configurationService = new ConfigurationServiceMock();
            PriceCalculationDMNServiceMock priceCalCService     = new PriceCalculationDMNServiceMock(configurationService);
            MarketRatesServiceMock         marketRatesService   = new MarketRatesServiceMock();
            var          priceCalculator = new OfferPriceCalculation(priceCalCService, marketRatesService, configurationService, null);
            FeeCondition regularFee      = new FeeCondition
            {
                Percentage  = (decimal)0.1,
                FixedAmount = new Currency {
                    Amount = 20, Code = "EUR"
                },
                LowerLimit = new Currency {
                    Amount = 20, Code = "EUR"
                },
                UpperLimit = new Currency {
                    Amount = 200, Code = "EUR"
                },
                VariationsDefinitionDMN = "product/price-variations/iterative-multiple-fee-var-over-range.dmn",
                PercentageLowerLimit    = (decimal)0.05,
                PercentageUpperLimit    = 1,
                Title         = "Origination-fee1",
                EffectiveDate = DateTime.Now.AddDays(-1),
                Currencies    = new List <string> {
                    "RSD", "EUR"
                }
            };

            ProductConditions conditions = new ProductConditions
            {
                Fees = new List <FeeCondition> {
                    regularFee
                },
                InterestRates = new List <InterestRateCondition> {
                }
            };
            var arrangementRequest = Utility.GetArangementRequest(conditions);

            Application application = new Application
            {
                ArrangementNumber = "1",
                CustomerName      = "Tester",
                StatusInformation = new StatusInformation
                {
                    Description = "Works as a tester"
                },
                CustomerSegment = "student",
                CollateralModel = "two-co-debtors",

                RiskScore   = 55,
                ChannelCode = "web",
                RequestDate = DateTime.Now
            };

            var result     = priceCalculator.CalculatePrice(application, arrangementRequest);
            var resultFees = result.Result.Conditions.Fees[0];

            var variation = result.Result.Conditions.Fees[0].Variations;

            Assert.Equal("2", variation.Count.ToString());

            var variationOne = variation[0];
            var variationTwo = variation[1];

            Assert.Equal("RanToCompletion", result.Status.ToString());
            Assert.Equal(1, resultFees.CalculatedPercentage);
            Assert.Equal((decimal)0.5, variationOne.Percentage);
            Assert.Equal((decimal)0.6, variationTwo.Percentage);
            Assert.Equal("product/price-variations/iterative-multiple-fee-var-over-range.dmn", resultFees.VariationsDefinitionDMN);
        }
        //Percentage and FixedAmount have a variation that sets them to near lower limit but still above
        public void IterativeCalculatedNearLowerLimit()
        {
            ConfigurationServiceMock       configurationService = new ConfigurationServiceMock();
            PriceCalculationDMNServiceMock priceCalCService     = new PriceCalculationDMNServiceMock(configurationService);
            MarketRatesServiceMock         marketRatesService   = new MarketRatesServiceMock();
            var          priceCalculator = new OfferPriceCalculation(priceCalCService, marketRatesService, configurationService, null);
            FeeCondition regularFee      = new FeeCondition
            {
                //Samo % se testira za sada jer trenutno nema za fixedAmount
                //Samo varijacije uticu na PercentageKind = FeeConditionKinds.OriginationFee,
                Percentage  = (decimal)0.1,
                FixedAmount = new Currency {
                    Amount = 200, Code = "EUR"
                },
                LowerLimit = new Currency {
                    Amount = 20, Code = "EUR"
                },
                UpperLimit = new Currency {
                    Amount = 200, Code = "EUR"
                },
                VariationsDefinitionDMN = "product/price-variations/iterative-fee-in-range-lower.dmn",
                PercentageLowerLimit    = (decimal)0.01,
                PercentageUpperLimit    = 1,
                Title         = "Origination-fee1",
                EffectiveDate = DateTime.Now.AddDays(-1),
                Currencies    = new List <string> {
                    "RSD", "EUR"
                }
            };

            ProductConditions conditions = new ProductConditions
            {
                Fees = new List <FeeCondition> {
                    regularFee
                },
                InterestRates = new List <InterestRateCondition> {
                }
            };
            var arrangementRequest = Utility.GetArangementRequest(conditions);

            Application application = new Application
            {
                ArrangementNumber = "1",
                CustomerName      = "Tester",
                StatusInformation = new StatusInformation
                {
                    Description = "Works as a tester"
                },
                CustomerSegment = "student",
                CollateralModel = "two-co-debtors",

                RiskScore   = 55,
                ChannelCode = "web",
                RequestDate = DateTime.Now
            };

            var result = priceCalculator.CalculatePrice(application, arrangementRequest);

            //Basic assertions
            Assert.Equal("RanToCompletion", result.Status.ToString());

            Assert.Single(result.Result.Conditions.Fees);
            var resultFees = result.Result.Conditions.Fees[0];

            Assert.Single(resultFees.Variations);
            var variation = resultFees.Variations[0];


            //Asserting input
            Assert.Equal(200, resultFees.FixedAmount.Amount);
            Assert.Equal((decimal)0.1, resultFees.Percentage);

            //Asserting output
            Assert.Equal("product/price-variations/iterative-fee-in-range-lower.dmn", resultFees.VariationsDefinitionDMN);
            Assert.Equal((decimal)0.03, resultFees.CalculatedPercentage);
            Assert.Equal((decimal) - 0.07, variation.Percentage);
            Assert.Equal(22, resultFees.CalculatedFixedAmount);
            Assert.Equal(-178, variation.FixedAmount);
        }
        //No variations, calc rates should be as they are set in the request
        //Rate is within limits
        public void IterativeNoVariationsRateAboveLimitBasedOnMarketRate()
        {
            var OfferPriceCalculation = new OfferPriceCalculation(priceCalCService, marketRatesService, configurationService, null);
            InterestRateCondition regularInterestEuribor = new InterestRateCondition
            {
                //This base rate id removes -1.5 from spreadRateValue, making rate under limit
                Kind = InterestRateKinds.RegularInterest,
                Rate = new InterestRate
                {
                    BaseRateId      = "EURIBOR-4M",
                    SpreadRateValue = 17
                },
                UpperLimit = new InterestRate
                {
                    BaseRateId      = "EURIBOR-6M",
                    SpreadRateValue = 18
                },
                LowerLimit = new InterestRate
                {
                    BaseRateId      = "EURIBOR-6M",
                    SpreadRateValue = 10
                },
                Title      = "regular-interest",
                Currencies = new List <string> {
                    "EUR"
                }
            };

            ProductConditions conditions = new ProductConditions
            {
                Fees          = new List <FeeCondition> {
                },
                InterestRates = new List <InterestRateCondition> {
                    regularInterestEuribor
                }
            };
            var arrangementRequest = Utility.GetArangementRequest(conditions);

            Application application = new Application
            {
                ArrangementNumber = "1",
                CustomerName      = "Tester",
                StatusInformation = new StatusInformation
                {
                    Description = "Works as a tester"
                },
                CustomerSegment = "student",
                CollateralModel = "two-co-debtors",

                RiskScore   = 55,
                ChannelCode = "web",
                RequestDate = DateTime.Now
            };

            var result         = OfferPriceCalculation.CalculatePrice(application, arrangementRequest);
            var resultInterest = result.Result.Conditions.InterestRates[0];

            //Basic assertions
            Assert.Equal("RanToCompletion", result.Status.ToString());
            Assert.Equal("0", resultInterest.Variations.Count.ToString());

            //Asserting input parameters
            Assert.Equal("EURIBOR-4M", resultInterest.Rate.BaseRateId);
            Assert.Equal(2, resultInterest.Rate.BaseRateValue);
            Assert.Equal(17, resultInterest.Rate.SpreadRateValue);

            Assert.Equal("EURIBOR-6M", resultInterest.UpperLimit.BaseRateId);
            Assert.Equal(0, resultInterest.UpperLimit.BaseRateValue);
            Assert.Equal((decimal)18.0, resultInterest.UpperLimit.SpreadRateValue);

            Assert.Equal("EURIBOR-6M", resultInterest.LowerLimit.BaseRateId);
            Assert.Equal(0, resultInterest.LowerLimit.BaseRateValue);
            Assert.Equal((decimal)10.0, resultInterest.LowerLimit.SpreadRateValue);

            //Asserting Napr and calculation results
            Assert.Equal((decimal)18.0, ((TermLoanRequest)result.Result).Napr);
            Assert.Equal((decimal)18.0, resultInterest.CalculatedRate);
            Assert.Equal((decimal)10.0, resultInterest.CalculatedLowerLimit);
            Assert.Equal((decimal)18.0, resultInterest.CalculatedUpperLimit);
        }