public void CalculateExpectedOLB2()
        {
            LoanProduct package = new LoanProduct
            {
                InstallmentType = new InstallmentType(1, "Monthly", 0, 1),
                LoanType        = OLoanTypes.Flat,
                ChargeInterestWithinGracePeriod = true,
                Currency = new Currency {
                    Id = 1
                }
            };

            package.KeepExpectedInstallment = false;
            package.AnticipatedTotalRepaymentPenaltiesBase = OAnticipatedRepaymentPenaltiesBases.RemainingOLB;
            Loan myContract = new Loan(package, 20000, 0.02m, 10, 0, new DateTime(2009, 1, 17), new User(), ApplicationSettings.GetInstance(""), NonWorkingDateSingleton.GetInstance(""), ProvisionTable.GetInstance(new User()), ChartOfAccounts.GetInstance(new User()));

            myContract.BadLoan = false;

            myContract.Repay(1, new DateTime(2009, 1, 17), 1000, true, false);

            Assert.AreEqual(19000, myContract.CalculateExpectedOlb(1, false).Value);
            Assert.AreEqual(17100, myContract.CalculateExpectedOlb(2, false).Value);
            Assert.AreEqual(15200, myContract.CalculateExpectedOlb(3, false).Value);
            Assert.AreEqual(13300, myContract.CalculateExpectedOlb(4, false).Value);
            Assert.AreEqual(11400, myContract.CalculateExpectedOlb(5, false).Value);
            Assert.AreEqual(9500, myContract.CalculateExpectedOlb(6, false).Value);
            Assert.AreEqual(7600, myContract.CalculateExpectedOlb(7, false).Value);
            Assert.AreEqual(5700, myContract.CalculateExpectedOlb(8, false).Value);
            Assert.AreEqual(3800, myContract.CalculateExpectedOlb(9, false).Value);
            Assert.AreEqual(1900, myContract.CalculateExpectedOlb(10, false).Value);
        }
        public void TestRepayFlat_GracePeriod_KeepNotExpectedInstallments()
        {
            ApplicationSettings.GetInstance("").UpdateParameter(OGeneralSettings.ACCOUNTINGPROCESS, OAccountingProcesses.Accrual);

            LoanProduct package = new LoanProduct
            {
                InstallmentType = new InstallmentType(1, "Monthly", 0, 1),
                LoanType        = OLoanTypes.Flat,
                ChargeInterestWithinGracePeriod = true,
                Currency = new Currency {
                    Id = 1, UseCents = true
                }
            };

            package.KeepExpectedInstallment = false;
            package.AnticipatedTotalRepaymentPenaltiesBase = OAnticipatedRepaymentPenaltiesBases.RemainingOLB;
            Loan myContract = new Loan(package, 50000, 0.01m, 8, 2, new DateTime(2006, 1, 1), new User(), ApplicationSettings.GetInstance(""), NonWorkingDateSingleton.GetInstance(""), ProvisionTable.GetInstance(new User()), ChartOfAccounts.GetInstance(new User()));

            myContract.BadLoan = false;

            myContract.Repay(1, new DateTime(2006, 2, 1), 1050, true, true);
            myContract.Repay(2, new DateTime(2006, 6, 1), 40000, true, true);

            Assert.AreEqual(50000, myContract.CalculateExpectedOlb(1, false).Value);
            Assert.AreEqual(50000, myContract.CalculateExpectedOlb(2, false).Value);
            Assert.AreEqual(50000m, myContract.CalculateExpectedOlb(3, false).Value);
            Assert.AreEqual(41666.67m, myContract.CalculateExpectedOlb(4, false).Value);
            Assert.AreEqual(33333.34m, myContract.CalculateExpectedOlb(5, false).Value);
            //Assert.AreEqual(11428m, myContract.CalculateExpectedOLB(6, false).Value);
            //Assert.AreEqual(7618.67m, myContract.CalculateExpectedOLB(7, false).Value);
            //Assert.AreEqual(3809.34m, myContract.CalculateExpectedOLB(8, false).Value);
        }
        private static OCurrency AnticipateCalculateFeesBasedOnOlb(Loan pContract, DateTime date, int installmentNumber, OPaymentType paymentType)
        {
            Installment preInstallment = installmentNumber != 1
                ? pContract.GetInstallment(installmentNumber - 2)
                : pContract.GetInstallment(installmentNumber - 1);

            OCurrency amountHasToPay;

            if (((preInstallment.IsRepaid) || (installmentNumber == 1)) || (!preInstallment.IsRepaid && preInstallment.ExpectedDate <= date))
            {
                if (pContract.EscapedMember != null)
                {
                    //calculate olb for the person of the group
                    amountHasToPay = (pContract.CalculateExpectedOlb(installmentNumber, false) *
                                      pContract.EscapedMember.LoanShareAmount / pContract.Amount);
                }
                else
                {
                    amountHasToPay = pContract.CalculateExpectedOlb(installmentNumber, false) - pContract.GetInstallment(installmentNumber - 1).PaidCapital;
                }
            }
            else
            {
                amountHasToPay = 0;
            }

            if (paymentType == OPaymentType.TotalPayment || pContract.EscapedMember != null)
            {
                return(amountHasToPay.Value * Convert.ToDecimal(pContract.AnticipatedTotalRepaymentPenalties));
            }

            return(amountHasToPay.Value * Convert.ToDecimal(pContract.AnticipatedPartialRepaymentPenalties));
        }
        public void OLB_Flat_NoRepayment_NoGracePeriod()
        {
            Loan myContract = _GetLoan(new DateTime(2006, 2, 1), 5, 0, OLoanTypes.Flat);

            Assert.AreEqual(1000, myContract.CalculateExpectedOlb(1, false).Value);
            Assert.AreEqual(800, myContract.CalculateExpectedOlb(2, false).Value);
            Assert.AreEqual(600, myContract.CalculateExpectedOlb(3, false).Value);
            Assert.AreEqual(400, myContract.CalculateExpectedOlb(4, false).Value);
            Assert.AreEqual(200, myContract.CalculateExpectedOlb(5, false).Value);
        }
        public void OLB_DecliningFixedInstallments_OneRepayment_OneMonthGracePeriod_Overdue_KeepNotExpectedInstallment()
        {
            ApplicationSettings.GetInstance("").UpdateParameter(OGeneralSettings.ACCOUNTINGPROCESS, OAccountingProcesses.Accrual);

            LoanProduct package = new LoanProduct
            {
                InstallmentType = new InstallmentType(1, "Monthly", 0, 1),
                LoanType        = OLoanTypes.DecliningFixedInstallments,
                ChargeInterestWithinGracePeriod = true,
                Currency = new Currency {
                    Id = 1, UseCents = true
                }
            };

            Loan myContract = new Loan(package, 750, 0.03m, 9, 1, new DateTime(2006, 2, 1), new User(), ApplicationSettings.GetInstance(""), NonWorkingDateSingleton.GetInstance(""), ProvisionTable.GetInstance(new User()), ChartOfAccounts.GetInstance(new User()));

            myContract.Repay(1, new DateTime(2006, 3, 1), 740, false, false);

            Assert.AreEqual(750, myContract.CalculateExpectedOlb(1, false).Value);
            Assert.AreEqual(32.5m, myContract.CalculateExpectedOlb(2, false).Value);
            Assert.AreEqual(28.85m, myContract.CalculateExpectedOlb(3, false).Value);
            Assert.AreEqual(25.09m, myContract.CalculateExpectedOlb(4, false).Value);
            Assert.AreEqual(21.21m, myContract.CalculateExpectedOlb(5, false).Value);
            Assert.AreEqual(17.22m, myContract.CalculateExpectedOlb(6, false).Value);
            Assert.AreEqual(13.11m, myContract.CalculateExpectedOlb(7, false).Value);
            Assert.AreEqual(8.87m, myContract.CalculateExpectedOlb(8, false).Value);
            Assert.AreEqual(4.51m, myContract.CalculateExpectedOlb(9, false).Value);
        }
        public void OLB_Flat_OneRepaymentBeforeDueDate_NoGracePeriod_NoOverDue_KeepExpectedInstallment()
        {
            Loan myContract = _GetLoan(new DateTime(2006, 2, 1), 5, 0, OLoanTypes.Flat);

            myContract.Repay(1, new DateTime(2006, 2, 24), 500, true, true);

            Assert.AreEqual(1000, myContract.CalculateExpectedOlb(1, true).Value);
            Assert.AreEqual(800, myContract.CalculateExpectedOlb(2, true).Value);
            Assert.AreEqual(600, myContract.CalculateExpectedOlb(3, true).Value);
            Assert.AreEqual(400, myContract.CalculateExpectedOlb(4, true).Value);
            Assert.AreEqual(200, myContract.CalculateExpectedOlb(5, true).Value);
        }
        public void OLB_Flat_OneRepaymentBeforeDueDate_NoGracePeriod_NoOverDue_KeepNotExpectedInstallment()
        {
            ApplicationSettings.GetInstance("").UpdateParameter(OGeneralSettings.ACCOUNTINGPROCESS, OAccountingProcesses.Accrual);

            Loan myContract = _GetLoan(new DateTime(2010, 1, 1), 5, 0, OLoanTypes.Flat);

            myContract.Repay(1, new DateTime(2010, 1, 26), 500, true, false);

            Assert.AreEqual(524.19m, myContract.CalculateExpectedOlb(1, false).Value);
            Assert.AreEqual(419.35m, myContract.CalculateExpectedOlb(2, false).Value);
            Assert.AreEqual(314.51m, myContract.CalculateExpectedOlb(3, false).Value);
            Assert.AreEqual(209.67m, myContract.CalculateExpectedOlb(4, false).Value);
            Assert.AreEqual(104.83m, myContract.CalculateExpectedOlb(5, false).Value);
        }
        public void OLB_Flat_TwosRepayments_SecondBeforeDueDate_NoGracePeriod_NoOverDue_KeepNotExpectedInstallment()
        {
            ApplicationSettings.GetInstance("").UpdateParameter(OGeneralSettings.ACCOUNTINGPROCESS, OAccountingProcesses.Accrual);

            Loan myContract = _GetLoan(new DateTime(2006, 2, 1), 5, 0, OLoanTypes.Flat);

            myContract.Repay(1, new DateTime(2006, 3, 1), 230, true, false);
            myContract.Repay(2, new DateTime(2006, 4, 1), 320, true, false);

            Assert.AreEqual(1000, myContract.CalculateExpectedOlb(1, false).Value);
            Assert.AreEqual(508.18m, myContract.CalculateExpectedOlb(2, false).Value);
            Assert.AreEqual(381.13m, myContract.CalculateExpectedOlb(3, false).Value);
            Assert.AreEqual(254.08m, myContract.CalculateExpectedOlb(4, false).Value);
            Assert.AreEqual(127.03m, myContract.CalculateExpectedOlb(5, false).Value);
        }
        public void OLB_Flat_OneRepayment_NoGracePeriod_OverDue_KeepNotExpectedInstallment()
        {
            ApplicationSettings.GetInstance("").UpdateParameter(OGeneralSettings.ACCOUNTINGPROCESS, OAccountingProcesses.Accrual);

            Loan myContract = _GetLoan(new DateTime(2006, 2, 1), 5, 0, OLoanTypes.Flat);

            myContract.Repay(1, new DateTime(2006, 3, 1), 630, true, false);

            Assert.AreEqual(1000, myContract.CalculateExpectedOlb(1, false).Value);
            Assert.AreEqual(400, myContract.CalculateExpectedOlb(2, false).Value);
            Assert.AreEqual(300, myContract.CalculateExpectedOlb(3, false).Value);
            Assert.AreEqual(200, myContract.CalculateExpectedOlb(4, false).Value);
            Assert.AreEqual(100, myContract.CalculateExpectedOlb(5, false).Value);
            ApplicationSettings.GetInstance("").UpdateParameter(OGeneralSettings.ACCOUNTINGPROCESS, OAccountingProcesses.Cash);
        }
        public void OLB_Flat_TotalRepayment_GracePeriod_KeepNotExpectedInstallment()
        {
            Loan myContract = _GetLoan(new DateTime(2006, 1, 1), 6, 1, OLoanTypes.Flat);

            myContract.Repay(1, new DateTime(2006, 2, 1), 30, true, false);
            myContract.Repay(2, new DateTime(2006, 3, 1), 230, true, false);
            myContract.Repay(3, new DateTime(2006, 3, 20), 920, true, true);

            Assert.AreEqual(1000, myContract.CalculateExpectedOlb(1, false).Value);
            Assert.AreEqual(1000, myContract.CalculateExpectedOlb(2, false).Value);
            Assert.AreEqual(800, myContract.CalculateExpectedOlb(3, false).Value);
            Assert.AreEqual(600, myContract.CalculateExpectedOlb(4, false).Value);
            Assert.AreEqual(400, myContract.CalculateExpectedOlb(5, false).Value);
            Assert.AreEqual(200, myContract.CalculateExpectedOlb(6, false).Value);
        }
        private static OCurrency AnticipateCalculateFeesBasedOnOlb(Loan pContract, DateTime date, int installmentNumber, OPaymentType paymentType)
        {
            Installment preInstallment = installmentNumber != 1 
                ? pContract.GetInstallment(installmentNumber - 2) 
                : pContract.GetInstallment(installmentNumber - 1);

            OCurrency amountHasToPay;

            if (((preInstallment.IsRepaid) || (installmentNumber == 1)) || (!preInstallment.IsRepaid && preInstallment.ExpectedDate <= date))
            {
                if (pContract.EscapedMember != null)
                {
                    //calculate olb for the person of the group
                    amountHasToPay = (pContract.CalculateExpectedOlb(installmentNumber, false) *
                                 pContract.EscapedMember.LoanShareAmount / pContract.Amount);
                }
                else
                {
                    amountHasToPay = pContract.CalculateExpectedOlb(installmentNumber, false) - pContract.GetInstallment(installmentNumber - 1).PaidCapital;
                }

            }
            else
            {
                amountHasToPay = 0;
            }

            if (paymentType == OPaymentType.TotalPayment || pContract.EscapedMember != null)
                return amountHasToPay.Value * Convert.ToDecimal(pContract.AnticipatedTotalRepaymentPenalties);

            return amountHasToPay.Value * Convert.ToDecimal(pContract.AnticipatedPartialRepaymentPenalties);
        }
        public static OCurrency CalculateAnticipateRepayment(Loan pContract, DateTime pDate, ApplicationSettings pGeneralSettings, NonWorkingDateSingleton pNonWorkingDate, OPaymentType pPaymentType)
        {
            Installment pInstallment = null;
            OCurrency interests = 0;
            Installment priorInstallment;
            OCurrency olb = 0;
            OCurrency fees = 0;
            OCurrency ammountHasToPay = 0;

            for (int i = 0; i < pContract.NbOfInstallments; i++)
            {
                Installment installment = pContract.GetInstallment(i);

                if (!installment.IsRepaid && installment.ExpectedDate > pDate)
                {
                    if (pInstallment == null)
                    {
                        pInstallment = installment;

                        if (olb == 0)
                        {
                            olb = pContract.CalculateExpectedOlb(pInstallment.Number, false);
                        }

                        //is case APR on the first installment
                        DateTime expectedDate;

                        if (i == 0)
                        {
                            expectedDate = pContract.StartDate;
                        }
                        else
                        {
                            priorInstallment = pContract.GetInstallment(i - 1);
                            expectedDate = priorInstallment.ExpectedDate;
                        }

                        int daySpan = (pDate - expectedDate).Days < 0 ? 0 : (pDate - expectedDate).Days;
                        int daysInMonth = DateTime.DaysInMonth(pDate.Year, pDate.Month);

                        if (pGeneralSettings.AccountingProcesses == OAccountingProcesses.Accrual)
                        {
                            interests = pInstallment.InterestsRepayment * daySpan / daysInMonth;
                        }
                        else
                        {
                            interests = pInstallment.ExpectedDate > pDate ? 0 : pInstallment.InterestsRepayment;
                        }
                    }

                    fees += CalculateCommision(pContract, pDate, installment.Number, pPaymentType, pGeneralSettings);
                }

                if (!installment.IsRepaid && installment.ExpectedDate <= pDate)
                {
                    ammountHasToPay += installment.InterestsRepayment + installment.PrincipalHasToPay;
                }
            }

            if (interests != 0)
                interests = pContract.UseCents ? Math.Round(interests.Value, 2) : Math.Round(interests.Value, 0);

            OCurrency amount = interests + fees + ammountHasToPay;

            return amount;
        }
        public static OCurrency CalculateAnticipateRepayment(Loan pContract, DateTime pDate, ApplicationSettings pGeneralSettings, NonWorkingDateSingleton pNonWorkingDate, OPaymentType pPaymentType)
        {
            Installment pInstallment = null;
            OCurrency   interests    = 0;
            Installment priorInstallment;
            OCurrency   olb             = 0;
            OCurrency   fees            = 0;
            OCurrency   ammountHasToPay = 0;

            for (int i = 0; i < pContract.NbOfInstallments; i++)
            {
                Installment installment = pContract.GetInstallment(i);

                if (!installment.IsRepaid && installment.ExpectedDate > pDate)
                {
                    if (pInstallment == null)
                    {
                        pInstallment = installment;

                        if (olb == 0)
                        {
                            olb = pContract.CalculateExpectedOlb(pInstallment.Number, false);
                        }

                        //is case APR on the first installment
                        DateTime expectedDate;

                        if (i == 0)
                        {
                            expectedDate = pContract.StartDate;
                        }
                        else
                        {
                            priorInstallment = pContract.GetInstallment(i - 1);
                            expectedDate     = priorInstallment.ExpectedDate;
                        }

                        int daySpan     = (pDate - expectedDate).Days < 0 ? 0 : (pDate - expectedDate).Days;
                        int daysInMonth = DateTime.DaysInMonth(pDate.Year, pDate.Month);

                        if (pGeneralSettings.AccountingProcesses == OAccountingProcesses.Accrual)
                        {
                            interests = pInstallment.InterestsRepayment * daySpan / daysInMonth;
                        }
                        else
                        {
                            interests = pInstallment.ExpectedDate > pDate ? 0 : pInstallment.InterestsRepayment;
                        }
                    }

                    fees += CalculateCommision(pContract, pDate, installment.Number, pPaymentType, pGeneralSettings);
                }

                if (!installment.IsRepaid && installment.ExpectedDate <= pDate)
                {
                    ammountHasToPay += installment.InterestsRepayment + installment.PrincipalHasToPay;
                }
            }

            if (interests != 0)
            {
                interests = pContract.UseCents ? Math.Round(interests.Value, 2) : Math.Round(interests.Value, 0);
            }

            OCurrency amount = interests + fees + ammountHasToPay;

            return(amount);
        }