Example #1
0
        public static LoanDisbursmentEvent GenerateLoanDisbursmentEvent(Loan pLoan, ApplicationSettings pGeneralSettings, DateTime pDisburseDate, bool pAlignInstallmentsDatesOnRealDisbursmentDate, bool pDisableFees, User pUser)
        {
            if (pAlignInstallmentsDatesOnRealDisbursmentDate)
            {
                //pLoan.StartDate = pDisburseDate;
                //for (int i = 1; i <= pLoan.NbOfInstallments; i++)
                //{
                //    pLoan.InstallmentList[i - 1].ExpectedDate = pLoan.CalculateInstallmentDate(pLoan.StartDate, i);
                //}
            }
            else
            {
                if (pGeneralSettings.PayFirstInterestRealValue)
                {
                    TimeSpan time     = pDisburseDate - pLoan.StartDate;
                    int      diffDays = Math.Abs(time.Days);

                    int nbOfDaysInPeriod = pLoan.InstallmentType.NbOfMonths * AVERAGE_NB_OF_DAYS_IN_MONTH + pLoan.InstallmentType.NbOfDays;

                    if (pDisburseDate.CompareTo(pLoan.StartDate) < 0)
                    {
                        pLoan.GetInstallment(0).InterestsRepayment += (Convert.ToDecimal(pLoan.InterestRate) * diffDays * pLoan.Amount / (double)nbOfDaysInPeriod);
                    }
                    else
                    {
                        pLoan.GetInstallment(0).InterestsRepayment -= (Convert.ToDecimal(pLoan.InterestRate) * diffDays * pLoan.Amount / (double)nbOfDaysInPeriod);
                    }

                    if (AmountComparer.Compare(pLoan.GetInstallment(0).InterestsRepayment, 0) < 0)
                    {
                        pLoan.GetInstallment(0).InterestsRepayment = 0;
                    }
                    pLoan.GetInstallment(0).InterestsRepayment = Math.Round(pLoan.GetInstallment(0).InterestsRepayment.Value, 2);
                }
            }

            pLoan.Disbursed = true;
            LoanDisbursmentEvent lDe = !pDisableFees
                                           ? new LoanDisbursmentEvent
            {
                Date       = pDisburseDate,
                Amount     = pLoan.Amount,
                ClientType = pLoan.ClientType
            }
                                           : new LoanDisbursmentEvent
            {
                Date        = pDisburseDate,
                Amount      = pLoan.Amount,
                Commissions = null,
                ClientType  = pLoan.ClientType
            };

            pLoan.Events.Add(lDe);
            return(lDe);
        }
Example #2
0
        public void Repay(ref OCurrency pAmountPaid, ref OCurrency pFeesEvent, ref OCurrency pCommissionsEvent, ref OCurrency pInterestEvent)
        {
            if (_cco.CancelFees && (_cco.ManualFeesAmount + _cco.ManualCommissionAmount) >= 0)
            {
                pCommissionsEvent = _cco.ManualCommissionAmount;
                pFeesEvent        = _cco.ManualFeesAmount;

                if (AmountComparer.Compare(pAmountPaid, _cco.ManualFeesAmount + _cco.ManualCommissionAmount) > 0)
                {
                    //pAmountPaid -= _cco.ManualFeesAmount + _cco.ManualCommissionAmount;
                }
                else
                {
                    pAmountPaid = 0;
                }
            }

            if (_cco.KeepExpectedInstallments)
            {
                if (_cco.CancelInterests && _cco.ManualInterestsAmount >= 0)
                {
                    OCurrency manualInterestAmount = _cco.ManualInterestsAmount;
                    for (int i = 0; i < _contract.NbOfInstallments; i++)
                    {
                        Installment installment = _contract.GetInstallment(i);
                        if (!installment.IsRepaid && pAmountPaid > 0 && manualInterestAmount > 0)
                        {
                            OCurrency interestHasToPay = installment.InterestsRepayment - installment.PaidInterests;
                            if (AmountComparer.Compare(manualInterestAmount, interestHasToPay) > 0)
                            {
                                pInterestEvent           += interestHasToPay;
                                installment.PaidInterests = installment.InterestsRepayment;
                                pAmountPaid          -= interestHasToPay;
                                manualInterestAmount -= interestHasToPay;
                            }
                            else
                            {
                                pInterestEvent            += manualInterestAmount;
                                installment.PaidInterests += manualInterestAmount;
                                pAmountPaid         -= manualInterestAmount;
                                manualInterestAmount = 0;
                            }

                            PaidIstallments.Add(installment);
                        }
                    }
                }
            }
        }
 private static void AutomaticRepayMethod(Installment pInstallment, ref OCurrency pAmountPaid, ref OCurrency pCommisionEvent)
 {
     if (AmountComparer.Compare(pAmountPaid, pInstallment.CommissionsUnpaid) > 0)
     {
         pCommisionEvent += pInstallment.CommissionsUnpaid;
         pAmountPaid     -= pInstallment.CommissionsUnpaid;
         pInstallment.PaidCommissions  += pInstallment.CommissionsUnpaid;
         pInstallment.CommissionsUnpaid = 0;
     }
     else
     {
         pCommisionEvent += pAmountPaid;
         pInstallment.PaidCommissions   += pAmountPaid;
         pInstallment.CommissionsUnpaid -= pAmountPaid;
         pAmountPaid = 0;
     }
 }
Example #4
0
        public void CalculateFees(DateTime pDate, ref OCurrency pAmountPaid, ref OCurrency pFeesEvent)
        {
            OCurrency fees = _loan.UseCents
                                        ? Math.Round(_bTcffar.CalculateFees(pDate).Value, 2)
                                        : Math.Round(_bTcffar.CalculateFees(pDate).Value, 0);

            if (AmountComparer.Compare(fees, pAmountPaid) > 0)
            {
                pFeesEvent += pAmountPaid;
                pAmountPaid = 0;
            }
            else
            {
                pAmountPaid -= fees;
                pFeesEvent  += fees;
            }
        }
Example #5
0
 public void Repay(Installment pInstallment, ref OCurrency pAmountPaid, ref OCurrency pFeesEvent)
 {
     if (AmountComparer.Compare(pAmountPaid, pInstallment.FeesUnpaid) > 0)
     {
         pFeesEvent             += pInstallment.FeesUnpaid;
         pAmountPaid            -= pInstallment.FeesUnpaid;
         pInstallment.PaidFees  += pInstallment.FeesUnpaid;
         pInstallment.FeesUnpaid = 0;
     }
     else
     {
         pFeesEvent              += pAmountPaid;
         pInstallment.PaidFees   += pAmountPaid;
         pInstallment.FeesUnpaid -= pAmountPaid;
         pAmountPaid              = 0;
     }
 }
Example #6
0
        public void Repay(Installment pInstallment, ref OCurrency pAmountPaid, ref OCurrency pInterestEvent, ref OCurrency pInterestPrepayment)
        {
            if (AmountComparer.Compare(pAmountPaid, pInstallment.InterestsRepayment - pInstallment.PaidInterests) > 0)
            {
                OCurrency interestHasToPay = pInstallment.InterestsRepayment - pInstallment.PaidInterests;

                pAmountPaid                -= interestHasToPay;
                pInterestEvent             += interestHasToPay;
                pInterestPrepayment        += interestHasToPay;
                pInstallment.PaidInterests += interestHasToPay;
            }
            else
            {
                pInstallment.PaidInterests += pAmountPaid;
                pInterestEvent             += pAmountPaid;
                pInterestPrepayment        += pAmountPaid;
                pAmountPaid = 0;
            }
        }
Example #7
0
        public void RepayNextInstallments(ref OCurrency amountPaid, ref OCurrency interestEvent, ref OCurrency interestPrepayment, ref OCurrency principalEvent, ref OCurrency feesEvent, ref OCurrency commissionsEvent)
        {
            if (amountPaid > 0)
            {
                OCurrency totalInterest  = 0;
                OCurrency totalPrincipal = 0;
                double    nbInterest     = 0;
                double    nbPrincipal    = 0;

                foreach (Installment _installment in _contract.InstallmentList)
                {
                    if (_installment.InterestsRepayment - _installment.PaidInterests > 0)
                    {
                        totalInterest += (_installment.InterestsRepayment - _installment.PaidInterests);
                        if (!_contract.GracePeriod.HasValue)
                        {
                            nbInterest += _contract.Product.ExoticProduct.GetExoticInstallment(_installment.Number - 1).InterestCoeff.Value;
                        }
                        else if (_installment.Number > _contract.GracePeriod.Value)
                        {
                            nbInterest += _contract.Product.ExoticProduct.GetExoticInstallment(_installment.Number - 1 - _contract.GracePeriod.Value).InterestCoeff.Value;
                        }
                    }

                    if (_installment.CapitalRepayment - _installment.PaidCapital > 0)
                    {
                        totalPrincipal += (_installment.CapitalRepayment - _installment.PaidCapital);
                        if (!_contract.GracePeriod.HasValue)
                        {
                            nbPrincipal += _contract.Product.ExoticProduct.GetExoticInstallment(_installment.Number - 1).PrincipalCoeff;
                        }
                        else if (_installment.Number > _contract.GracePeriod.Value)
                        {
                            nbPrincipal += _contract.Product.ExoticProduct.GetExoticInstallment(_installment.Number - 1 - _contract.GracePeriod.Value).PrincipalCoeff;
                        }
                    }
                }

                if (AmountComparer.Compare(amountPaid, totalInterest) > 0)
                {
                    amountPaid         -= totalInterest;
                    interestEvent      += totalInterest;
                    interestPrepayment += totalInterest;
                    totalInterest       = 0;
                }
                else
                {
                    totalInterest      -= amountPaid;
                    interestEvent      += amountPaid;
                    interestPrepayment += amountPaid;
                    amountPaid          = 0;
                }

                if (AmountComparer.Compare(amountPaid, totalPrincipal) > 0)
                {
                    amountPaid     -= totalPrincipal;
                    principalEvent += totalPrincipal;
                    totalPrincipal  = 0;
                }
                else
                {
                    totalPrincipal -= amountPaid;
                    principalEvent += amountPaid;
                    amountPaid      = 0;
                }

                if (totalInterest != 0)
                {
                    totalInterest = totalInterest / (Convert.ToDecimal(nbInterest) * 10);
                }

                if (totalPrincipal != 0)
                {
                    totalPrincipal = totalPrincipal / (Convert.ToDecimal(nbPrincipal) * 10);
                }

                for (int i = 0; i < _contract.NbOfInstallments; i++)
                {
                    Installment _installment = _contract.GetInstallment(i);
                    if (!_installment.IsRepaid)
                    {
                        ExoticInstallment exoticInstallment = null;

                        if (!_contract.GracePeriod.HasValue)
                        {
                            exoticInstallment = _contract.Product.ExoticProduct.GetExoticInstallment(i);
                            _installment.InterestsRepayment = Convert.ToDecimal(exoticInstallment.InterestCoeff.Value) * totalInterest * (double)10;
                            _installment.CapitalRepayment   = Convert.ToDecimal(exoticInstallment.PrincipalCoeff) * totalPrincipal * (double)10;
                        }
                        else if (_installment.Number > _contract.GracePeriod.Value)
                        {
                            exoticInstallment = _contract.Product.ExoticProduct.GetExoticInstallment(i - _contract.GracePeriod.Value);
                            _installment.InterestsRepayment = Convert.ToDecimal(exoticInstallment.InterestCoeff.Value) * totalInterest * (double)10;
                            _installment.CapitalRepayment   = Convert.ToDecimal(exoticInstallment.PrincipalCoeff) * totalPrincipal * (double)10;
                        }
                        else
                        {
                            _installment.InterestsRepayment = totalInterest * Convert.ToDecimal(_contract.InterestRate);
                            _installment.CapitalRepayment   = 0;
                        }
                    }
                }
            }
        }
 public void TestEqualsWhenFirstNumberGreaterThanSecondOne()
 {
     Assert.IsFalse(AmountComparer.Equals(243m, 242.97m));
 }
 public void TestCompareWhenAmount2MinusAmount1LowerThan002()
 {
     Assert.IsTrue(AmountComparer.Compare(154.014m, 154.033m) == 0);
 }
 public void TestCompareWhenAmount2MinusAmount1GreaterThan002()
 {
     Assert.IsTrue(AmountComparer.Compare(154.011m, 154.033m) < 0);
 }
 public void TestEqualsWhenSecondNumberGreaterThanFirstOneButDifferenceLowerThan002()
 {
     Assert.IsTrue(AmountComparer.Equals(1567.1234m, 1567.1238m));
 }
 public void TestCompareWhenAmount1MinusAmount2GreaterThan002()
 {
     Assert.IsTrue(AmountComparer.Compare(154.033m, 154.001m) > 0);
 }
 public void TestEqualsWhenFirstNumberGreaterThanSecondOneButDifferenceLowerThan002()
 {
     Assert.IsTrue(AmountComparer.Equals(243.001m, 243.02m));
 }
        public void RepayNextInstallments(ref OCurrency amountPaid, ref OCurrency interestEvent, ref OCurrency interestPrepayment, ref OCurrency principalEvent, ref OCurrency feesEvent, ref OCurrency commissionsEvent)
        {
            if (amountPaid == 0)
            {
                return;
            }
            for (int i = 0; i < _contract.NbOfInstallments; i++)
            {
                Installment installment = _contract.GetInstallment(i);
                if (!installment.IsRepaid && amountPaid > 0)
                {
                    //commission
                    _methodToRepayCommission.RepayCommission(installment, ref amountPaid, ref commissionsEvent);
                    if (amountPaid == 0)
                    {
                        break;
                    }

                    //penalty
                    _methodToRepayFees.RepayFees(installment, ref amountPaid, ref feesEvent);
                    if (amountPaid == 0)
                    {
                        break;
                    }

                    //Interests
                    if (amountPaid == 0)
                    {
                        return;
                    }
                    _methodToRepayInterest.RepayInterest(installment, ref amountPaid, ref interestEvent, ref interestPrepayment);

                    //principal
                    if (amountPaid == 0)
                    {
                        _paidInstallments.Add(installment);
                        return;
                    }

                    OCurrency principalHasToPay = installment.CapitalRepayment - installment.PaidCapital;

                    if (AmountComparer.Compare(amountPaid, principalHasToPay) < 0)
                    {
                        installment.PaidCapital += amountPaid;
                        installment.PaidCapital  = Math.Round(installment.PaidCapital.Value, 2);
                        principalEvent          += amountPaid;
                        amountPaid = 0;
                    }
                    else if (AmountComparer.Compare(amountPaid, principalHasToPay) > 0)
                    {
                        installment.PaidCapital = installment.CapitalRepayment;
                        amountPaid     -= principalHasToPay;
                        principalEvent += principalHasToPay;
                    }
                    else
                    {
                        installment.PaidCapital += amountPaid;
                        installment.PaidCapital  = Math.Round(installment.PaidCapital.Value, 2);
                        principalEvent          += amountPaid;
                        amountPaid = 0;
                    }

                    _paidInstallments.Add(installment);
                }
            }
        }
        public void RepayInstallments(DateTime payDate,
                                      ref OCurrency amountPaid,
                                      ref OCurrency interestEvent,
                                      ref OCurrency principalEvent,
                                      ref OCurrency feesEvent,
                                      ref OCurrency commissionsEvent,
                                      ref OPaymentType paymentType)
        {
            if (amountPaid == 0)
            {
                return;
            }
            // we need date without time part
            payDate = payDate.Date;

            Installment installment = null;

            int daysInTheYear = _generalSettings.GetDaysInAYear(_contract.StartDate.Year);
            int startNumber   = 0;
            int roundingPoint = _contract.UseCents ? 2 : 0;

            OCurrency olb               = _contract.CalculateActualOlb();
            OCurrency actualOlb         = _contract.CalculateActualOlb();
            OCurrency interestsToRepay  = 0;
            OCurrency movedPrincipal    = 0;
            OCurrency paidPrincipal     = 0;
            OCurrency paymentOfInterest = 0;
            OCurrency totalAmount       = _calculateMaximumAmount.CalculateMaximumAmountAuthorizedToRepay(payDate);

            DateTime beginDate           = _contract.StartDate;
            DateTime date                = _contract.StartDate;
            bool     recalculateSchedule = false;
            bool     totalPayment        = totalAmount == amountPaid &&
                                           _contract.GetFirstUnpaidInstallment().Number != _contract.InstallmentList.Count;

            #region calculate interest payment)
            for (int i = 0; i < _contract.NbOfInstallments; i++)
            {
                installment = _contract.GetInstallment(i);
                if (!installment.IsRepaid)
                {
                    //get last repDate
                    if (date < _contract.GetLastRepaymentDate())
                    {
                        date      = _contract.GetLastRepaymentDate();
                        beginDate = date;
                    }
                }
            }

            for (int i = 0; i < _contract.NbOfInstallments; i++)
            {
                installment = _contract.GetInstallment(i);
                if (installment.IsRepaid)
                {
                    continue;
                }
                if (installment.Number == 1 && installment.ExpectedDate > payDate)
                {
                    if (installment.PaidCapital == 0 && installment.PaidInterests > 0)
                    {
                        date = installment.Number == 1
                                   ? _contract.StartDate
                                   : _contract.GetInstallment(installment.Number - 2).ExpectedDate;
                        beginDate = date;
                    }

                    int daySpan = (payDate - _contract.StartDate).Days < 0
                                      ? 0
                                      : (payDate - _contract.StartDate).Days;

                    installment.InterestsRepayment = olb * _contract.InterestRate * daySpan / daysInTheYear;

                    installment.InterestsRepayment =
                        Math.Round(installment.InterestsRepayment.Value, roundingPoint,
                                   MidpointRounding.AwayFromZero);
                    interestsToRepay += installment.InterestsRepayment;
                    startNumber       = 0;
                    date              = installment.ExpectedDate;
                }

                if (installment.Number > 1 && installment.ExpectedDate > payDate)
                {
                    OCurrency paidInterests = installment.PaidInterests;

                    int daySpan = (payDate - date).Days < 0 ? 0 : (payDate - date).Days;
                    installment.InterestsRepayment = olb * _contract.InterestRate * daySpan / daysInTheYear + paidInterests;

                    installment.InterestsRepayment =
                        Math.Round(installment.InterestsRepayment.Value, roundingPoint,
                                   MidpointRounding.AwayFromZero);
                    interestsToRepay += installment.InterestsRepayment - paidInterests;
                    date              = installment.ExpectedDate;
                }

                if (installment.ExpectedDate <= payDate)
                {
                    OCurrency calculatedInterest = 0;
                    OCurrency paidInterest       = 0;

                    if (installment.PaidInterests > 0 &&
                        installment.InterestsRepayment > installment.PaidInterests)
                    {
                        calculatedInterest = installment.PaidInterests;
                    }

                    if (installment.PaidCapital == 0 &&
                        installment.PaidInterests > 0 &&
                        installment.PaidInterests != installment.InterestsRepayment)
                    {
                        DateTime dateOfInstallment = installment.Number == 1
                                                         ? _contract.StartDate
                                                         : _contract.GetInstallment(installment.Number - 2).ExpectedDate;

                        int d = (date - dateOfInstallment).Days;

                        OCurrency olbBeforePayment =
                            _contract.Events.GetRepaymentEvents().Where(
                                repaymentEvent =>
                                !repaymentEvent.Deleted && repaymentEvent.Date <= dateOfInstallment).
                            Aggregate(
                                _contract.Amount,
                                (current, repaymentEvent) => current - repaymentEvent.Principal);

                        calculatedInterest =
                            (olbBeforePayment * Convert.ToDecimal(_contract.InterestRate) / daysInTheYear * d).Value;
                        calculatedInterest = Math.Round(calculatedInterest.Value, roundingPoint,
                                                        MidpointRounding.AwayFromZero);

                        if (installment.PaidInterests < calculatedInterest && actualOlb == olbBeforePayment)
                        {
                            paidInterest       = installment.PaidInterests.Value;
                            calculatedInterest = 0;
                            date = dateOfInstallment;
                        }

                        if (installment.PaidInterests < calculatedInterest && actualOlb != olbBeforePayment)
                        {
                            paidInterest       = 0;
                            calculatedInterest = installment.PaidInterests;
                        }
                    }

                    DateTime expectedDate = installment.ExpectedDate;
                    //in case very late repayment
                    if (installment.Number == _contract.InstallmentList.Count &&
                        installment.ExpectedDate < payDate &&
                        installment.PaidCapital == 0)
                    {
                        expectedDate = payDate;
                    }

                    int daySpan = (expectedDate - date).Days < 0
                                      ? 0
                                      : (expectedDate - date).Days;

                    if (daySpan == 0 && calculatedInterest > 0)
                    {
                        interestsToRepay += calculatedInterest - installment.PaidInterests;
                    }

                    if (daySpan > 0)
                    {
                        installment.InterestsRepayment = Math.Round((olb * _contract.InterestRate / daysInTheYear * daySpan).Value,
                                                                    roundingPoint, MidpointRounding.AwayFromZero);
                        installment.InterestsRepayment =
                            Math.Round(calculatedInterest.Value + installment.InterestsRepayment.Value,
                                       roundingPoint,
                                       MidpointRounding.AwayFromZero);
                        interestsToRepay += installment.InterestsRepayment - calculatedInterest - paidInterest;
                        date              = installment.ExpectedDate;
                    }
                }
            }
            #endregion

            #region Repay installment
            for (int i = 0; i < _contract.NbOfInstallments; i++)
            {
                installment = _contract.GetInstallment(i);

                #region payment on time
                if (installment.ExpectedDate == payDate)
                {
                    OCurrency interestPrepayment = 0;
                    installment.CommissionsUnpaid = 0;
                    installment.FeesUnpaid        = 0;
                    installment.PaidFees          = 0;

                    //interest
                    if (amountPaid == 0)
                    {
                        break;
                    }
                    _methodToRepayInterest.RepayInterest(installment, ref amountPaid, ref paymentOfInterest,
                                                         ref interestPrepayment);

                    interestsToRepay -= paymentOfInterest;

                    if (interestsToRepay < amountPaid && amountPaid > 0)
                    {
                        if (!totalPayment)
                        {
                            if (
                                AmountComparer.Compare(amountPaid,
                                                       installment.CapitalRepayment - installment.PaidCapital) > 0)
                            {
                                if (installment.CapitalRepayment - installment.PaidCapital == amountPaid)
                                {
                                    OCurrency principalHasToPay = installment.CapitalRepayment - installment.PaidCapital;
                                    installment.PaidCapital = installment.CapitalRepayment;
                                    amountPaid    -= principalHasToPay;
                                    paidPrincipal += principalHasToPay;
                                }
                                else
                                {
                                    OCurrency paidCapital = installment.PaidCapital;
                                    movedPrincipal               = amountPaid - installment.CapitalRepayment + paidCapital;
                                    installment.PaidCapital      = amountPaid + paidCapital;
                                    installment.CapitalRepayment = amountPaid + paidCapital;
                                    paidPrincipal += amountPaid;
                                    amountPaid     = 0;
                                }
                            }
                            else
                            {
                                installment.PaidCapital += amountPaid;
                                paidPrincipal           += amountPaid;
                                amountPaid = 0;
                            }
                        }
                        else
                        {
                            installment.PaidCapital      = amountPaid;
                            installment.CapitalRepayment = amountPaid;
                            paidPrincipal += amountPaid;
                            amountPaid     = 0;
                            paymentType    = OPaymentType.TotalPayment;
                        }
                    }

                    PaidIstallments.Add(installment);
                    if (installment.PaidCapital > 0)
                    {
                        olb -= paidPrincipal;
                    }
                    else
                    {
                        olb -= installment.CapitalRepayment;
                    }

                    beginDate           = installment.ExpectedDate;
                    startNumber         = installment.Number;
                    recalculateSchedule = true;

                    principalEvent   += paidPrincipal;
                    interestEvent    += paymentOfInterest;
                    paidPrincipal     = 0;
                    paymentOfInterest = 0;
                    if (amountPaid == 0)
                    {
                        break;
                    }
                }
                #endregion

                #region payment installmets which is late
                if (installment.ExpectedDate < payDate)
                {
                    OCurrency interestPrepayment = 0;
                    installment.CommissionsUnpaid = 0;
                    installment.FeesUnpaid        = 0;
                    installment.PaidFees          = 0;
                    recalculateSchedule           = true;

                    //interest
                    if (amountPaid == 0)
                    {
                        break;
                    }
                    _methodToRepayInterest.RepayInterest(installment, ref amountPaid, ref paymentOfInterest,
                                                         ref interestPrepayment);

                    interestsToRepay -= paymentOfInterest;

                    if (amountPaid - interestsToRepay > 0 && amountPaid > 0)
                    {
                        if (AmountComparer.Compare(amountPaid, installment.CapitalRepayment - installment.PaidCapital) > 0)
                        {
                            if (amountPaid - interestsToRepay < installment.CapitalRepayment - installment.PaidCapital)
                            {
                                OCurrency paidCapital = installment.PaidCapital;
                                installment.PaidCapital = amountPaid - interestsToRepay + paidCapital;
                                amountPaid    -= installment.PaidCapital - paidCapital;
                                paidPrincipal += installment.PaidCapital - paidCapital;
                            }
                            else
                            {
                                OCurrency principalHasToPay = installment.CapitalRepayment - installment.PaidCapital;
                                installment.PaidCapital = installment.CapitalRepayment;
                                amountPaid    -= principalHasToPay;
                                paidPrincipal += principalHasToPay;
                            }
                        }
                        else
                        {
                            installment.PaidCapital += amountPaid - interestsToRepay;
                            paidPrincipal           += amountPaid - interestsToRepay;
                            amountPaid -= paidPrincipal;
                        }
                    }

                    if (paidPrincipal > 0 || paymentOfInterest > 0)
                    {
                        PaidIstallments.Add(installment);
                    }

                    if (installment.PaidCapital > 0)
                    {
                        olb -= paidPrincipal;
                    }
                    else
                    {
                        olb -= installment.CapitalRepayment;
                    }

                    startNumber = installment.Number;
                    beginDate   = installment.ExpectedDate;

                    principalEvent   += paidPrincipal;
                    interestEvent    += paymentOfInterest;
                    paidPrincipal     = 0;
                    paymentOfInterest = 0;
                    if (amountPaid == 0)
                    {
                        break;
                    }
                }
                #endregion

                #region early payment
                if (installment.ExpectedDate > payDate)
                {
                    OCurrency interestPrepayment = 0;
                    installment.CommissionsUnpaid = 0;
                    installment.FeesUnpaid        = 0;
                    installment.PaidFees          = 0;
                    recalculateSchedule           = true;
                    //interest
                    if (amountPaid == 0)
                    {
                        break;
                    }
                    _methodToRepayInterest.RepayInterest(installment, ref amountPaid, ref paymentOfInterest,
                                                         ref interestPrepayment);

                    interestsToRepay -= paymentOfInterest;

                    if (amountPaid - interestsToRepay > 0 && amountPaid > 0)
                    {
                        if (AmountComparer.Compare(amountPaid, installment.CapitalRepayment - installment.PaidCapital) > 0)
                        {
                            if (installment.CapitalRepayment - installment.PaidCapital == amountPaid)
                            {
                                OCurrency principalHasToPay = installment.CapitalRepayment - installment.PaidCapital;
                                installment.PaidCapital = installment.CapitalRepayment;
                                amountPaid    -= principalHasToPay;
                                paidPrincipal += principalHasToPay;
                            }
                            else
                            {
                                OCurrency paidCapital = installment.PaidCapital;
                                movedPrincipal               = amountPaid - installment.CapitalRepayment + paidCapital;
                                installment.PaidCapital      = amountPaid + paidCapital;
                                installment.CapitalRepayment = amountPaid + paidCapital;
                                paidPrincipal += amountPaid;
                                amountPaid     = 0;
                            }
                        }
                        else
                        {
                            installment.PaidCapital += amountPaid;
                            paidPrincipal           += amountPaid;
                            amountPaid = 0;
                        }
                    }

                    if (paidPrincipal > 0)
                    {
                        startNumber = installment.Number;
                    }

                    if (installment.CapitalRepayment - installment.PaidCapital > 0 &&
                        installment.CapitalRepayment > 0)
                    {
                        startNumber = installment.Number - 1;
                    }

                    beginDate = startNumber > 0 ? installment.ExpectedDate : _contract.StartDate;

                    if (installment.PaidCapital > 0)
                    {
                        olb -= paidPrincipal;
                    }
                    else
                    {
                        if (startNumber == installment.Number)
                        {
                            olb -= installment.CapitalRepayment;
                        }
                    }

                    if (paidPrincipal > 0 || paymentOfInterest > 0)
                    {
                        PaidIstallments.Add(installment);
                    }

                    principalEvent   += paidPrincipal;
                    interestEvent    += paymentOfInterest;
                    paidPrincipal     = 0;
                    paymentOfInterest = 0;

                    if (installment.CapitalRepayment > 0 &&
                        installment.CapitalRepayment - installment.PaidCapital == 0 &&
                        olb > 0)
                    {
                        OCurrency paidInterests = installment.PaidInterests;

                        int daySpan = (installment.ExpectedDate - payDate).Days < 0
                                          ? 0
                                          : (installment.ExpectedDate - payDate).Days;

                        installment.InterestsRepayment = paidInterests.Value +
                                                         Math.Round((olb * _contract.InterestRate / daysInTheYear * daySpan).Value
                                                                    , roundingPoint, MidpointRounding.AwayFromZero);
                    }

                    if (amountPaid == 0)
                    {
                        break;
                    }
                }
                #endregion
            }
            #endregion

            //recalculate installmets after repayment
            if (recalculateSchedule)
            {
                OCurrency o = _contract.CalculateActualOlb();
                bool      isCapitalRemoved     = false;
                bool      isInterestCalculated = false;

                for (int i = 0; i < _contract.NbOfInstallments; i++)
                {
                    installment = _contract.GetInstallment(i);
                    if (installment.Number > startNumber)
                    {
                        OCurrency   remainingPrincipal = 0;
                        Installment priorInstallment   = null;
                        Installment priorInstallment1  = null;

                        if (installment.Number > 1)
                        {
                            priorInstallment = _contract.GetInstallment(installment.Number - 2);
                        }

                        if (installment.Number > 2)
                        {
                            priorInstallment1 = _contract.GetInstallment(installment.Number - 3);
                        }

                        if (priorInstallment != null &&
                            priorInstallment.CapitalRepayment - priorInstallment.PaidCapital > 0 &&
                            priorInstallment.PaidCapital > 0 &&
                            !isCapitalRemoved)
                        {
                            remainingPrincipal = priorInstallment.CapitalRepayment - priorInstallment.PaidCapital;
                            isCapitalRemoved   = true;
                        }

                        if (installment.CapitalRepayment - installment.PaidCapital > 0 &&
                            installment.PaidCapital > 0 &&
                            !isCapitalRemoved)
                        {
                            remainingPrincipal = -1 * installment.PaidCapital.Value;
                            isCapitalRemoved   = true;
                            beginDate          = payDate;
                        }
                        // balloon case /////////////////////
                        if (installment.CapitalRepayment == 0 &&
                            installment.PaidCapital == 0 &&
                            installment.PaidInterests == 0)
                        {
                            beginDate            = installment.Number > 1 ? priorInstallment.ExpectedDate : _contract.StartDate;
                            isInterestCalculated = false;
                            isCapitalRemoved     = true;
                        }
                        /////////////////////////////
                        if (priorInstallment != null &&
                            priorInstallment1 != null &&
                            priorInstallment.InterestHasToPay == 0 &&
                            installment.PaidCapital == 0 &&
                            priorInstallment1.PaidCapital > 0 &&
                            priorInstallment1.CapitalRepayment - priorInstallment1.PaidCapital > 0 &&
                            !isCapitalRemoved)
                        {
                            olb = o;
                            remainingPrincipal = priorInstallment.CapitalRepayment + priorInstallment1.CapitalRepayment -
                                                 priorInstallment1.PaidCapital;
                            isCapitalRemoved = true;
                        }

                        if (installment.InterestsRepayment == 0)
                        {
                            o = olb;
                        }

                        installment.OLB = Math.Round(olb.Value, roundingPoint);

                        if (installment.ExpectedDate > payDate &&
                            installment.PaidInterests > 0 &&
                            olb == actualOlb)
                        {
                            beginDate = installment.Number > 1 ? priorInstallment.ExpectedDate : _contract.StartDate;
                        }

                        DateTime expectedDate = installment.ExpectedDate;
                        //in case very late repayment
                        if (installment.Number == _contract.InstallmentList.Count &&
                            installment.ExpectedDate < payDate &&
                            installment.PaidCapital == 0)
                        {
                            expectedDate = payDate;
                            beginDate    = priorInstallment.ExpectedDate;
                        }

                        int days = (expectedDate - beginDate).Days;

                        if (installment.PaidInterests == installment.InterestsRepayment && days < 0)
                        {
                            days = 0;
                        }

                        OCurrency interestPayment =
                            (o * Convert.ToDecimal(_contract.InterestRate) / daysInTheYear * days).Value;


                        if (olb == actualOlb && !isInterestCalculated)
                        {
                            installment.InterestsRepayment =
                                Math.Round(interestPayment.Value, roundingPoint, MidpointRounding.AwayFromZero);
                            isInterestCalculated = true;
                        }
                        else
                        {
                            installment.InterestsRepayment +=
                                Math.Round(interestPayment.Value, roundingPoint, MidpointRounding.AwayFromZero);
                        }

                        if (installment.PaidCapital == 0 && movedPrincipal > 0)
                        {
                            movedPrincipal -= installment.CapitalRepayment;
                            if (movedPrincipal > 0)
                            {
                                installment.CapitalRepayment = 0;
                            }
                            else
                            {
                                installment.CapitalRepayment = installment.CapitalRepayment -
                                                               (installment.CapitalRepayment + movedPrincipal);
                            }
                        }

                        if (!totalPayment)
                        {
                            olb -= installment.CapitalRepayment + remainingPrincipal;
                        }
                        else
                        {
                            installment.CapitalRepayment = 0;
                        }

                        if (installment.PaidInterests != installment.InterestsRepayment && days >= 0)
                        {
                            beginDate = installment.ExpectedDate;
                        }
                        o = olb;
                    }
                    else
                    {
                        beginDate = payDate >= installment.ExpectedDate ? payDate : installment.ExpectedDate;
                    }
                }
            }

            if (installment != null)
            {
                for (int i = installment.Number; i < _contract.NbOfInstallments; i++)
                {
                    _contract.GetInstallment(i).FeesUnpaid = 0;
                }
            }
        }
 public void TestEqualsWhenThe2NumbersAreReallyEquals()
 {
     Assert.IsTrue(AmountComparer.Equals(123.3456m, 123.3456m));
 }
Example #17
0
    public void Sort()
    {
        AmountComparer ac = new AmountComparer();

        list.Sort(ac);
    }
        public void RepayNextInstallments(ref OCurrency amountPaid, ref OCurrency interestEvent, ref OCurrency interestPrepayment, ref OCurrency principalEvent, ref OCurrency feesEvent, ref OCurrency commissionsEvent)
        {
            if (amountPaid <= 0) return;
            OCurrency totalInterest = 0;
            OCurrency totalPrincipal = 0;
            double nbInterest = 0;
            double nbPrincipal = 0;

            foreach (Installment installment in _contract.InstallmentList)
            {
                if(installment.InterestsRepayment - installment.PaidInterests > 0)
                {
                    totalInterest += (installment.InterestsRepayment - installment.PaidInterests);
                    if (!_contract.GracePeriod.HasValue)
                    {
                        nbInterest += _contract.Product.ExoticProduct.GetExoticInstallment(installment.Number - 1).InterestCoeff.Value;
                    }
                    else if (installment.Number > _contract.GracePeriod.Value)
                    {
                        nbInterest += _contract.Product.ExoticProduct.GetExoticInstallment(installment.Number - 1 - _contract.GracePeriod.Value).InterestCoeff.Value;
                    }							
                }

                if(installment.CapitalRepayment - installment.PaidCapital > 0)
                {
                    totalPrincipal += (installment.CapitalRepayment - installment.PaidCapital);
                    if (!_contract.GracePeriod.HasValue)
                    {
                        nbPrincipal += _contract.Product.ExoticProduct.GetExoticInstallment(installment.Number - 1).PrincipalCoeff;
                    }
                    else if (installment.Number > _contract.GracePeriod.Value)
                    {
                        nbPrincipal += _contract.Product.ExoticProduct.GetExoticInstallment(installment.Number - 1 - _contract.GracePeriod.Value).PrincipalCoeff;
                    }
                }
            }

            if(AmountComparer.Compare(amountPaid,totalInterest) > 0)
            {
                amountPaid -= totalInterest;
                interestEvent += totalInterest;
                interestPrepayment += totalInterest;
                totalInterest = 0;
            }
            else
            {
                totalInterest -= amountPaid;
                interestEvent += amountPaid;
                interestPrepayment += amountPaid;
                amountPaid = 0;
            }

            if(AmountComparer.Compare(amountPaid,totalPrincipal) > 0)
            {
                amountPaid -= totalPrincipal;
                principalEvent += totalPrincipal;
                totalPrincipal = 0;
            }
            else
            {
                totalPrincipal -= amountPaid;
                principalEvent += amountPaid;
                amountPaid = 0;
            }

            if(totalInterest != 0)
                totalInterest = totalInterest / (Convert.ToDecimal(nbInterest) * 10);

            if(totalPrincipal != 0)
                totalPrincipal = totalPrincipal / (Convert.ToDecimal(nbPrincipal) * 10);

            OCurrency interestForLastInstallment = 0;
            OCurrency capitalForLastInstallment = 0;

            for (int i = 0; i < _contract.NbOfInstallments; i++)
            {
                Installment installment = _contract.GetInstallment(i);
                if(!installment.IsRepaid)
                {
                    ExoticInstallment exoticInstallment;

                    if (!_contract.GracePeriod.HasValue)
                    {
                        exoticInstallment = _contract.Product.ExoticProduct.GetExoticInstallment(i);

                        OCurrency tempInterest = Convert.ToDecimal(exoticInstallment.InterestCoeff)*totalInterest*(double)10;
                        OCurrency tempCapital = Convert.ToDecimal(exoticInstallment.PrincipalCoeff)*totalPrincipal*(double)10;

                        installment.InterestsRepayment = Math.Truncate(tempInterest.Value);
                        installment.CapitalRepayment = Math.Truncate(tempCapital.Value);

                        interestForLastInstallment += tempInterest - installment.InterestsRepayment;
                        capitalForLastInstallment += tempCapital - installment.CapitalRepayment;

                    }
                    else if (installment.Number > _contract.GracePeriod.Value)
                    {
                        exoticInstallment = _contract.Product.ExoticProduct.GetExoticInstallment(i - _contract.GracePeriod.Value);

                        OCurrency tempInterest = Convert.ToDecimal(exoticInstallment.InterestCoeff) * totalInterest * (double)10;
                        OCurrency tempCapital = Convert.ToDecimal(exoticInstallment.PrincipalCoeff) * totalPrincipal * (double)10;

                        installment.InterestsRepayment = Math.Truncate(tempInterest.Value);
                        installment.CapitalRepayment = Math.Truncate(tempCapital.Value);

                        interestForLastInstallment += tempInterest - installment.InterestsRepayment;
                        capitalForLastInstallment += tempCapital - installment.CapitalRepayment;
                    }
                    else
                    {
                        OCurrency tempInterest = 0;
                        if (totalInterest != 0)
                            tempInterest = totalPrincipal * Convert.ToDecimal(_contract.InterestRate);

                        installment.InterestsRepayment = Math.Truncate(tempInterest.Value);
                        installment.CapitalRepayment = 0;

                        interestForLastInstallment += tempInterest - installment.InterestsRepayment;
                    }
                }

                _paidInstallments.Add(installment);
            }

            Installment lastInstallment = _contract.GetInstallment(_contract.NbOfInstallments - 1);
            lastInstallment.InterestsRepayment += interestForLastInstallment;
            lastInstallment.CapitalRepayment += capitalForLastInstallment;
            lastInstallment.InterestsRepayment = lastInstallment.InterestsRepayment;
            lastInstallment.CapitalRepayment = lastInstallment.CapitalRepayment;

            lastInstallment.InterestsRepayment = Math.Round(lastInstallment.InterestsRepayment.Value, 0);
            lastInstallment.CapitalRepayment = Math.Round(lastInstallment.CapitalRepayment.Value, 0);
        }
 public void TestEqualsWhenSecondNumberGreaterThanFirstOne()
 {
     Assert.IsFalse(AmountComparer.Equals(242.974321m, 243.0001m));
 }