Exemplo n.º 1
0
        public void Reschedule_Annuity_ChangeInterestRate_PartiallyPaid_Overpaid()
        {
            Loan loan = _GetLoan(_GetAnnuityProduct_RoundingTypeBegin(), 10000, 0.04m, 6, new DateTime(2010, 1, 15));
            loan.Repay(1, new DateTime(2010, 2, 12), 1906, false, true);
            loan.Repay(2, new DateTime(2010, 3, 12), 1908, false, true);
            PaymentMethod paymentMethod = new PaymentMethod(1, "Cash", "", false);
            loan.Repay(3, new DateTime(2010, 4, 5), 1500, false, 0, 0, true, 200, true, false, false, paymentMethod);
            Assert.AreEqual(loan.GetInstallment(0).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(1).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(2).IsPartiallyRepaid, true);

            ReschedulingOptions ro = new ReschedulingOptions
            {
                InterestRate = 0.03m,
                NewInstallments = 0,
                RepaymentDateOffset = 0,
                ChargeInterestDuringShift = true
            };
            loan.Reschedule(ro);

            _AssertInstallment(loan, 2, "2010-04-15", 169, 2643, 6926, 1300, 169);
            _AssertInstallment(loan, 3, "2010-05-17", 128, 1386, 4283, 0, 31);
            _AssertInstallment(loan, 4, "2010-06-15", 87, 1427, 2897, 0, 0);
            _AssertInstallment(loan, 5, "2010-07-15", 44, 1470, 1470, 0, 0);
        }
Exemplo n.º 2
0
        public RescheduleLoanEvent Reschedule(ReschedulingOptions ro, Loan contract, NonWorkingDateSingleton nwdS, ApplicationSettings applicationSettings)
        {
            _contract        = contract;
            _nwdS            = nwdS;
            _generalSettings = applicationSettings;

            switch (contract.Product.LoanType)
            {
            case OLoanTypes.Flat:
                _Reschedule_Flat(ro);
                break;

            case OLoanTypes.DecliningFixedPrincipal:
                _Reschedule_FixedPrincipal(ro);
                break;

            case OLoanTypes.DecliningFixedInstallments:
                _Reschedule_DecliningFixedInstallments(ro);
                break;
            }

            _Reschedule_AdjustOverpaid();

            RescheduleLoanEvent rSe = new RescheduleLoanEvent
            {
                Date         = ro.ReschedulingDate,
                Amount       = contract.CalculateActualOlb(),
                Interest     = contract.GetTotalInterestDue(),
                ClientType   = contract.ClientType,
                BadLoan      = contract.BadLoan,
                NbOfMaturity = ro.NewInstallments,
                DateOffset   = ro.RepaymentDateOffset,
                GracePeriod  = ro.GracePeriod,
                ChargeInterestDuringShift       = ro.ChargeInterestDuringShift,
                ChargeInterestDuringGracePeriod = ro.ChargeInterestDuringGracePeriod,
                InstallmentNumber =
                    contract.GetLastFullyRepaidInstallment() == null
                                                      ? 1
                                                      : contract.GetLastFullyRepaidInstallment().Number + 1
            };

            _contract.CalculateStartDates();
            return(rSe);
        }
Exemplo n.º 3
0
        public RescheduleLoanEvent Reschedule(ReschedulingOptions ro, Loan contract, NonWorkingDateSingleton nwdS, ApplicationSettings applicationSettings)
        {
            _contract = contract;
            _nwdS = nwdS;
            _generalSettings = applicationSettings;

            switch (contract.Product.LoanType)
            {
                case OLoanTypes.Flat:
                    _Reschedule_Flat(ro);
                    break;

                case OLoanTypes.DecliningFixedPrincipal:
                    _Reschedule_FixedPrincipal(ro);
                    break;

                case OLoanTypes.DecliningFixedInstallments:
                    _Reschedule_DecliningFixedInstallments(ro);
                    break;
            }

            _Reschedule_AdjustOverpaid();

            RescheduleLoanEvent rSe = new RescheduleLoanEvent
                                          {
                                              Date = ro.ReschedulingDate,
                                              Amount = contract.CalculateActualOlb(),
                                              Interest = contract.GetTotalInterestDue(),
                                              ClientType = contract.ClientType,
                                              BadLoan = contract.BadLoan,
                                              NbOfMaturity = ro.NewInstallments,
                                              DateOffset = ro.RepaymentDateOffset,
                                              GracePeriod = ro.GracePeriod,
                                              ChargeInterestDuringShift = ro.ChargeInterestDuringShift,
                                              ChargeInterestDuringGracePeriod = ro.ChargeInterestDuringGracePeriod,
                                              InstallmentNumber =
                                                  contract.GetLastFullyRepaidInstallment() == null
                                                      ? 1
                                                      : contract.GetLastFullyRepaidInstallment().Number + 1
                                          };
            _contract.CalculateStartDates();
            return rSe;
        }
Exemplo n.º 4
0
        private DateTime[] _Reschedule_AdjustDates(ReschedulingOptions ro)
        {
            DateTime[] retval  = new DateTime[2];
            DateTime   oldDate = DateTime.MinValue;
            DateTime   newDate = DateTime.MinValue;
            bool       first   = false;
            int        number  = 0;

            for (int i = 0; i < _contract.InstallmentList.Count; i++)
            {
                Installment installment = _contract.GetInstallment(i);
                if (installment.IsRepaid)
                {
                    continue;
                }
                if (!first)
                {
                    first   = true;
                    oldDate = installment.ExpectedDate;
                    newDate = installment.ExpectedDate;
                    if (0 == ro.RepaymentDateOffset)
                    {
                        break;
                    }

                    newDate = newDate.AddDays(ro.RepaymentDateOffset);

                    DateTime actualNewDate = _nwdS.GetTheNearestValidDate(newDate,
                                                                          _generalSettings.IsIncrementalDuringDayOff,
                                                                          _generalSettings.DoNotSkipNonWorkingDays, true);
                    installment.ExpectedDate = actualNewDate;
                }
                installment.ExpectedDate = _contract.CalculateInstallmentDate(newDate, number);
                number++;
            }
            retval[0] = oldDate;
            retval[1] = newDate;
            return(retval);
        }
Exemplo n.º 5
0
        private void _Reschedule_FixedPrincipal(ReschedulingOptions ro)
        {
            _Reschedule_ExtendMaturity(ro.NewInstallments);
            int roundDecimals = _contract.UseCents ? 2 : 0;
            Installment firstUnpaidInstallment = _contract.GetFirstUnpaidInstallment();
            OCurrency paidCapital = 0;
            if (firstUnpaidInstallment.IsPartiallyRepaid && firstUnpaidInstallment.PaidCapital != 0 && ro.GracePeriod > 0)
            {
                paidCapital = firstUnpaidInstallment.PaidCapital;
                firstUnpaidInstallment.CapitalRepayment = firstUnpaidInstallment.PaidCapital;
                firstUnpaidInstallment = _contract.GetInstallment(firstUnpaidInstallment.Number);
            }

            int firstUnpaidInstallmentNumber = firstUnpaidInstallment.Number;
            int toNext = firstUnpaidInstallment.IsPartiallyRepaid && ro.GracePeriod > 0 ? 1 : 0;

            if (firstUnpaidInstallment.IsPartiallyRepaid || ro.NewInstallments > 0 || ro.GracePeriod > 0)
            {
                OCurrency unpaidAmount = 0;
                foreach (Installment installment in _contract.InstallmentList)
                {
                    unpaidAmount += installment.IsRepaid ? 0 : installment.CapitalRepayment - installment.PaidCapital;
                }

                unpaidAmount += paidCapital;
                int nbOfUnpaid = _contract.InstallmentList.Count - firstUnpaidInstallmentNumber + 1 - toNext;
                double monthly = Math.Round(Convert.ToDouble(unpaidAmount.Value / (nbOfUnpaid - ro.GracePeriod)),
                                            roundDecimals,
                                            MidpointRounding.AwayFromZero);

                for (int i = firstUnpaidInstallment.Number - 1; i < _contract.InstallmentList.Count; i++)
                {
                    Installment installment = _contract.GetInstallment(i);

                    if (installment.Number > ro.GracePeriod + firstUnpaidInstallment.Number - 1 + toNext)
                    {
                        installment.CapitalRepayment = Convert.ToDecimal(monthly);
                    }
                    else
                    {
                        installment.CapitalRepayment = 0;
                    }
                }

                Installment installmentOfCorrection = _contract.GetInstallment(firstUnpaidInstallmentNumber + ro.GracePeriod - 1 + toNext);

                installmentOfCorrection.CapitalRepayment += installmentOfCorrection.PaidCapital;
                double diff = Convert.ToDouble(unpaidAmount.Value) - monthly * (nbOfUnpaid - ro.GracePeriod);

                if (diff != 0)
                    installmentOfCorrection.CapitalRepayment += Convert.ToDecimal(diff);

                OCurrency olb = firstUnpaidInstallment.OLB + paidCapital;
                for (int i = firstUnpaidInstallment.Number - 1; i < _contract.InstallmentList.Count; i++)
                {
                    Installment installment = _contract.GetInstallment(i);
                    installment.OLB = olb;
                    olb -= installment.CapitalRepayment;
                }
            }

            DateTime[] dates = _Reschedule_AdjustDates(ro);
            bool firstNonRepaid = true;

            if(firstUnpaidInstallment.IsPartiallyRepaid && ro.GracePeriod > 0)
            {
                firstUnpaidInstallment.InterestsRepayment = firstUnpaidInstallment.PaidInterests;
                firstUnpaidInstallment.CapitalRepayment = firstUnpaidInstallment.PaidCapital;
                firstNonRepaid = false;
            }
            //interest calculation
            foreach (Installment installment in _contract.InstallmentList)
            {
                if (installment.IsRepaid) continue;
                if (firstNonRepaid)
                {
                    firstNonRepaid = false;

                    if (ro.ChargeInterestDuringShift
                        || _contract.InterestRate != ro.InterestRate
                        || ro.NewInstallments > 0
                        || ro.GracePeriod > 0)
                    {
                        TimeSpan oldSpan;
                        TimeSpan newSpan;

                        if ((installment.Number > ro.GracePeriod + firstUnpaidInstallment.Number - 1 + toNext) || (ro.ChargeInterestDuringGracePeriod))
                        {
                            if (1 == installment.Number)
                            {
                                DateTime endDate =
                                    _contract.StartDate.AddMonths(_contract.InstallmentType.NbOfMonths).AddDays(_contract.InstallmentType.NbOfDays);
                                endDate = _nwdS.GetTheNearestValidDate(endDate,
                                                                       _generalSettings.IsIncrementalDuringDayOff,
                                                                       _generalSettings.DoNotSkipNonWorkingDays, true);

                                newSpan = (ro.ChargeInterestDuringShift ? installment.ExpectedDate : dates[0]) -
                                          _contract.StartDate;
                                oldSpan = endDate - _contract.StartDate;
                            }
                            else
                            {
                                DateTime startDate = _contract.GetInstallment(installment.Number - 2).ExpectedDate;
                                oldSpan = dates[0] - startDate;
                                newSpan = (ro.ChargeInterestDuringShift ? dates[1] : dates[0]) - startDate;
                            }

                            OCurrency amount = installment.OLB - installment.PaidCapital;
                            decimal interest = (amount.Value * newSpan.Days) * ro.InterestRate / oldSpan.Days;
                            interest = Math.Round(interest, roundDecimals, MidpointRounding.AwayFromZero);
                            installment.InterestsRepayment = Convert.ToDecimal(interest);
                        }
                        else
                        {
                            installment.InterestsRepayment = 0;
                        }
                    }
                }
                else
                {
                    if (_contract.InterestRate != ro.InterestRate
                        || firstUnpaidInstallment.IsPartiallyRepaid
                        || ro.NewInstallments > 0
                        || ro.GracePeriod > 0)
                    {
                        if ((installment.Number > ro.GracePeriod + firstUnpaidInstallment.Number - 1 + toNext) || (ro.ChargeInterestDuringGracePeriod))
                        {
                            decimal interest = installment.OLB.Value * ro.InterestRate;
                            interest = Math.Round(interest, roundDecimals, MidpointRounding.AwayFromZero);
                            installment.InterestsRepayment = Convert.ToDecimal(interest);
                        }
                        else
                        {
                            installment.InterestsRepayment = 0;
                        }
                    }
                }
            }
        }
Exemplo n.º 6
0
        private DateTime[] _Reschedule_AdjustDates(ReschedulingOptions ro)
        {
            DateTime[] retval = new DateTime[2];
            DateTime oldDate = DateTime.MinValue;
            DateTime newDate = DateTime.MinValue;
            bool first = false;
            int number = 0;
            for (int i = 0; i < _contract.InstallmentList.Count; i++)
            {
                Installment installment = _contract.GetInstallment(i);
                if (installment.IsRepaid) continue;
                if (!first)
                {
                    first = true;
                    oldDate = installment.ExpectedDate;
                    newDate = installment.ExpectedDate;
                    if (0 == ro.RepaymentDateOffset)
                        break;

                    newDate = newDate.AddDays(ro.RepaymentDateOffset);

                    DateTime actualNewDate = _nwdS.GetTheNearestValidDate(newDate,
                                                                          _generalSettings.IsIncrementalDuringDayOff,
                                                                          _generalSettings.DoNotSkipNonWorkingDays, true);
                    installment.ExpectedDate = actualNewDate;
                }
                installment.ExpectedDate = _contract.CalculateInstallmentDate(newDate, number);
                number++;
            }
            retval[0] = oldDate;
            retval[1] = newDate;
            return retval;
        }
Exemplo n.º 7
0
        public void Reschedule_Flat_ShiftDate_UseCents()
        {
            Loan loan = _GetLoan(_GetFlatProduct_WithCents(), 10000, 0.04m, 6, new DateTime(2009, 12, 24));
            loan.Repay(1, new DateTime(2010, 1, 25), 2066.67m, false, true);
            loan.Repay(2, new DateTime(2010, 2, 24), 2066.67m, false, true);
            Assert.AreEqual(loan.GetInstallment(0).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(1).IsRepaid, true);

            ReschedulingOptions ro = new ReschedulingOptions
            {
                InterestRate = 0.04m,
                NewInstallments = 0,
                RepaymentDateOffset = 38,
                ChargeInterestDuringShift = true
            };
            loan.Reschedule(ro);

            _AssertInstallment(loan, 2, "2010-05-03", 942.86m, 1666.67m);
            _AssertInstallment(loan, 3, "2010-06-01", 400, 1666.66m);
            _AssertInstallment(loan, 4, "2010-07-01", 400, 1666.67m);
            _AssertInstallment(loan, 5, "2010-08-02", 400, 1666.66m);
        }
Exemplo n.º 8
0
        public void Reschedule_Flat_ShiftDate_ChangeInterestRate_PartiallyPaid()
        {
            Loan loan = _GetLoan(_GetFlatProduct(), 10000, 0.04m, 6, new DateTime(2009, 12, 22));
            loan.Repay(1, new DateTime(2010, 1, 22), 2067, false, true);
            loan.Repay(2, new DateTime(2010, 2, 22), 2067, false, true);
            PaymentMethod paymentMethod = new PaymentMethod(1, "Cash", "", false);
            loan.Repay(3, new DateTime(2010, 3, 5), 1500, false, 0, 0, true, 200, true, false, false, paymentMethod);
            Assert.AreEqual(loan.GetInstallment(0).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(1).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(2).IsPartiallyRepaid, true);

            ReschedulingOptions ro = new ReschedulingOptions
            {
                InterestRate = 0.03m,
                NewInstallments = 0,
                RepaymentDateOffset = 40,
                ChargeInterestDuringShift = true
            };
            loan.Reschedule(ro);

            _AssertInstallment(loan, 2, "2010-05-03", 729, 2640, 6666);
            _AssertInstallment(loan, 3, "2010-06-01", 300, 1342, 4026);
            _AssertInstallment(loan, 4, "2010-07-01", 300, 1342, 2684);
            _AssertInstallment(loan, 5, "2010-08-02", 300, 1342, 1342);
        }
Exemplo n.º 9
0
        public void Reschedule_FixedPrincipal_ShiftDate_PartiallyPaid_UseCents()
        {
            Loan loan = _GetLoan(_GetFixedPrincipalProduct_WithCents(), 10000, 0.04m, 6, new DateTime(2010, 1, 11));
            loan.Repay(1, new DateTime(2010, 2, 11), 2066.67m, false, true);
            loan.Repay(2, new DateTime(2010, 3, 11), 2000.00m, false, true);
            PaymentMethod paymentMethod = new PaymentMethod(1, "Cash", "", false);
            loan.Repay(3, new DateTime(2010, 4, 5), 1500.00m, false, 0, 0, true, 200, true, false, false, paymentMethod);
            Assert.AreEqual(loan.GetInstallment(0).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(1).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(2).IsPartiallyRepaid, true);

            ReschedulingOptions ro = new ReschedulingOptions
            {
                InterestRate = 0.04m,
                NewInstallments = 0,
                RepaymentDateOffset = 19,
                ChargeInterestDuringShift = true
            };
            loan.Reschedule(ro);

            _AssertInstallment(loan, 2, "2010-05-03", 342.12m, 2641.65m, 6666.66m);
            _AssertInstallment(loan, 3, "2010-06-01", 161.00m, 1341.67m, 4025.01m);
            _AssertInstallment(loan, 4, "2010-07-01", 107.33m, 1341.67m, 2683.34m);
            _AssertInstallment(loan, 5, "2010-08-02", 53.67m, 1341.67m, 1341.67m);
        }
Exemplo n.º 10
0
        public void Test_ProvisionRescheduledLoanProcessing()
        {
            Loan myContract = _SetContract(1000, 0.03m, OLoanTypes.Flat, new NonRepaymentPenalties(0, 0, 0.003, 0), false, 1, new DateTime(2010, 6, 6), 6);
            OpenCBS.CoreDomain.Contracts.Loans.LoanRepayment.Repayment.RepayLateInstallments.CalculateInstallments rLI =
                _SetRepaymentOptions(myContract, false);

            ProvisionTable provisionTable = ProvisionTable.GetInstance(new User());
            provisionTable.ProvisioningRates = new List<ProvisioningRate>();
            provisionTable.Add(new ProvisioningRate { Number = 1, NbOfDaysMin = 0, NbOfDaysMax = 0, Rate = 0.5 });
            provisionTable.Add(new ProvisioningRate { Number = 2, NbOfDaysMin = 1, NbOfDaysMax = 30, Rate = 1 });
            provisionTable.Add(new ProvisioningRate { Number = 3, NbOfDaysMin = 31, NbOfDaysMax = 60, Rate = 1.5 });
            provisionTable.Add(new ProvisioningRate { Number = 3, NbOfDaysMin = 60, NbOfDaysMax = 999, Rate = 2 });
            provisionTable.Add(new ProvisioningRate { Number = 4, NbOfDaysMin = -1, NbOfDaysMax = -1, Rate = 1 });

            Assert.AreEqual(new DateTime(2010, 7, 6), myContract.GetInstallment(0).ExpectedDate);
            Assert.AreEqual(new DateTime(2010, 8, 6), myContract.GetInstallment(1).ExpectedDate);
            myContract.Repay(1, new DateTime(2010, 8, 6), 100, false, false);

            ReschedulingOptions ro = new ReschedulingOptions
            {
                InterestRate = 0.04m,
                NewInstallments = 2,
                RepaymentDateOffset = 0,
                ChargeInterestDuringShift = true,
                ReschedulingDate = new DateTime(2010, 12, 1)
            };
            myContract.Reschedule(ro);
            myContract.Rescheduled = true;

            rLI.CalculateNewInstallmentsWithLateFees(new DateTime(2010, 10, 1));

            ProvisionEvent e = myContract.GetProvisionEvent(new DateTime(2010, 10, 1), provisionTable);
            Assert.AreEqual(e.Code, "LLPE");
            Assert.AreEqual(e.Amount, 1000);
            myContract.Events.Add(e);
        }
Exemplo n.º 11
0
 public Loan FakeReschedule(Loan contract, DateTime date, int nbOfMaturity, int dateOffset, bool pAccruedInterestDuringTheGracePeriod, decimal pNewInterestRate, int gracePeriod, bool chargeInterestDuringGracePeriod)
 {
     Loan fakeContract = contract.Copy();
     ReschedulingOptions ro = new ReschedulingOptions
                                  {
                                      ChargeInterestDuringShift = pAccruedInterestDuringTheGracePeriod,
                                      NewInstallments = nbOfMaturity,
                                      InterestRate = pNewInterestRate,
                                      RepaymentDateOffset = dateOffset,
                                      ReschedulingDate = date,
                                      GracePeriod = gracePeriod,
                                      ChargeInterestDuringGracePeriod = chargeInterestDuringGracePeriod
                                  };
     fakeContract.Reschedule(ro);
     return fakeContract;
 }
Exemplo n.º 12
0
        public Loan Reschedule(Loan pContract, DateTime pDate, int pNbOfMaturity, int dateOffset,
            bool pAccruedInterestDuringTheGracePeriod, decimal pNewInterestRate, int gracePeriod, bool chargeInterestDuringGracePeriod)
        {
            using (SqlConnection conn = _loanManager.GetConnection())
            using (SqlTransaction sqlTransac = conn.BeginTransaction())
            {
                try
                {
                    Loan copyOfLoan = pContract.Copy();

                    //create the rescheduling loan event
                    ReschedulingOptions ro = new ReschedulingOptions
                                                 {
                                                     ReschedulingDate = pDate,
                                                     ChargeInterestDuringShift = pAccruedInterestDuringTheGracePeriod,
                                                     InterestRate = pNewInterestRate,
                                                     RepaymentDateOffset = dateOffset,
                                                     NewInstallments = pNbOfMaturity,
                                                     GracePeriod = gracePeriod,
                                                     ChargeInterestDuringGracePeriod = chargeInterestDuringGracePeriod
                                                 };
                    RescheduleLoanEvent rescheduleLoanEvent = pContract.Reschedule(ro);
                    rescheduleLoanEvent.User = _user;

                    //insert into table ReschedulingOfALoanEvents
                    _ePs.FireEvent(rescheduleLoanEvent, pContract, sqlTransac);
                    OverdueEvent overdueEvent = pContract.AddRecheduleTransformationEvent(pDate);
                    if (overdueEvent != null) _ePs.FireEvent(overdueEvent, pContract, sqlTransac);

                    ArchiveInstallments(copyOfLoan, rescheduleLoanEvent, sqlTransac);

                    //delete all the old installments of the table Installments
                    _instalmentManager.DeleteInstallments(pContract.Id, sqlTransac);

                    //insert all the new installments in the table Installments
                    _instalmentManager.AddInstallments(pContract.InstallmentList, pContract.Id, sqlTransac);

                    _loanManager.UpdateLoanToRescheduled(pNewInterestRate, pNbOfMaturity, pContract, sqlTransac);

                    sqlTransac.Commit();
                    return pContract;
                }
                catch (Exception ex)
                {
                    sqlTransac.Rollback();
                    throw ex;
                }
            }
        }
Exemplo n.º 13
0
        private void _Reschedule_FixedPrincipal(ReschedulingOptions ro)
        {
            _Reschedule_ExtendMaturity(ro.NewInstallments);
            int         roundDecimals          = _contract.UseCents ? 2 : 0;
            Installment firstUnpaidInstallment = _contract.GetFirstUnpaidInstallment();
            OCurrency   paidCapital            = 0;

            if (firstUnpaidInstallment.IsPartiallyRepaid && firstUnpaidInstallment.PaidCapital != 0 && ro.GracePeriod > 0)
            {
                paidCapital = firstUnpaidInstallment.PaidCapital;
                firstUnpaidInstallment.CapitalRepayment = firstUnpaidInstallment.PaidCapital;
                firstUnpaidInstallment = _contract.GetInstallment(firstUnpaidInstallment.Number);
            }

            int firstUnpaidInstallmentNumber = firstUnpaidInstallment.Number;
            int toNext = firstUnpaidInstallment.IsPartiallyRepaid && ro.GracePeriod > 0 ? 1 : 0;

            if (firstUnpaidInstallment.IsPartiallyRepaid || ro.NewInstallments > 0 || ro.GracePeriod > 0)
            {
                OCurrency unpaidAmount = 0;
                foreach (Installment installment in _contract.InstallmentList)
                {
                    unpaidAmount += installment.IsRepaid ? 0 : installment.CapitalRepayment - installment.PaidCapital;
                }

                unpaidAmount += paidCapital;
                int    nbOfUnpaid = _contract.InstallmentList.Count - firstUnpaidInstallmentNumber + 1 - toNext;
                double monthly    = Math.Round(Convert.ToDouble(unpaidAmount.Value / (nbOfUnpaid - ro.GracePeriod)),
                                               roundDecimals,
                                               MidpointRounding.AwayFromZero);

                for (int i = firstUnpaidInstallment.Number - 1; i < _contract.InstallmentList.Count; i++)
                {
                    Installment installment = _contract.GetInstallment(i);

                    if (installment.Number > ro.GracePeriod + firstUnpaidInstallment.Number - 1 + toNext)
                    {
                        installment.CapitalRepayment = Convert.ToDecimal(monthly);
                    }
                    else
                    {
                        installment.CapitalRepayment = 0;
                    }
                }

                Installment installmentOfCorrection = _contract.GetInstallment(firstUnpaidInstallmentNumber + ro.GracePeriod - 1 + toNext);

                installmentOfCorrection.CapitalRepayment += installmentOfCorrection.PaidCapital;
                double diff = Convert.ToDouble(unpaidAmount.Value) - monthly * (nbOfUnpaid - ro.GracePeriod);

                if (diff != 0)
                {
                    installmentOfCorrection.CapitalRepayment += Convert.ToDecimal(diff);
                }

                OCurrency olb = firstUnpaidInstallment.OLB + paidCapital;
                for (int i = firstUnpaidInstallment.Number - 1; i < _contract.InstallmentList.Count; i++)
                {
                    Installment installment = _contract.GetInstallment(i);
                    installment.OLB = olb;
                    olb            -= installment.CapitalRepayment;
                }
            }

            DateTime[] dates          = _Reschedule_AdjustDates(ro);
            bool       firstNonRepaid = true;

            if (firstUnpaidInstallment.IsPartiallyRepaid && ro.GracePeriod > 0)
            {
                firstUnpaidInstallment.InterestsRepayment = firstUnpaidInstallment.PaidInterests;
                firstUnpaidInstallment.CapitalRepayment   = firstUnpaidInstallment.PaidCapital;
                firstNonRepaid = false;
            }
            //interest calculation
            foreach (Installment installment in _contract.InstallmentList)
            {
                if (installment.IsRepaid)
                {
                    continue;
                }
                if (firstNonRepaid)
                {
                    firstNonRepaid = false;

                    if (ro.ChargeInterestDuringShift ||
                        _contract.InterestRate != ro.InterestRate ||
                        ro.NewInstallments > 0 ||
                        ro.GracePeriod > 0)
                    {
                        TimeSpan oldSpan;
                        TimeSpan newSpan;

                        if ((installment.Number > ro.GracePeriod + firstUnpaidInstallment.Number - 1 + toNext) || (ro.ChargeInterestDuringGracePeriod))
                        {
                            if (1 == installment.Number)
                            {
                                DateTime endDate =
                                    _contract.StartDate.AddMonths(_contract.InstallmentType.NbOfMonths).AddDays(_contract.InstallmentType.NbOfDays);
                                endDate = _nwdS.GetTheNearestValidDate(endDate,
                                                                       _generalSettings.IsIncrementalDuringDayOff,
                                                                       _generalSettings.DoNotSkipNonWorkingDays, true);

                                newSpan = (ro.ChargeInterestDuringShift ? installment.ExpectedDate : dates[0]) -
                                          _contract.StartDate;
                                oldSpan = endDate - _contract.StartDate;
                            }
                            else
                            {
                                DateTime startDate = _contract.GetInstallment(installment.Number - 2).ExpectedDate;
                                oldSpan = dates[0] - startDate;
                                newSpan = (ro.ChargeInterestDuringShift ? dates[1] : dates[0]) - startDate;
                            }

                            OCurrency amount   = installment.OLB - installment.PaidCapital;
                            decimal   interest = (amount.Value * newSpan.Days) * ro.InterestRate / oldSpan.Days;
                            interest = Math.Round(interest, roundDecimals, MidpointRounding.AwayFromZero);
                            installment.InterestsRepayment = Convert.ToDecimal(interest);
                        }
                        else
                        {
                            installment.InterestsRepayment = 0;
                        }
                    }
                }
                else
                {
                    if (_contract.InterestRate != ro.InterestRate ||
                        firstUnpaidInstallment.IsPartiallyRepaid ||
                        ro.NewInstallments > 0 ||
                        ro.GracePeriod > 0)
                    {
                        if ((installment.Number > ro.GracePeriod + firstUnpaidInstallment.Number - 1 + toNext) || (ro.ChargeInterestDuringGracePeriod))
                        {
                            decimal interest = installment.OLB.Value * ro.InterestRate;
                            interest = Math.Round(interest, roundDecimals, MidpointRounding.AwayFromZero);
                            installment.InterestsRepayment = Convert.ToDecimal(interest);
                        }
                        else
                        {
                            installment.InterestsRepayment = 0;
                        }
                    }
                }
            }
        }
Exemplo n.º 14
0
        private void _Reschedule_Flat(ReschedulingOptions ro)
        {
            _Reschedule_ExtendMaturity(ro.NewInstallments);
            DateTime[] dates = _Reschedule_AdjustDates(ro);

            int         roundDecimals          = _contract.UseCents ? 2 : 0;
            bool        firstNonRepaid         = true;
            Installment firstUnpaidInstallment = _contract.GetFirstUnpaidInstallment();
            int         moveToNext             = 0;

            foreach (Installment installment in _contract.InstallmentList)
            {
                if (installment.IsRepaid)
                {
                    continue;
                }

                if (firstNonRepaid)
                {
                    firstNonRepaid = false;
                    if (ro.ChargeInterestDuringShift ||
                        _contract.InterestRate != ro.InterestRate ||
                        ro.NewInstallments > 0 ||
                        ro.GracePeriod > 0)
                    {
                        TimeSpan oldSpan;
                        TimeSpan newSpan;
                        if (1 == installment.Number)
                        {
                            DateTime endDate =
                                _contract.StartDate.AddMonths(_contract.InstallmentType.NbOfMonths).AddDays(
                                    _contract.InstallmentType.NbOfDays);
                            endDate = _nwdS.GetTheNearestValidDate(endDate, _generalSettings.IsIncrementalDuringDayOff,
                                                                   _generalSettings.DoNotSkipNonWorkingDays, true);
                            newSpan = (ro.ChargeInterestDuringShift ? installment.ExpectedDate : dates[0]) - _contract.StartDate;
                            oldSpan = endDate - _contract.StartDate;
                        }
                        else
                        {
                            DateTime startDate = _contract.GetInstallment(installment.Number - 2).ExpectedDate;
                            oldSpan = dates[0] - startDate;
                            newSpan = (ro.ChargeInterestDuringShift ? dates[1] : dates[0]) - startDate;
                        }

                        if (ro.GracePeriod > 0 && installment.IsPartiallyRepaid)
                        {
                            installment.InterestsRepayment = installment.PaidInterests;
                            moveToNext = 1;
                        }
                        else
                        {
                            if (installment.Number >= ro.GracePeriod + firstUnpaidInstallment.Number)
                            {
                                OCurrency interest = _contract.Amount * newSpan.Days * ro.InterestRate / oldSpan.Days;
                                interest = Math.Round(interest.Value, roundDecimals, MidpointRounding.AwayFromZero);
                                installment.InterestsRepayment = interest;
                            }
                            else
                            {
                                if (ro.ChargeInterestDuringGracePeriod)
                                {
                                    OCurrency interest = _contract.Amount * newSpan.Days * ro.InterestRate / oldSpan.Days;
                                    interest = Math.Round(interest.Value, roundDecimals, MidpointRounding.AwayFromZero);
                                    installment.InterestsRepayment = interest;
                                }
                                else
                                {
                                    installment.InterestsRepayment = 0;
                                }
                            }
                        }
                    }
                }
                else
                {
                    if (ro.GracePeriod > 0 && installment.IsPartiallyRepaid)
                    {
                        installment.InterestsRepayment = installment.PaidInterests;
                        moveToNext = 1;
                    }
                    else
                    {
                        if (installment.Number > ro.GracePeriod + firstUnpaidInstallment.Number - 1 + moveToNext)
                        {
                            OCurrency interest = _contract.Amount * ro.InterestRate;
                            interest = Math.Round(interest.Value, roundDecimals, MidpointRounding.AwayFromZero);
                            installment.InterestsRepayment = interest;
                        }
                        else
                        {
                            if (ro.ChargeInterestDuringGracePeriod)
                            {
                                OCurrency interest = _contract.Amount * ro.InterestRate;
                                interest = Math.Round(interest.Value, roundDecimals, MidpointRounding.AwayFromZero);
                                installment.InterestsRepayment = interest;
                            }
                            else
                            {
                                installment.InterestsRepayment = 0;
                            }
                        }
                    }
                }
            }

            if (null == firstUnpaidInstallment)
            {
                return;
            }

            if (!firstUnpaidInstallment.IsPartiallyRepaid && 0 == ro.NewInstallments && 0 == ro.GracePeriod)
            {
                return;
            }

            OCurrency unpaidAmount = 0;

            foreach (Installment installment in _contract.InstallmentList)
            {
                unpaidAmount += installment.CapitalRepayment - installment.PaidCapital;
            }

            int nbOfUnpaid = _contract.InstallmentList.Count - firstUnpaidInstallment.Number + 1;

            int nextNumber = 0;

            if (firstUnpaidInstallment.IsPartiallyRepaid && ro.GracePeriod > 0)
            {
                nextNumber = 1;
            }

            double monthly = Math.Round(
                Convert.ToDouble(unpaidAmount.Value / (nbOfUnpaid - ro.GracePeriod - nextNumber)), roundDecimals,
                MidpointRounding.AwayFromZero);

            for (int i = firstUnpaidInstallment.Number - 1; i < _contract.InstallmentList.Count; i++)
            {
                Installment installment = _contract.GetInstallment(i);
                if (installment.Number > ro.GracePeriod + firstUnpaidInstallment.Number - 1 + nextNumber)
                {
                    installment.CapitalRepayment = Convert.ToDecimal(monthly);
                }
                else
                {
                    installment.CapitalRepayment = 0;
                }
            }

            firstUnpaidInstallment.CapitalRepayment += firstUnpaidInstallment.PaidCapital;

            double diff = Convert.ToDouble(unpaidAmount.Value) - monthly * (nbOfUnpaid - ro.GracePeriod - nextNumber);

            if (diff != 0)
            {
                if (nextNumber != 1)
                {
                    if (ro.GracePeriod > 0)
                    {
                        _contract.GetInstallment(firstUnpaidInstallment.Number + ro.GracePeriod).CapitalRepayment += Convert.ToDecimal(diff);
                    }
                    else
                    {
                        firstUnpaidInstallment.CapitalRepayment += Convert.ToDecimal(diff);
                    }
                }
                else
                {
                    _contract.GetInstallment(firstUnpaidInstallment.Number + ro.GracePeriod).CapitalRepayment += Convert.ToDecimal(diff);
                }
            }

            OCurrency olb = firstUnpaidInstallment.OLB;

            for (int i = firstUnpaidInstallment.Number - 1; i < _contract.InstallmentList.Count; i++)
            {
                Installment installment = _contract.GetInstallment(i);
                installment.OLB = olb;
                olb            -= installment.CapitalRepayment;
            }
        }
Exemplo n.º 15
0
        public void Test_RescheduleLateLoanProcessing()
        {
            Loan myContract = _SetContract(1000, 0.03m, OLoanTypes.Flat, new NonRepaymentPenalties(0, 0, 0.003, 0), false, 1, new DateTime(2010, 6, 6), 6);
            OpenCBS.CoreDomain.Contracts.Loans.LoanRepayment.Repayment.RepayLateInstallments.CalculateInstallments rLI =
                _SetRepaymentOptions(myContract, false);

            Assert.AreEqual(new DateTime(2010, 7, 6), myContract.GetInstallment(0).ExpectedDate);
            Assert.AreEqual(new DateTime(2010, 8, 6), myContract.GetInstallment(1).ExpectedDate);

            myContract.Repay(1, new DateTime(2010, 7, 6), 230, false, true);
            myContract.Repay(2, new DateTime(2010, 8, 6), 230, false, true);

            rLI.CalculateNewInstallmentsWithLateFees(new DateTime(2010, 10, 1));
            ReschedulingOptions ro = new ReschedulingOptions
            {
                InterestRate = 0.04m,
                NewInstallments = 2,
                RepaymentDateOffset = 0,
                ChargeInterestDuringShift = true,
                ReschedulingDate = new DateTime(2010, 10, 1)
            };
            myContract.Reschedule(ro);
            myContract.AddRecheduleTransformationEvent(ro.ReschedulingDate);
            List<OverdueEvent> list = myContract.Events.GetOverdueEvents();
            Assert.AreEqual(list[0].Code, "LLRL");

            // good loan to the bad loan
            OverdueEvent e = myContract.GetOverdueEvent(new DateTime(2010, 10, 1));
            Assert.AreEqual(e.Code, "GLLL");
            e = myContract.GetOverdueEvent(new DateTime(2010, 10, 20));
            Assert.AreEqual(e, null);
            myContract.Repay(1, new DateTime(2010, 10, 20), 500, false, true);
            //bad loan to the late loan
            e = myContract.GetOverdueEvent(new DateTime(2010, 10, 21));

            Assert.AreEqual(e.Code, "LLGL");
            myContract.Repay(1, new DateTime(2010, 11, 6), 500, false, true);
            //late loan to the good loan
        }
Exemplo n.º 16
0
        public void Reschedule_FixedPrincipal_ExtendMaturity_ShiftDate_ChangeInterestRate_PartiallyPaid_UseCents()
        {
            Loan loan = _GetLoan(_GetFixedPrincipalProduct_WithCents(), 10000, 0.04m, 6, new DateTime(2010, 1, 11));
            loan.Repay(1, new DateTime(2010, 2, 11), 2066.67m, false, true);
            loan.Repay(2, new DateTime(2010, 3, 11), 2000.00m, false, true);
            PaymentMethod paymentMethod = new PaymentMethod(1, "Cash", "", false);
            loan.Repay(3, new DateTime(2010, 4, 5), 1500.00m, false, 0, 0, true, 200, true, false, false, paymentMethod);
            Assert.AreEqual(loan.GetInstallment(0).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(1).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(2).IsPartiallyRepaid, true);

            ReschedulingOptions ro = new ReschedulingOptions
            {
                InterestRate = 0.03m,
                NewInstallments = 2,
                RepaymentDateOffset = 13,
                ChargeInterestDuringShift = true
            };
            loan.Reschedule(ro);

            _AssertInstallment(loan, 2, "2010-04-26", 226.41m, 2194.46m, 6666.66m, 1300.00m, 200.00m);
            _AssertInstallment(loan, 3, "2010-05-25", 134.17m, 894.44m, 4472.20m, 0, 0);
            _AssertInstallment(loan, 4, "2010-06-25", 107.33m, 894.44m, 3577.76m, 0, 0);
            _AssertInstallment(loan, 5, "2010-07-26", 80.50m, 894.44m, 2683.32m, 0, 0);
            _AssertInstallment(loan, 6, "2010-08-25", 53.67m, 894.44m, 1788.88m, 0, 0);
            _AssertInstallment(loan, 7, "2010-09-27", 26.83m, 894.44m, 894.44m, 0, 0);
        }
Exemplo n.º 17
0
        public void Reschedule_Annuity_ShiftDate_ChangeInterestRate()
        {
            Loan loan = _GetLoan(_GetAnnuityProduct_RoundingTypeBegin(), 10000, 0.04m, 6, new DateTime(2010, 1, 15));
            loan.Repay(1, new DateTime(2010, 2, 15), 1906, false, true);
            loan.Repay(2, new DateTime(2010, 3, 15), 1908, false, true);
            Assert.AreEqual(loan.GetInstallment(0).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(1).IsRepaid, true);

            ReschedulingOptions ro = new ReschedulingOptions
            {
                InterestRate = 0.03m,
                NewInstallments = 0,
                RepaymentDateOffset = 16,
                ChargeInterestDuringShift = true
            };
            loan.Reschedule(ro);

            _AssertInstallment(loan, 2, "2010-05-03", 315, 1656);
            _AssertInstallment(loan, 3, "2010-06-01", 158, 1705);
            _AssertInstallment(loan, 4, "2010-07-01", 107, 1756);
            _AssertInstallment(loan, 5, "2010-08-02", 54, 1809);
        }
Exemplo n.º 18
0
        public void Reschedule_Flat_ExtendMaturity_ShiftDate()
        {
            Loan loan = _GetLoan(_GetFlatProduct(), 10000, 0.04m, 6, new DateTime(2009, 12, 22));
            loan.Repay(1, new DateTime(2010, 1, 22), 2067, false, true);
            loan.Repay(2, new DateTime(2010, 1, 22), 2067, false, true);
            Assert.AreEqual(loan.GetInstallment(0).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(1).IsRepaid, true);

            ReschedulingOptions ro = new ReschedulingOptions
            {
                InterestRate = 0.04m,
                NewInstallments = 2,
                RepaymentDateOffset = 21,
                ChargeInterestDuringShift = true
            };
            loan.Reschedule(ro);
            _AssertInstallment(loan, 2, "2010-04-12", 700, 1111, 6666, 0, 0);
            _AssertInstallment(loan, 3, "2010-05-12", 400, 1111, 5555, 0, 0);
            _AssertInstallment(loan, 4, "2010-06-14", 400, 1111, 4444, 0, 0);
            _AssertInstallment(loan, 5, "2010-07-12", 400, 1111, 3333, 0, 0);
            _AssertInstallment(loan, 6, "2010-08-12", 400, 1111, 2222, 0, 0);
            _AssertInstallment(loan, 7, "2010-09-13", 400, 1111, 1111, 0, 0);
        }
Exemplo n.º 19
0
        public void Reschedule_Annuity_ShiftDate_ChangeInterestRate_PartiallyPaid_UseCents()
        {
            Loan loan = _GetLoan(_GetAnnuityProduct_RoundingTypeBegin_WithCents(), 10000, 0.04m, 6, new DateTime(2010, 1, 12));
            loan.Repay(1, new DateTime(2010, 2, 12), 1907.62m, false, true);
            loan.Repay(2, new DateTime(2010, 3, 12), 1907.62m, false, true);
            PaymentMethod paymentMethod = new PaymentMethod(1, "Cash", "", false);
            loan.Repay(3, new DateTime(2010, 4, 5), 1500, false, 0, 0, true, 200, true, false, false, paymentMethod);
            Assert.AreEqual(loan.GetInstallment(0).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(1).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(2).IsPartiallyRepaid, true);

            ReschedulingOptions ro = new ReschedulingOptions
            {
                InterestRate = 0.03m,
                NewInstallments = 0,
                RepaymentDateOffset = 19,
                ChargeInterestDuringShift = true
            };
            loan.Reschedule(ro);

            _AssertInstallment(loan, 2, "2010-05-03", 272.15m, 2644.40m, 6924.46m);
            _AssertInstallment(loan, 3, "2010-06-01", 128.40m, 1384.73m, 4280.06m);
            _AssertInstallment(loan, 4, "2010-07-01", 86.86m, 1426.27m, 2895.33m);
            _AssertInstallment(loan, 5, "2010-08-02", 44.07m, 1469.06m, 1469.06m);
        }
Exemplo n.º 20
0
        public void Reschedule_Flat_ShiftDate_ChangeInterestRate()
        {
            Loan loan = _GetLoan(_GetFlatProduct(), 10000, 0.04m, 6, new DateTime(2009, 12, 24));
            loan.Repay(1, new DateTime(2010, 1, 25), 2067, false, true);
            loan.Repay(2, new DateTime(2010, 2, 24), 2067, false, true);
            Assert.AreEqual(loan.GetInstallment(0).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(1).IsRepaid, true);

            ReschedulingOptions ro = new ReschedulingOptions
            {
                InterestRate = 0.03m,
                NewInstallments = 0,
                RepaymentDateOffset = 38,
                ChargeInterestDuringShift = true
            };
            loan.Reschedule(ro);

            _AssertInstallment(loan, 2, "2010-05-03", 707, 1667); // 10_000 * 0.03 * 66 / 28
            _AssertInstallment(loan, 3, "2010-06-01", 300, 1666);
            _AssertInstallment(loan, 4, "2010-07-01", 300, 1667);
            _AssertInstallment(loan, 5, "2010-08-02", 300, 1666);
        }
Exemplo n.º 21
0
        public void Reschedule_Annuity_ShiftDate_ChangeInterestRate_UseCents()
        {
            Loan loan = _GetLoan(_GetAnnuityProduct_WithCents(), 10000, 0.04m, 6, new DateTime(2010, 1, 12));
            loan.Repay(1, new DateTime(2010, 2, 12), 1907.62m, false, true);
            loan.Repay(2, new DateTime(2010, 3, 12), 1907.62m, false, true);
            Assert.AreEqual(loan.GetInstallment(0).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(1).IsRepaid, true);

            ReschedulingOptions ro = new ReschedulingOptions
            {
                InterestRate = 0.03m,
                NewInstallments = 0,
                RepaymentDateOffset = 19,
                ChargeInterestDuringShift = true
            };
            loan.Reschedule(ro);

            _AssertInstallment(loan, 2, "2010-05-03", 335.05m, 1655.13m);
            _AssertInstallment(loan, 3, "2010-06-01", 158.08m, 1704.79m);
            _AssertInstallment(loan, 4, "2010-07-01", 106.94m, 1755.93m);
            _AssertInstallment(loan, 5, "2010-08-02", 54.26m, 1808.61m);
        }
Exemplo n.º 22
0
        public void Reschedule_Flat_ShiftDate_ChangeInterestRate_PartiallyPaid_UseCents()
        {
            Assert.Ignore();
            Loan loan = _GetLoan(_GetFlatProduct_WithCents(), 10000, 0.04m, 6, new DateTime(2009, 12, 22));
            loan.Repay(1, new DateTime(2010, 1, 22), 2066.67m, false, true);
            loan.Repay(2, new DateTime(2010, 2, 22), 2066.67m, false, true);
            //            loan.Repay(3, new DateTime(2010, 3, 5), 1500.00m, false, 0, 0, true, 200, true, false, false, OPaymentMethods.Cash);
            Assert.AreEqual(loan.GetInstallment(0).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(1).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(2).IsPartiallyRepaid, true);

            ReschedulingOptions ro = new ReschedulingOptions
            {
                InterestRate = 0.03m,
                NewInstallments = 0,
                RepaymentDateOffset = 40,
                ChargeInterestDuringShift = true
            };
            loan.Reschedule(ro);

            _AssertInstallment(loan, 2, "2010-05-03", 728.57m, 2641.65m, 6666.66m);
            _AssertInstallment(loan, 3, "2010-06-01", 300.00m, 1341.67m, 4025.01m);
            _AssertInstallment(loan, 4, "2010-07-01", 300.00m, 1341.67m, 2683.34m);
            _AssertInstallment(loan, 5, "2010-08-02", 300.00m, 1341.67m, 1341.67m);
        }
Exemplo n.º 23
0
        public void Reschedule_Annuity_ShiftDate_PartiallyPaid()
        {
            Loan loan = _GetLoan(_GetAnnuityProduct_RoundingTypeBegin(), 10000, 0.04m, 6, new DateTime(2010, 1, 15));
            loan.Repay(1, new DateTime(2010, 2, 12), 1906, false, true);
            loan.Repay(2, new DateTime(2010, 3, 12), 1908, false, true);
            PaymentMethod paymentMethod = new PaymentMethod(1, "Cash", "", false);
            loan.Repay(3, new DateTime(2010, 4, 5), 1500, false, 0, 0, true, 200, true, false, false, paymentMethod);
            Assert.AreEqual(loan.GetInstallment(0).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(1).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(2).IsPartiallyRepaid, true);

            ReschedulingOptions ro = new ReschedulingOptions
            {
                InterestRate = 0.04m,
                NewInstallments = 0,
                RepaymentDateOffset = 16,
                ChargeInterestDuringShift = true
            };
            loan.Reschedule(ro);

            _AssertInstallment(loan, 2, "2010-05-03", 341, 2625, 6926);
            _AssertInstallment(loan, 3, "2010-06-01", 172, 1378, 4301);
            _AssertInstallment(loan, 4, "2010-07-01", 117, 1433, 2923);
            _AssertInstallment(loan, 5, "2010-08-02", 60, 1490, 1490);
        }
Exemplo n.º 24
0
        public void Reschedule_Annuity_ExtendMaturity()
        {
            Loan loan = _GetLoan(_GetAnnuityProduct_RoundingTypeBegin(), 10000, 0.04m, 6, new DateTime(2010, 1, 15));
            loan.Repay(1, new DateTime(2010, 2, 12), 1906, false, true);
            loan.Repay(2, new DateTime(2010, 3, 12), 1908, false, true);
            Assert.AreEqual(loan.GetInstallment(0).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(1).IsRepaid, true);

            ReschedulingOptions ro = new ReschedulingOptions
            {
                InterestRate = 0.04m,
                NewInstallments = 2,
                RepaymentDateOffset = 0,
                ChargeInterestDuringShift = true
            };
            loan.Reschedule(ro);

            _AssertInstallment(loan, 2, "2010-04-15", 277, 1046, 6926, 0, 0);
            _AssertInstallment(loan, 3, "2010-05-17", 235, 1086, 5880, 0, 0);
            _AssertInstallment(loan, 4, "2010-06-15", 192, 1129, 4794, 0, 0);
            _AssertInstallment(loan, 5, "2010-07-15", 147, 1174, 3665, 0, 0);
            _AssertInstallment(loan, 6, "2010-08-16", 100, 1221, 2491, 0, 0);
            _AssertInstallment(loan, 7, "2010-09-15", 51, 1270, 1270, 0, 0);
        }
Exemplo n.º 25
0
 public void Reschedule_ContractClosed_ThrowException()
 {
     Loan loan = _GetContract_6Month_Flat();
     loan.Repay(1, new DateTime(2006, 1, 30), 1120, true, true);
     Assert.AreEqual(loan.Closed, true);
     ReschedulingOptions ro = new ReschedulingOptions();
     loan.Reschedule(ro);
 }
Exemplo n.º 26
0
        private void _Reschedule_DecliningFixedInstallments(ReschedulingOptions ro)
        {
            int months = _contract.InstallmentType.NbOfMonths;
            int days = _contract.InstallmentType.NbOfDays;
            int rounding = _contract.UseCents ? 2 : 0;

            // Split installments into two lists - paid and unpaid
            List<Installment> paidInstallments = new List<Installment>();
            List<Installment> unpaidInstallments = new List<Installment>();
            foreach (Installment installment in _contract.InstallmentList)
            {
                if (installment.IsRepaid)
                {
                    paidInstallments.Add(installment);
                }
                else
                {
                    unpaidInstallments.Add(installment);
                }
            }

            // Add new installments
            if (ro.NewInstallments > 0)
            {
                int lastNumber = unpaidInstallments[unpaidInstallments.Count - 1].Number;
                for (int i = 1; i <= ro.NewInstallments; i++)
                {
                    Installment installment = new Installment();
                    installment.Number = lastNumber + i;
                    installment.CapitalRepayment = 0;
                    installment.PaidCapital = 0;
                    installment.InterestsRepayment = 0;
                    installment.PaidInterests = 0;
                    installment.FeesUnpaid = 0;
                    installment.CommissionsUnpaid = 0;
                    unpaidInstallments.Add(installment);
                }
            }

            // We want to recalculate installments if new installments are introduced,
            // interest rate is changed, or the first unpaid installment is partially paid.
            int moveToNext = 0;
            if (unpaidInstallments[0].IsPartiallyRepaid && ro.GracePeriod > 0)
            {
                moveToNext = 1;
            }

            bool recalculate = ro.NewInstallments > 0
                || _contract.InterestRate != ro.InterestRate
                || unpaidInstallments[0].IsPartiallyRepaid
                || ro.GracePeriod != ro.NewInstallments;

            //if (ro.NewInstallments > 0 || _contract.InterestRate != ro.InterestRate || unpaidInstallments[0].IsPartiallyRepaid)
            if (recalculate)
            {
                OCurrency initialOlb = unpaidInstallments[0].OLB - unpaidInstallments[0].PaidCapital;

                int n = unpaidInstallments.Count - ro.GracePeriod - moveToNext;
                // We use the formula below to calculate monthly annuity payments

                //OCurrency monthly = 0 == r ? initialOlb / n : initialOlb * r * Math.Pow(1 + r, n) / (Math.Pow(1 + r, n) - 1);
                OCurrency monthly = _contract.VPM(initialOlb, n, ro.InterestRate);
                monthly = Math.Round(monthly.Value, rounding, MidpointRounding.AwayFromZero); //_Reschedule_Round(monthly);

                // Now loop through the unpaid installments and calculate the principal and the interest
                OCurrency sum = 0;
                OCurrency olb = initialOlb;

                foreach (Installment installment in unpaidInstallments)
                {
                    OCurrency interest = olb * ro.InterestRate;

                    if (installment.IsPartiallyRepaid && ro.GracePeriod > 0)
                    {
                        installment.InterestsRepayment = installment.PaidInterests;
                        installment.CapitalRepayment = installment.PaidCapital;
                    }
                    else
                    {
                        if (installment.Number > ro.GracePeriod + unpaidInstallments[0].Number - 1 + moveToNext)
                        {
                            OCurrency principal = monthly - interest;
                            installment.CapitalRepayment = Math.Round(principal.Value, rounding,
                                                                      MidpointRounding.AwayFromZero);
                        }
                        else
                        {
                            installment.CapitalRepayment = 0;
                        }

                        if ((installment.Number > ro.GracePeriod + unpaidInstallments[0].Number - 1 + moveToNext) ||
                            (ro.ChargeInterestDuringGracePeriod))
                        {
                            installment.InterestsRepayment = Math.Round(interest.Value, rounding,
                                                                        MidpointRounding.AwayFromZero);
                        }
                        else
                        {
                            installment.InterestsRepayment = 0;
                        }

                        if (ro.GracePeriod > 0)
                        {
                            if (!installment.IsPartiallyRepaid)
                            {
                                sum += installment.CapitalRepayment;
                                installment.OLB = olb;
                                olb -= installment.CapitalRepayment.Value;
                            }
                        }
                        else
                        {
                            sum += installment.CapitalRepayment;
                            installment.OLB = olb;
                            olb -= installment.CapitalRepayment.Value;
                        }
                    }
                }

                // As a result of rounding there might be some difference between the
                // initial OLB and the sum of installment repayments. Thus we have to
                // compensate for this difference.
                OCurrency diff = sum - initialOlb;
                if (diff != 0)
                {
                    unpaidInstallments[ro.GracePeriod + moveToNext].CapitalRepayment -= diff;
                    int firstNumber = unpaidInstallments[ro.GracePeriod + moveToNext].Number;
                    // Iterate through all unpaid but first
                    foreach (Installment installment in unpaidInstallments.FindAll(x => x.Number > firstNumber))
                    {
                        installment.OLB += diff;
                    }
                }
            }

            // Adjust the amount of interest for the first installment
            if ((ro.RepaymentDateOffset > 0 && ro.ChargeInterestDuringShift) ||
                (_contract.FirstDateChanged && 1 == unpaidInstallments[0].Number && ro.GracePeriod > 0 && ro.ChargeInterestDuringGracePeriod) ||
                (_contract.FirstDateChanged && 1 == unpaidInstallments[0].Number && 0 == ro.GracePeriod))
            {
                DateTime startDate;
                DateTime endDate1;
                DateTime endDate2;
                if (0 == paidInstallments.Count)
                {
                    startDate = _contract.StartDate;
                    endDate1 = startDate.AddMonths(months).AddDays(days);
                    endDate2 = _contract.FirstInstallmentDate.AddDays(ro.RepaymentDateOffset * (ro.ChargeInterestDuringShift ? 1 : 0));
                }
                else
                {
                    startDate = paidInstallments[paidInstallments.Count - 1].ExpectedDate;
                    endDate1 = startDate.AddMonths(months).AddDays(days);
                    endDate2 = endDate1.AddDays(ro.RepaymentDateOffset * (ro.ChargeInterestDuringShift ? 1 : 0));
                }
                TimeSpan oldSpan = endDate1 - startDate;
                TimeSpan newSpan = endDate2 - startDate;
                double olb = Convert.ToDouble(unpaidInstallments[0].OLB.Value);
                double ratio;

                if (ro.GracePeriod > 0 && !ro.ChargeInterestDuringGracePeriod)
                {
                    ratio = (double)(newSpan.Days - oldSpan.Days) / oldSpan.Days;
                }
                else
                {
                    ratio = (double)newSpan.Days / oldSpan.Days;
                }

                OCurrency interest = Convert.ToDecimal(olb) * ro.InterestRate * Convert.ToDecimal(ratio);
                interest = Math.Round(interest.Value, rounding, MidpointRounding.AwayFromZero);
                unpaidInstallments[0].InterestsRepayment = interest;
            }

            if (unpaidInstallments[0].IsPartiallyRepaid)
            {
                int instNum = ro.GracePeriod > 0 ? ro.GracePeriod - 1 : 0;
                unpaidInstallments[instNum].CapitalRepayment += unpaidInstallments[0].PaidCapital;
                unpaidInstallments[instNum].OLB += unpaidInstallments[0].PaidCapital;
            }

            // Adjust dates
            DateTime baseDate = unpaidInstallments[0].ExpectedDate.AddDays(ro.RepaymentDateOffset);
            int num = 0;
            foreach (Installment installment in unpaidInstallments)
            {
                DateTime d = baseDate.AddMonths(months * num).AddDays(days * num);
                d = _nwdS.GetTheNearestValidDate(d, _generalSettings.IsIncrementalDuringDayOff,
                                                 _generalSettings.DoNotSkipNonWorkingDays, true);
                installment.ExpectedDate = d;
                num++;
            }

            // Merge the lists back into one
            _contract.InstallmentList = paidInstallments;
            _contract.InstallmentList.AddRange(unpaidInstallments);
            _contract.NbOfInstallments = _contract.InstallmentList.Count();
        }
Exemplo n.º 27
0
        public void Reschedule_FixedPrincipal_ChangeInterest()
        {
            Loan loan = _GetLoan(_GetFixedPrincipalProduct(), 10000, 0.04m, 6, new DateTime(2009, 12, 24));
            loan.Repay(1, new DateTime(2010, 1, 25), 2067, false, true);
            loan.Repay(2, new DateTime(2010, 2, 24), 2000, false, true);
            Assert.AreEqual(loan.GetInstallment(0).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(1).IsRepaid, true);

            ReschedulingOptions ro = new ReschedulingOptions
            {
                InterestRate = 0.03m,
                NewInstallments = 0,
                RepaymentDateOffset = 0,
                ChargeInterestDuringShift = true
            };
            loan.Reschedule(ro);

            _AssertInstallment(loan, 2, "2010-03-24", 200, 1666);
            _AssertInstallment(loan, 3, "2010-04-26", 150, 1667);
            _AssertInstallment(loan, 4, "2010-05-24", 100, 1666);
            _AssertInstallment(loan, 5, "2010-06-24", 50, 1667);
        }
Exemplo n.º 28
0
        private void _Reschedule_Flat(ReschedulingOptions ro)
        {
            _Reschedule_ExtendMaturity(ro.NewInstallments);
            DateTime[] dates = _Reschedule_AdjustDates(ro);

            int roundDecimals = _contract.UseCents ? 2 : 0;
            bool firstNonRepaid = true;
            Installment firstUnpaidInstallment = _contract.GetFirstUnpaidInstallment();
            int moveToNext = 0;

            foreach (Installment installment in _contract.InstallmentList)
            {
                if (installment.IsRepaid)
                    continue;

                if (firstNonRepaid)
                {
                    firstNonRepaid = false;
                    if (ro.ChargeInterestDuringShift
                        || _contract.InterestRate != ro.InterestRate
                        || ro.NewInstallments > 0
                        || ro.GracePeriod > 0)
                    {
                        TimeSpan oldSpan;
                        TimeSpan newSpan;
                        if (1 == installment.Number)
                        {
                            DateTime endDate =
                                _contract.StartDate.AddMonths(_contract.InstallmentType.NbOfMonths).AddDays(
                                    _contract.InstallmentType.NbOfDays);
                            endDate = _nwdS.GetTheNearestValidDate(endDate, _generalSettings.IsIncrementalDuringDayOff,
                                                                   _generalSettings.DoNotSkipNonWorkingDays, true);
                            newSpan = (ro.ChargeInterestDuringShift ? installment.ExpectedDate : dates[0]) - _contract.StartDate;
                            oldSpan = endDate - _contract.StartDate;
                        }
                        else
                        {
                            DateTime startDate = _contract.GetInstallment(installment.Number - 2).ExpectedDate;
                            oldSpan = dates[0] - startDate;
                            newSpan = (ro.ChargeInterestDuringShift ? dates[1] : dates[0]) - startDate;
                        }

                        if (ro.GracePeriod > 0 && installment.IsPartiallyRepaid)
                        {
                            installment.InterestsRepayment = installment.PaidInterests;
                            moveToNext = 1;
                        }
                        else
                        {
                            if (installment.Number >= ro.GracePeriod + firstUnpaidInstallment.Number)
                            {
                                OCurrency interest = _contract.Amount * newSpan.Days * ro.InterestRate / oldSpan.Days;
                                interest = Math.Round(interest.Value, roundDecimals, MidpointRounding.AwayFromZero);
                                installment.InterestsRepayment = interest;
                            }
                            else
                            {
                                if (ro.ChargeInterestDuringGracePeriod)
                                {
                                    OCurrency interest = _contract.Amount * newSpan.Days * ro.InterestRate / oldSpan.Days;
                                    interest = Math.Round(interest.Value, roundDecimals, MidpointRounding.AwayFromZero);
                                    installment.InterestsRepayment = interest;
                                }
                                else
                                {
                                    installment.InterestsRepayment = 0;
                                }
                            }
                        }
                    }
                }
                else
                {
                    if (ro.GracePeriod > 0 && installment.IsPartiallyRepaid)
                    {
                        installment.InterestsRepayment = installment.PaidInterests;
                        moveToNext = 1;
                    }
                    else
                    {
                        if (installment.Number > ro.GracePeriod + firstUnpaidInstallment.Number - 1 + moveToNext)
                        {
                            OCurrency interest = _contract.Amount * ro.InterestRate;
                            interest = Math.Round(interest.Value, roundDecimals, MidpointRounding.AwayFromZero);
                            installment.InterestsRepayment = interest;
                        }
                        else
                        {
                            if (ro.ChargeInterestDuringGracePeriod)
                            {
                                OCurrency interest = _contract.Amount * ro.InterestRate;
                                interest = Math.Round(interest.Value, roundDecimals, MidpointRounding.AwayFromZero);
                                installment.InterestsRepayment = interest;
                            }
                            else
                            {
                                installment.InterestsRepayment = 0;
                            }
                        }
                    }
                }
            }

            if (null == firstUnpaidInstallment)
                return;

            if (!firstUnpaidInstallment.IsPartiallyRepaid && 0 == ro.NewInstallments && 0 == ro.GracePeriod)
                return;

            OCurrency unpaidAmount = 0;

            foreach (Installment installment in _contract.InstallmentList)
            {
                unpaidAmount += installment.CapitalRepayment - installment.PaidCapital;
            }

            int nbOfUnpaid = _contract.InstallmentList.Count - firstUnpaidInstallment.Number + 1;

            int nextNumber = 0;
            if (firstUnpaidInstallment.IsPartiallyRepaid && ro.GracePeriod > 0)
            {
                nextNumber = 1;
            }

            double monthly = Math.Round(
                Convert.ToDouble(unpaidAmount.Value / (nbOfUnpaid - ro.GracePeriod - nextNumber)), roundDecimals,
                MidpointRounding.AwayFromZero);

            for (int i = firstUnpaidInstallment.Number - 1; i < _contract.InstallmentList.Count; i++)
            {
                Installment installment = _contract.GetInstallment(i);
                if (installment.Number > ro.GracePeriod + firstUnpaidInstallment.Number - 1 + nextNumber)
                {
                    installment.CapitalRepayment = Convert.ToDecimal(monthly);
                }
                else
                {
                    installment.CapitalRepayment = 0;
                }
            }

            firstUnpaidInstallment.CapitalRepayment += firstUnpaidInstallment.PaidCapital;

            double diff = Convert.ToDouble(unpaidAmount.Value) - monthly * (nbOfUnpaid - ro.GracePeriod - nextNumber);

            if (diff != 0)
            {
                if (nextNumber != 1)
                    if (ro.GracePeriod > 0)
                    {
                        _contract.GetInstallment(firstUnpaidInstallment.Number + ro.GracePeriod).CapitalRepayment += Convert.ToDecimal(diff);
                    }
                    else
                    {
                        firstUnpaidInstallment.CapitalRepayment += Convert.ToDecimal(diff);
                    }
                else
                {
                    _contract.GetInstallment(firstUnpaidInstallment.Number + ro.GracePeriod).CapitalRepayment += Convert.ToDecimal(diff);
                }
            }

            OCurrency olb = firstUnpaidInstallment.OLB;

            for (int i = firstUnpaidInstallment.Number - 1; i < _contract.InstallmentList.Count; i++)
            {
                Installment installment = _contract.GetInstallment(i);
                installment.OLB = olb;
                olb -= installment.CapitalRepayment;
            }
        }
Exemplo n.º 29
0
        public void Reschedule_FixedPrincipal_ExtendMaturity_ShiftDate()
        {
            Loan loan = _GetLoan(_GetFixedPrincipalProduct(), 10000, 0.04m, 6, new DateTime(2010, 1, 11));
            loan.Repay(1, new DateTime(2010, 2, 11), 2067, false, true);
            loan.Repay(2, new DateTime(2010, 3, 11), 2000, false, true);
            Assert.AreEqual(loan.GetInstallment(0).IsRepaid, true);
            Assert.AreEqual(loan.GetInstallment(1).IsRepaid, true);

            ReschedulingOptions ro = new ReschedulingOptions
            {
                InterestRate = 0.04m,
                NewInstallments = 2,
                RepaymentDateOffset = 43,
                ChargeInterestDuringShift = true
            };
            loan.Reschedule(ro);

            _AssertInstallment(loan, 2, "2010-05-25", 625, 1111, 6666, 0, 0);
            _AssertInstallment(loan, 3, "2010-06-25", 222, 1111, 5555, 0, 0);
            _AssertInstallment(loan, 4, "2010-07-26", 178, 1111, 4444, 0, 0);
            _AssertInstallment(loan, 5, "2010-08-25", 133, 1111, 3333, 0, 0);
            _AssertInstallment(loan, 6, "2010-09-27", 89, 1111, 2222, 0, 0);
            _AssertInstallment(loan, 7, "2010-10-25", 44, 1111, 1111, 0, 0);
        }
Exemplo n.º 30
0
        public RescheduleLoanEvent Reschedule(ReschedulingOptions ro)
        {
            if (Closed)
                throw new ReschedulingContractClosedException();

            RescheduleLoan reschedule = new RescheduleLoan();

            RescheduleLoanEvent rSe = reschedule.Reschedule(ro, this, _nwdS, _generalSettings);
            _nbOfInstallments = _installmentList.Count;
            Events.Add(rSe);
            return rSe;
        }
Exemplo n.º 31
0
        private void _Reschedule_DecliningFixedInstallments(ReschedulingOptions ro)
        {
            int months   = _contract.InstallmentType.NbOfMonths;
            int days     = _contract.InstallmentType.NbOfDays;
            int rounding = _contract.UseCents ? 2 : 0;

            // Split installments into two lists - paid and unpaid
            List <Installment> paidInstallments   = new List <Installment>();
            List <Installment> unpaidInstallments = new List <Installment>();

            foreach (Installment installment in _contract.InstallmentList)
            {
                if (installment.IsRepaid)
                {
                    paidInstallments.Add(installment);
                }
                else
                {
                    unpaidInstallments.Add(installment);
                }
            }

            // Add new installments
            if (ro.NewInstallments > 0)
            {
                int lastNumber = unpaidInstallments[unpaidInstallments.Count - 1].Number;
                for (int i = 1; i <= ro.NewInstallments; i++)
                {
                    Installment installment = new Installment();
                    installment.Number             = lastNumber + i;
                    installment.CapitalRepayment   = 0;
                    installment.PaidCapital        = 0;
                    installment.InterestsRepayment = 0;
                    installment.PaidInterests      = 0;
                    installment.FeesUnpaid         = 0;
                    installment.CommissionsUnpaid  = 0;
                    unpaidInstallments.Add(installment);
                }
            }

            // We want to recalculate installments if new installments are introduced,
            // interest rate is changed, or the first unpaid installment is partially paid.
            int moveToNext = 0;

            if (unpaidInstallments[0].IsPartiallyRepaid && ro.GracePeriod > 0)
            {
                moveToNext = 1;
            }

            bool recalculate = ro.NewInstallments > 0 ||
                               _contract.InterestRate != ro.InterestRate ||
                               unpaidInstallments[0].IsPartiallyRepaid ||
                               ro.GracePeriod != ro.NewInstallments;

            //if (ro.NewInstallments > 0 || _contract.InterestRate != ro.InterestRate || unpaidInstallments[0].IsPartiallyRepaid)
            if (recalculate)
            {
                OCurrency initialOlb = unpaidInstallments[0].OLB - unpaidInstallments[0].PaidCapital;

                int n = unpaidInstallments.Count - ro.GracePeriod - moveToNext;
                // We use the formula below to calculate monthly annuity payments

                //OCurrency monthly = 0 == r ? initialOlb / n : initialOlb * r * Math.Pow(1 + r, n) / (Math.Pow(1 + r, n) - 1);
                OCurrency monthly = _contract.VPM(initialOlb, n, ro.InterestRate);
                monthly = Math.Round(monthly.Value, rounding, MidpointRounding.AwayFromZero); //_Reschedule_Round(monthly);

                // Now loop through the unpaid installments and calculate the principal and the interest
                OCurrency sum = 0;
                OCurrency olb = initialOlb;

                foreach (Installment installment in unpaidInstallments)
                {
                    OCurrency interest = olb * ro.InterestRate;

                    if (installment.IsPartiallyRepaid && ro.GracePeriod > 0)
                    {
                        installment.InterestsRepayment = installment.PaidInterests;
                        installment.CapitalRepayment   = installment.PaidCapital;
                    }
                    else
                    {
                        if (installment.Number > ro.GracePeriod + unpaidInstallments[0].Number - 1 + moveToNext)
                        {
                            OCurrency principal = monthly - interest;
                            installment.CapitalRepayment = Math.Round(principal.Value, rounding,
                                                                      MidpointRounding.AwayFromZero);
                        }
                        else
                        {
                            installment.CapitalRepayment = 0;
                        }

                        if ((installment.Number > ro.GracePeriod + unpaidInstallments[0].Number - 1 + moveToNext) ||
                            (ro.ChargeInterestDuringGracePeriod))
                        {
                            installment.InterestsRepayment = Math.Round(interest.Value, rounding,
                                                                        MidpointRounding.AwayFromZero);
                        }
                        else
                        {
                            installment.InterestsRepayment = 0;
                        }

                        if (ro.GracePeriod > 0)
                        {
                            if (!installment.IsPartiallyRepaid)
                            {
                                sum            += installment.CapitalRepayment;
                                installment.OLB = olb;
                                olb            -= installment.CapitalRepayment.Value;
                            }
                        }
                        else
                        {
                            sum            += installment.CapitalRepayment;
                            installment.OLB = olb;
                            olb            -= installment.CapitalRepayment.Value;
                        }
                    }
                }

                // As a result of rounding there might be some difference between the
                // initial OLB and the sum of installment repayments. Thus we have to
                // compensate for this difference.
                OCurrency diff = sum - initialOlb;
                if (diff != 0)
                {
                    unpaidInstallments[ro.GracePeriod + moveToNext].CapitalRepayment -= diff;
                    int firstNumber = unpaidInstallments[ro.GracePeriod + moveToNext].Number;
                    // Iterate through all unpaid but first
                    foreach (Installment installment in unpaidInstallments.FindAll(x => x.Number > firstNumber))
                    {
                        installment.OLB += diff;
                    }
                }
            }

            // Adjust the amount of interest for the first installment
            if ((ro.RepaymentDateOffset > 0 && ro.ChargeInterestDuringShift) ||
                (_contract.FirstDateChanged && 1 == unpaidInstallments[0].Number && ro.GracePeriod > 0 && ro.ChargeInterestDuringGracePeriod) ||
                (_contract.FirstDateChanged && 1 == unpaidInstallments[0].Number && 0 == ro.GracePeriod))
            {
                DateTime startDate;
                DateTime endDate1;
                DateTime endDate2;
                if (0 == paidInstallments.Count)
                {
                    startDate = _contract.StartDate;
                    endDate1  = startDate.AddMonths(months).AddDays(days);
                    endDate2  = _contract.FirstInstallmentDate.AddDays(ro.RepaymentDateOffset * (ro.ChargeInterestDuringShift ? 1 : 0));
                }
                else
                {
                    startDate = paidInstallments[paidInstallments.Count - 1].ExpectedDate;
                    endDate1  = startDate.AddMonths(months).AddDays(days);
                    endDate2  = endDate1.AddDays(ro.RepaymentDateOffset * (ro.ChargeInterestDuringShift ? 1 : 0));
                }
                TimeSpan oldSpan = endDate1 - startDate;
                TimeSpan newSpan = endDate2 - startDate;
                double   olb     = Convert.ToDouble(unpaidInstallments[0].OLB.Value);
                double   ratio;

                if (ro.GracePeriod > 0 && !ro.ChargeInterestDuringGracePeriod)
                {
                    ratio = (double)(newSpan.Days - oldSpan.Days) / oldSpan.Days;
                }
                else
                {
                    ratio = (double)newSpan.Days / oldSpan.Days;
                }

                OCurrency interest = Convert.ToDecimal(olb) * ro.InterestRate * Convert.ToDecimal(ratio);
                interest = Math.Round(interest.Value, rounding, MidpointRounding.AwayFromZero);
                unpaidInstallments[0].InterestsRepayment = interest;
            }

            if (unpaidInstallments[0].IsPartiallyRepaid)
            {
                int instNum = ro.GracePeriod > 0 ? ro.GracePeriod - 1 : 0;
                unpaidInstallments[instNum].CapitalRepayment += unpaidInstallments[0].PaidCapital;
                unpaidInstallments[instNum].OLB += unpaidInstallments[0].PaidCapital;
            }

            // Adjust dates
            DateTime baseDate = unpaidInstallments[0].ExpectedDate.AddDays(ro.RepaymentDateOffset);
            int      num      = 0;

            foreach (Installment installment in unpaidInstallments)
            {
                DateTime d = baseDate.AddMonths(months * num).AddDays(days * num);
                d = _nwdS.GetTheNearestValidDate(d, _generalSettings.IsIncrementalDuringDayOff,
                                                 _generalSettings.DoNotSkipNonWorkingDays, true);
                installment.ExpectedDate = d;
                num++;
            }

            // Merge the lists back into one
            _contract.InstallmentList = paidInstallments;
            _contract.InstallmentList.AddRange(unpaidInstallments);
            _contract.NbOfInstallments = _contract.InstallmentList.Count();
        }