/// <summary>
        /// Смята резултатите на финансовия калкулатор
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public CreditCalcResults Calculate(CreditCalcParams p)
        {
            IsParamsValid(p);
            CreditCalcResults res = null;

            if (p.IsAnnuityInstallments)
            {
                res = CalculateAnnuity(p);
            }
            else
            {
                res = CalculateDescending(p);
            }
            APRCalculator aprCalc = new APRCalculator(p.Amount);

            foreach (var m in res.MonthlyInstallments)
            {
                if (m.RowNumber == 0)
                {
                    aprCalc.AddInstalment(m.Fees, 0);
                }
                else
                {
                    aprCalc.AddInstalment(m.TotalInstallment, 365.25M / 12M * m.RowNumber);
                }
                res.TotalFees         += m.Fees;
                res.TotalRates        += m.RateInstallment;
                res.TotalInstallments += m.Installment;
            }
            res.AnnualPercentageRate = aprCalc.Calculate();
            res.TotalInstallmentsWithTotalFeesAndRates = res.TotalInstallments + res.TotalFees;
            return(res);
        }
        private CreditCalcParams GetParamsFromModel(CreditCalculatorParamsVM model)
        {
            CreditCalcParams res = new CreditCalcParams();

            res.Amount                             = model.Amount ?? 0;
            res.Period                             = model.Period ?? 0;
            res.Rate                               = model.Rate ?? 0;
            res.PromotionPeriod                    = model.PromotionPeriod;
            res.PromotionRate                      = model.PromotionRate;
            res.GratisPeriod                       = model.GratisPeriod;
            res.IsAnnuityInstallments              = model.IsAnnuityInstallments;
            res.ApplicationFee                     = model.ApplicationFee;
            res.TreatApplicationFeeAsPercent       = model.TreatApplicationFeeAsPercent;
            res.ProcessingFee                      = model.ProcessingFee;
            res.TreatProcessingFeeAsPercent        = model.TreatProcessingFeeAsPercent;
            res.OtherInitialFees                   = model.OtherInitialFees;
            res.TreatOtherInitialFeesAsPercent     = model.TreatOtherInitialFeesAsPercent;
            res.MonthlyManagementFee               = model.MonthlyManagementFee;
            res.TreatMonthlyManagementFeeAsPercent = model.TreatMonthlyManagementFeeAsPercent;
            res.OtherMonthlyFees                   = model.OtherMonthlyFees;
            res.TreatOtherMonthlyFeesAsPercent     = model.TreatOtherMonthlyFeesAsPercent;
            res.AnnualManagementFee                = model.AnnualManagementFee;
            res.TreatAnnualManagementFeeAsPercent  = model.TreatAnnualManagementFeeAsPercent;
            res.OtherAnnualFees                    = model.OtherAnnualFees;
            res.TreatOtherAnnualFeesAsPercent      = model.TreatOtherAnnualFeesAsPercent;

            return(res);
        }
 /// <summary>
 /// Пресмята първоначалните такси
 /// </summary>
 /// <param name="p"></param>
 /// <param name="m"></param>
 /// <returns></returns>
 private decimal InitialFeesCalc(CreditCalcParams p, MonthlyResult m)
 {
     m.Fees  = getFeeAmount(p.Amount, p.ApplicationFee, p.TreatApplicationFeeAsPercent);
     m.Fees += getFeeAmount(p.Amount, p.ProcessingFee, p.TreatProcessingFeeAsPercent);
     m.Fees += getFeeAmount(p.Amount, p.OtherInitialFees, p.TreatOtherInitialFeesAsPercent);
     return(Math.Round(m.Fees, 2));
 }
        /// <summary>
        /// Пресмята и запълва първия ред от погасителния план
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        private MonthlyResult GetZeroMonth(CreditCalcParams p)
        {
            MonthlyResult m = new MonthlyResult();

            m.RowNumber          = 0;
            m.Date               = DateTime.Now;
            m.Installment        = m.PrinicpalInstallment = m.RateInstallment = 0;
            m.PrincipalRemainder = p.Amount;
            m.Fees               = InitialFeesCalc(p, m);
            m.TotalInstallment   = p.Amount - m.Fees;
            return(m);
        }
        /// <summary>
        /// Функция, пресмятаща резултатите от погасителния план при намаляващи месечни вноски
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        private CreditCalcResults CalculateDescending(CreditCalcParams p)
        {
            CreditCalcResults res = new CreditCalcResults();

            res.MonthlyInstallments = new List <MonthlyResult>();
            res.MonthlyInstallments.Add(GetZeroMonth(p));
            decimal principalInstallment = Math.Round(p.Amount / (p.Period - (p.GratisPeriod ?? 0)), 2);

            for (int i = 1; i <= p.Period; i++)
            {
                MonthlyResult m = new MonthlyResult();
                if (i == 1)
                {
                    m.PrincipalRemainder = p.Amount;
                }
                else
                {
                    m.PrincipalRemainder = res.MonthlyInstallments[i - 1].CurrentPrincipallRemainder();
                }
                m.RowNumber = i;
                m.Date      = DateTime.Now.AddMonths(i);
                bool isInPromotion = (i <= (p.PromotionPeriod ?? 0));
                bool isInGratis    = (i <= (p.GratisPeriod ?? 0));
                m.RateInstallment = Math.Round((decimal)(m.PrincipalRemainder * (isInPromotion ? p.PromotionRate : p.Rate) / 100) / 12, 2);
                if (isInGratis)
                {
                    m.PrinicpalInstallment = 0;
                }
                else
                {
                    m.PrinicpalInstallment = (i == p.Period) ? Math.Round(p.Amount - (i - 1 - (p.GratisPeriod ?? 0)) * principalInstallment, 2) : principalInstallment;
                }
                m.Installment = (isInGratis ? 0 : m.PrinicpalInstallment) + m.RateInstallment;
                if (i % 12 == 1 && i != 1)
                {
                    m.Fees = MonthlyFeesCalc(p, m) + AnnualFeesCalc(p, m);
                }
                else
                {
                    m.Fees = MonthlyFeesCalc(p, m);
                }
                m.TotalInstallment = m.Installment + m.Fees;
                res.MonthlyInstallments.Add(m);
            }
            return(res);
        }
Exemplo n.º 6
0
 public CreditCalcResults CalculateCredit(CreditCalcParams parameters)
 {
     return(this.creditCalculator.Calculate(parameters));
 }
        public void IsParamsValid(CreditCalcParams Params)
        {
            if ((Params.Amount) <= 0 || (Params.Amount) > 999999999)
            {
                throw new ArgumentException("Моля въведете размер на кредита по-голям от нула и по-малко от 1 000 000 000.");
            }
            if ((Params.Period) <= 0 || (Params.Period) > 960)
            {
                throw new ArgumentException("Моля въведете коректно число за срок (до 960 месеца).");
            }
            if ((Params.Rate) <= 0)
            {
                throw new ArgumentException("Моля въведете размер на лихвата по-голяма от нула.");
            }
            if (Params.PromotionPeriod.HasValue && (Params.PromotionPeriod <= 0 || Params.PromotionPeriod >= Params.Period))
            {
                throw new ArgumentException("Моля въведете коректно число за промоционален период (промоционалният период трябва да е по-голям от нула и по-малък от срока на кредита).");
            }
            if (!Params.PromotionRate.HasValue && Params.PromotionPeriod.HasValue)
            {
                throw new ArgumentException("Моля въведете коректно число за промоционална лихва(въвели сте промоционален период, но не сте въвели промоционална лихва)");
            }
            if (Params.PromotionRate.HasValue && !Params.PromotionPeriod.HasValue)
            {
                throw new ArgumentException("Моля въведете коректно число за промоционален период(въвели сте промоционална лихва, но не сте въвели промоционален период)");
            }
            if (Params.GratisPeriod.HasValue && (Params.GratisPeriod <= 0 || Params.GratisPeriod >= Params.Period))
            {
                throw new ArgumentException("Моля въведете коректно число за гратисен период (гратисният период трябва да е по-малък от срока на кредита)");
            }
            if (Params.ApplicationFee.HasValue)
            {
                if (Params.TreatApplicationFeeAsPercent && (Params.ApplicationFee <= 0 || Params.ApplicationFee >= 41))
                {
                    throw new ArgumentException("Моля въведете коректно число за такса кандидатстване.");
                }
                else if (Params.ApplicationFee <= 0)
                {
                    throw new ArgumentException("Моля въведете коректно число за такса кандидатстване.");
                }
            }
            if ((Params.ApplicationFee.HasValue || Params.ProcessingFee.HasValue || Params.OtherInitialFees.HasValue) && Params.Amount > 0)
            {
                if (getFeeAmount(Params.Amount, Params.ApplicationFee, Params.TreatApplicationFeeAsPercent)
                    + getFeeAmount(Params.Amount, Params.ProcessingFee ?? 0, Params.TreatProcessingFeeAsPercent)
                    + getFeeAmount(Params.Amount, Params.OtherInitialFees ?? 0, Params.TreatOtherInitialFeesAsPercent) > (Params.Amount / 2))
                {
                    throw new ArgumentException("Първоначалните такси не трябва да надвишават 50% от размера на кредита.");
                }
            }

            if (Params.AnnualManagementFee.HasValue)
            {
                if (Params.TreatAnnualManagementFeeAsPercent && (Params.AnnualManagementFee <= 0 || Params.AnnualManagementFee >= 41))
                {
                    throw new ArgumentException("Моля въведете коректно число за Годишна такса.");
                }
                else if (Params.AnnualManagementFee <= 0)
                {
                    throw new ArgumentException("Моля въведете коректно число за Годишна такса.");
                }
            }
            if (Params.OtherAnnualFees.HasValue)
            {
                if (Params.TreatOtherAnnualFeesAsPercent && (Params.OtherAnnualFees <= 0 || Params.OtherAnnualFees >= 41))
                {
                    throw new ArgumentException("Моля въведете коректно число за други годишни такси.");
                }
                if (!Params.TreatOtherAnnualFeesAsPercent && (Params.OtherAnnualFees <= 0 || Params.OtherAnnualFees >= Params.Amount))
                {
                    throw new ArgumentException("Моля въведете коректно число за други годишни такси.");
                }
            }
            if (Params.MonthlyManagementFee.HasValue)
            {
                if (Params.TreatMonthlyManagementFeeAsPercent && (Params.MonthlyManagementFee <= 0 || Params.MonthlyManagementFee >= 41))
                {
                    throw new ArgumentException("Моля въведете коректно число за месечна такса управление.");
                }
                if (!Params.TreatMonthlyManagementFeeAsPercent && (Params.MonthlyManagementFee <= 0 || Params.MonthlyManagementFee >= Params.Amount))
                {
                    throw new ArgumentException("Моля въведете коректно число за месечна такса управление.");
                }
            }
            if (Params.OtherMonthlyFees.HasValue)
            {
                if (Params.TreatOtherMonthlyFeesAsPercent && (Params.OtherMonthlyFees <= 0 || Params.OtherMonthlyFees >= 41))
                {
                    throw new ArgumentException("Моля въведете коректно число за други месечни такси.");
                }
                if (!Params.TreatOtherMonthlyFeesAsPercent && (Params.OtherMonthlyFees <= 0 || Params.OtherMonthlyFees >= Params.Amount))
                {
                    throw new ArgumentException("Моля въведете коректно число за други месечни такси.");
                }
            }
        }
        /// <summary>
        /// Функция, пресмятаща резултатите от погасителния план при анюитетни вноски
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        private CreditCalcResults CalculateAnnuity(CreditCalcParams p)
        {
            CreditCalcResults res = new CreditCalcResults();

            res.MonthlyInstallments = new List <MonthlyResult>();
            res.MonthlyInstallments.Add(GetZeroMonth(p));
            bool    hasPromotion           = p.PromotionPeriod.HasValue;
            decimal pmtPromotional         = hasPromotion ? PMT(p.PromotionRate.Value, p.Period - (p.GratisPeriod ?? 0), p.Amount) : 0;
            decimal pmtNormal              = hasPromotion ? 0 : PMT(p.Rate, p.Period - (p.GratisPeriod ?? 0), p.Amount);
            decimal promotionalInstallment = 0;

            for (int i = 1; i <= p.Period; i++)
            {
                MonthlyResult m = new MonthlyResult();
                if (i == 1)
                {
                    m.PrincipalRemainder = p.Amount;
                }
                else
                {
                    m.PrincipalRemainder = res.MonthlyInstallments[i - 1].CurrentPrincipallRemainder();
                }
                m.RowNumber = i;
                m.Date      = DateTime.Now.AddMonths(i);
                if (i <= (p.PromotionPeriod ?? 0))
                {
                    m.RateInstallment = Math.Round((decimal)(m.PrincipalRemainder * p.PromotionRate / 100) / 12, 2);
                    if (i <= (p.GratisPeriod ?? 0))
                    {
                        m.Installment = m.RateInstallment;
                    }
                    else
                    {
                        m.Installment = pmtPromotional;
                    }
                    m.PrinicpalInstallment  = m.Installment - m.RateInstallment;
                    promotionalInstallment += m.PrinicpalInstallment;
                }
                else
                {
                    m.RateInstallment = Math.Round((decimal)(m.PrincipalRemainder * p.Rate / 100) / 12, 2);
                    if (i <= (p.GratisPeriod ?? 0))
                    {
                        m.Installment = m.RateInstallment;
                    }
                    else
                    {
                        if (pmtNormal == 0)
                        {
                            pmtNormal = PMT(p.Rate, p.Period - Math.Max(p.PromotionPeriod.Value, p.GratisPeriod ?? 0), p.Amount - promotionalInstallment);
                        }
                        if (i == p.Period)
                        {
                            pmtNormal = PMT(p.Rate, 1, m.PrincipalRemainder);
                        }
                        m.Installment = pmtNormal;
                    }
                    m.PrinicpalInstallment = m.Installment - m.RateInstallment;
                }
                if (i % 12 == 1 && i != 1)
                {
                    m.Fees = MonthlyFeesCalc(p, m) + AnnualFeesCalc(p, m);
                }
                else
                {
                    m.Fees = MonthlyFeesCalc(p, m);
                }
                m.TotalInstallment = m.Installment + m.Fees;
                res.MonthlyInstallments.Add(m);
            }
            return(res);
        }
 /// <summary>
 /// Функция, пресмятаща годишните такси
 /// </summary>
 /// <param name="p"></param>
 /// <param name="m"></param>
 /// <returns></returns>
 private decimal AnnualFeesCalc(CreditCalcParams p, MonthlyResult m)
 {
     m.Fees  = getFeeAmount(m.PrincipalRemainder, p.AnnualManagementFee, p.TreatAnnualManagementFeeAsPercent);
     m.Fees += getFeeAmount(m.PrincipalRemainder, p.OtherAnnualFees, p.TreatOtherAnnualFeesAsPercent);
     return(Math.Round(m.Fees, 2));
 }