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

            Installment installment = null;

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

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

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

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

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

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

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

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

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

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

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

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

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

                    if (installment.PaidCapital == 0
                        && installment.PaidInterests > 0
                        && installment.PaidInterests != installment.InterestsRepayment)
                    {

                        DateTime dateOfInstallment = installment.Number == 1
                                                         ? _contract.StartDate
                                                         : _contract.GetInstallment(installment.Number - 2).ExpectedDate;

                        int d = (date - dateOfInstallment).Days;

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

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

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

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

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

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

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

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

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

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

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

                    interestsToRepay -= paymentOfInterest;

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

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

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

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

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

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

                    interestsToRepay -= paymentOfInterest;

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

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

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

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

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

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

                    interestsToRepay -= paymentOfInterest;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                        int days = (expectedDate - beginDate).Days;

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

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

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

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

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

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

            if (installment != null)
                for (int i = installment.Number; i < _contract.NbOfInstallments; i++)
                {
                    _contract.GetInstallment(i).FeesUnpaid = 0;
                }
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        private static OCurrency CalculateCommision(Loan pContract, DateTime pDate, int number, OPaymentType pPaymentType, ApplicationSettings pGeneralSettings)
        {
            OCurrency commision;

            if (pContract.Product.AnticipatedTotalRepaymentPenaltiesBase == OAnticipatedRepaymentPenaltiesBases.RemainingInterest)
            {
                commision = _AnticipateCalculateNonRepaymentPenalties(pContract, pDate, number, pPaymentType, pGeneralSettings);
            }
            else
            {
                commision = AnticipateCalculateFeesBasedOnOlb(pContract, pDate, number, pPaymentType);
            }
            return commision;
        }
Ejemplo n.º 4
0
        public OCurrency CalculateCommision(DateTime pDate, int pNumber, OPaymentType pPaymentType, OCurrency amount, ref bool calculated)
        {
            if (_contract.Product.AnticipatedPartialRepaymentPenaltiesBase == OAnticipatedRepaymentPenaltiesBases.PrepaidPrincipal
                && !calculated)
            {
                calculated = true;
                return amount * _contract.AnticipatedPartialRepaymentPenalties / (1 + _contract.AnticipatedPartialRepaymentPenalties);
            }

            if (_contract.Product.AnticipatedTotalRepaymentPenaltiesBase ==
                    OAnticipatedRepaymentPenaltiesBases.RemainingInterest && !calculated)
                {
                    return CalculationBaseForLateFees.AnticipateFeesBasedOnOverdueInterest(
                        _contract, pDate, pNumber, false,
                        _generalSettings, _nWds, pPaymentType);
                }

            return CalculationBaseForLateFees.AnticipateFeesBasedOnOlb(_contract, pDate, pNumber, false,
                                                                       _generalSettings, _nWds, pPaymentType);
        }
        public static OCurrency AnticipateFeesBasedOnOverdueInterest(Loan pContract, DateTime pDate, int pInstallmentNumber, bool pForClosure, ApplicationSettings pGeneralSettings, NonWorkingDateSingleton pNonWorkingDate, OPaymentType pPaymentType)
        {
            OCurrency fees = _AnticipateCalculateNonRepaymentPenalties(pContract, pDate, pInstallmentNumber, pPaymentType, pGeneralSettings);

            return(fees.Value);
        }
Ejemplo n.º 6
0
        private EventStock GenerateRepaymentEvents(CreditContractRepayment cCr, 
                                                   DateTime payDate, 
                                                   OCurrency penaltiesEvent,
                                                   OCurrency commissionsEvent, 
                                                   OCurrency interestEvent, 
                                                   OCurrency interestPrepayment, 
                                                   OCurrency principalEvent,
                                                   int pastDueDays, 
                                                   OPaymentType paymentType, 
                                                   bool isPending, 
                                                   int instNumber,
                                                   PaymentMethod paymentMethod,
                                                   bool overridePenalty,
                                                   OCurrency manualPenalty,
                                                   OCurrency manualInterestEvent,
                                                   ref RepaymentEvent totalEvent)
        {
            RepaymentEvent rpEvent;
            totalEvent.Penalties = 0;
            totalEvent.Commissions = 0;
            EventStock listOfLoanEvents = new EventStock();

            #region Event identification
            //////////////////////////////////////////////////////////////////////////////////////////////////////////
            if (cCr.PaidIstallments.Count > 0)
            {
                List<Installment> lateInstallments = cCr.PaidIstallments.FindAll(i => i.CalculatedPenalty > 0);
                Installment lastLate = 0 == lateInstallments.Count ? null : lateInstallments.OrderBy(i => i.Number).Last();

                foreach (Installment paidInstallment in cCr.PaidIstallments)
                {
                    int number = paidInstallment.Number;
                    OCurrency rpeCapital = 0;
                    OCurrency rpeInterests = 0;
                    OCurrency rpeCommission = 0;
                    OCurrency rpePenalty = 0;
                    int overdueDays = (payDate.Date - paidInstallment.ExpectedDate).Days > 0
                                          ? (payDate.Date - paidInstallment.ExpectedDate).Days
                                          : 0;

                    foreach (RepaymentEvent rpe in Events.GetLoanRepaymentEvents())
                    {
                        if (rpe.InstallmentNumber == paidInstallment.Number && !rpe.Deleted)
                        {
                            if (rpe.RepaymentType != OPaymentType.PersonTotalPayment)
                            {
                                if ((rpe.RepaymentType != OPaymentType.PartialPayment)
                                    && (rpe.RepaymentType != OPaymentType.ProportionalPayment))
                                {
                                    rpeCapital += rpe.Principal;
                                    rpeInterests += rpe.Interests;
                                }

                                if (rpe.RepaymentType == OPaymentType.PartialPayment && paymentType == OPaymentType.TotalPayment)
                                {
                                    rpeCapital += rpe.Principal;
                                    rpeInterests += rpe.Interests;
                                }

                                rpePenalty += rpe.Penalties;
                            }

                            rpeCommission += rpe.Commissions;
                            if (rpe.RepaymentType == OPaymentType.PersonTotalPayment && cCr.LoanOptions.ManualCommissionAmount != 0)
                                rpeCommission -= rpe.Commissions;
                        }
                    }

                    if (rpeCapital > paidInstallment.PaidCapital)
                        rpeCapital = 0;

                    if (rpeInterests < 0)
                        rpeInterests = 0;

                    if (rpeInterests > paidInstallment.InterestsRepayment)
                    {
                        rpeInterests = 0;
                    }

                    OCurrency principalAmount = paidInstallment.CapitalRepayment -
                                                (paidInstallment.CapitalRepayment - (paidInstallment.PaidCapital - rpeCapital));

                    OCurrency interestAmount = paidInstallment.InterestsRepayment -
                                               (paidInstallment.InterestsRepayment - (paidInstallment.PaidInterests - rpeInterests));

                    if (interestAmount < 0)
                        interestAmount = 0;

                    principalEvent -= principalAmount;
                    interestEvent -= interestAmount;

                    if (principalAmount == 0
                        && interestAmount == 0
                        && paidInstallment.PaidCapital == 0 && manualInterestEvent == 0)
                    {
                        principalAmount = principalEvent;
                        interestAmount = interestEvent;
                    }

                    if (interestAmount < 0)
                        interestAmount = 0;

                    OCurrency commissionAmount = paidInstallment.CommissionsUnpaid -
                                               (paidInstallment.CommissionsUnpaid - (paidInstallment.PaidCommissions - rpeCommission));

                    OCurrency penaltyAmount;
                    if (overridePenalty)
                    {
                        if (lastLate != null && paidInstallment.CalculatedPenalty <= manualPenalty && paidInstallment.Number < lastLate.Number)
                        {
                            penaltyAmount = paidInstallment.CalculatedPenalty;
                            manualPenalty -= penaltyAmount;
                        }
                        else
                        {
                            penaltyAmount = manualPenalty;
                            manualPenalty = 0m;
                        }
                    }
                    else
                    {
                        penaltyAmount = paidInstallment.FeesUnpaid -
                                                  (paidInstallment.FeesUnpaid - (paidInstallment.PaidFees - rpePenalty));
                    }

                    //just to be sure that we do not have negative in the base
                    penaltyAmount = penaltyAmount < 0 ? 0 : penaltyAmount;
                    commissionAmount = commissionAmount < 0 ? 0 : commissionAmount;

                    if (overridePenalty && penaltyAmount > 0)
                    {
                        penaltyAmount = (-1.0) * penaltyAmount;
                    }

                    rpEvent = CreateRepaymentEvent(number,
                                                       payDate,
                                                       penaltyAmount,
                                                       commissionAmount,
                                                       interestAmount,
                                                       interestAmount,
                                                       principalAmount,
                                                       overdueDays,
                                                       _clientType == OClientTypes.Group,
                                                       paymentType,
                                                       isPending);

                    if (overridePenalty && penaltyAmount < 0)
                        penaltyAmount = (-1.0)*penaltyAmount;
                    rpEvent.PaymentMethod = paymentMethod;
                    rpEvent.CalculatedPenalties = paidInstallment.CalculatedPenalty;
                    if (rpEvent.CalculatedPenalties > penaltyAmount)
                    {
                        if (overridePenalty)
                        {
                            rpEvent.WrittenOffPenalties = rpEvent.CalculatedPenalties - penaltyAmount;
                        }
                        else
                        {
                            rpEvent.UnpaidPenalties = rpEvent.CalculatedPenalties - penaltyAmount;
                        }
                    }
                    totalEvent.Penalties += rpEvent.Penalties;
                    totalEvent.Commissions += rpEvent.Commissions;

                    if (rpEvent.InterestPrepayment != 0
                        || rpEvent.Principal != 0
                        || rpEvent.Penalties != 0
                        || rpEvent.Commissions != 0)
                        listOfLoanEvents.Add(rpEvent);
                }
            }
            else
            {
                rpEvent = CreateRepaymentEvent(instNumber,
                                               payDate,
                                               penaltiesEvent,
                                               commissionsEvent,
                                               interestEvent,
                                               interestPrepayment,
                                               principalEvent,
                                               pastDueDays,
                                               _clientType == OClientTypes.Group,
                                               paymentType,
                                               isPending);
                rpEvent.PaymentMethod = paymentMethod;
                // Calculate penalties
                Installment installment = GetInstallment(instNumber - 1);
                rpEvent.CalculatedPenalties = installment.CalculatedPenalty;
                if (rpEvent.CalculatedPenalties > penaltiesEvent)
                {
                    if (overridePenalty)
                    {
                        rpEvent.WrittenOffPenalties = rpEvent.CalculatedPenalties - penaltiesEvent;
                    }
                    else
                    {
                        rpEvent.UnpaidPenalties = rpEvent.CalculatedPenalties - penaltiesEvent;
                    }
                }
                totalEvent.Penalties += rpEvent.Penalties;
                totalEvent.Commissions += rpEvent.Commissions;
                listOfLoanEvents.Add(rpEvent);
            }
            #endregion

            return listOfLoanEvents;
        }
Ejemplo n.º 7
0
        public void Repay(OCurrency amountPaid, 
                         ref OCurrency penaltiesEvent, 
                         ref OCurrency commissionsEvent, 
                         ref OCurrency interestsEvent,
                         ref OCurrency iterestPrepayment, 
                         ref OCurrency principalEvent, 
                         ref OCurrency manualInterestAmount, 
                         ref OPaymentType paymentType)
        {
            _repaymentMethod.Repay(ref amountPaid, ref penaltiesEvent, ref commissionsEvent, ref interestsEvent);
            //repayLateInstallment + eventualy a good installment => Penalties
            _calculateInstallments.CalculateNewInstallmentsWithLateFees(_date);

            if (paymentType == OPaymentType.PartialPayment
                || paymentType == OPaymentType.TotalPayment
                || paymentType == OPaymentType.ProportionalPayment)
                _calculateInstallments.CalculateAnticipateRepayment(_date, paymentType, amountPaid);

            switch (paymentType)
            {
                case OPaymentType.StandardPayment:
                    {
                        if (LoanOptions.LoansType == OLoanTypes.DecliningFixedPrincipalWithRealInterest)
                        {
                            _calculateRealInterestInstallments.RepayInstallments(_date,
                                                                                ref amountPaid,
                                                                                ref interestsEvent,
                                                                                ref principalEvent,
                                                                                ref penaltiesEvent,
                                                                                ref commissionsEvent,
                                                                                ref paymentType);
                            PaidIstallments.AddRange(AddInstallments(_calculateRealInterestInstallments.PaidIstallments, PaidIstallments));
                        }
                        else
                        {
                            _calculateInstallments.RepayInstallments(_date,
                                                                 ref amountPaid,
                                                                 ref interestsEvent,
                                                                 ref principalEvent,
                                                                 ref penaltiesEvent,
                                                                 ref commissionsEvent);
                        }

                        break;
                    }

                case OPaymentType.TotalPayment:
                    {
                        _calculateInstallments.RepayTotalAnticipateInstallments(_date, ref amountPaid,
                                                                                ref interestsEvent, ref principalEvent,
                                                                                ref penaltiesEvent,
                                                                                ref commissionsEvent);
                        break;
                    }

                case OPaymentType.PartialPayment:
                    {
                        _calculateInstallments.RepayPartialAnticipateInstallments(_date, ref amountPaid,
                                                                                  ref interestsEvent,
                                                                                  ref principalEvent,
                                                                                  ref penaltiesEvent,
                                                                                  ref commissionsEvent);
                        break;
                    }
                case OPaymentType.ProportionalPayment:
                    {
                        _calculateInstallments.RepayProportinalyInstallments(_date, ref amountPaid,
                                                                                  ref interestsEvent,
                                                                                  ref principalEvent,
                                                                                  ref penaltiesEvent,
                                                                                  ref commissionsEvent);
                        break;
                    }
            }

            PaidIstallments.AddRange(AddInstallments(_calculateInstallments.PaidIstallments, PaidIstallments));
            PaidIstallments.AddRange(AddInstallments(_repaymentMethod.PaidIstallments, PaidIstallments));

            //old legacy one day we will remove it
            if (paymentType == OPaymentType.StandardPayment)
                _feesForAnticipatedRepayment.calculateFees(_date, ref amountPaid, ref commissionsEvent);

            //repaynextinstallment
            if (amountPaid > 0)
            {
                _repayNextInstallments.RepayNextInstallments(ref amountPaid, ref interestsEvent, ref iterestPrepayment,
                                                             ref principalEvent, ref penaltiesEvent,
                                                             ref commissionsEvent);

                PaidIstallments.AddRange(AddInstallments(_repayNextInstallments.PaidInstallments, PaidIstallments));
            }
        }
Ejemplo n.º 8
0
 public OCurrency CalculateAnticipateInteresAmountForClosure(DateTime pDate, OPaymentType pPaymentType)
 {
     return CalculationBaseForLateFees.CalculateAnticipateRepayment(this, pDate, _generalSettings, _nwdS, pPaymentType);
 }
Ejemplo n.º 9
0
        public void Repay(OCurrency amountPaid, ref OCurrency penaltiesEvent, ref OCurrency commissionsEvent, ref OCurrency interestsEvent,
            ref OCurrency iterestPrepayment, ref OCurrency principalEvent, ref OCurrency manualInterestAmount, OPaymentType paymentType)
        {
            _repaymentMethod.Repay(ref amountPaid, ref penaltiesEvent, ref commissionsEvent, ref interestsEvent);
            //repayLateInstallment + eventualy a good installment => Penalties
            _calculateInstallments.CalculateNewInstallmentsWithLateFees(_date);

            if (paymentType == OPaymentType.PartialPayment || paymentType == OPaymentType.TotalPayment)
                _calculateInstallments.CalculateAnticipateRepayment(_date, paymentType, amountPaid);

            switch (paymentType)
            {
                case OPaymentType.StandardPayment:
                    {
                        _calculateInstallments.RepayInstallments(_date, ref amountPaid, ref interestsEvent,
                                                                 ref principalEvent, ref penaltiesEvent,
                                                                 ref commissionsEvent);
                        break;
                    }

                case OPaymentType.TotalPayment:
                    {
                        _calculateInstallments.RepayTotalAnticipateInstallments(_date, ref amountPaid,
                                                                                ref interestsEvent, ref principalEvent,
                                                                                ref penaltiesEvent,
                                                                                ref commissionsEvent);
                        break;
                    }

                case OPaymentType.PartialPayment:
                    {
                        _calculateInstallments.RepayPartialAnticipateInstallments(_date, ref amountPaid,
                                                                                  ref interestsEvent,
                                                                                  ref principalEvent,
                                                                                  ref penaltiesEvent,
                                                                                  ref commissionsEvent);
                        break;
                    }
            }

            PaidIstallments = _calculateInstallments.PaidIstallments;

               //old legacy one day we will remove it
            if (paymentType == OPaymentType.StandardPayment)
                _feesForAnticipatedRepayment.calculateFees(_date, ref amountPaid, ref commissionsEvent);

            //repaynextinstallment
            if (amountPaid > 0)
            {
                _repayNextInstallments.RepayNextInstallments(ref amountPaid, ref interestsEvent, ref iterestPrepayment,
                                                             ref principalEvent, ref penaltiesEvent,
                                                             ref commissionsEvent);

                foreach(Installment paidIstallment in _repayNextInstallments.PaidInstallments)
                {
                    PaidIstallments.Add(paidIstallment);
                }
            }
        }
        private static OCurrency CalculateCommision(Loan pContract, DateTime pDate, int number, OPaymentType pPaymentType, ApplicationSettings pGeneralSettings)
        {
            OCurrency commision;

            if (pContract.Product.AnticipatedTotalRepaymentPenaltiesBase == OAnticipatedRepaymentPenaltiesBases.RemainingInterest)
            {
                commision = _AnticipateCalculateNonRepaymentPenalties(pContract, pDate, number, pPaymentType, pGeneralSettings);
            }
            else
            {
                commision = AnticipateCalculateFeesBasedOnOlb(pContract, pDate, number, pPaymentType);
            }
            return(commision);
        }
Ejemplo n.º 11
0
        private EventStock GenerateRepaymentEvents(CreditContractRepayment cCr, 
                                                   DateTime payDate, 
                                                   OCurrency penaltiesEvent,
                                                   OCurrency commissionsEvent, 
                                                   OCurrency interestEvent, 
                                                   OCurrency interestPrepayment, 
                                                   OCurrency principalEvent,
                                                   int pastDueDays, 
                                                   OPaymentType paymentType, 
                                                   bool isPending, 
                                                   int instNumber,
                                                   OPaymentMethods paymentMethods)
        {
            RepaymentEvent rpEvent;
            EventStock listOfLoanEvents = new EventStock();

            #region Event identification
            //////////////////////////////////////////////////////////////////////////////////////////////////////////
            if (cCr.PaidIstallments.Count > 0)
            {
                foreach (Installment paidIstallment in cCr.PaidIstallments)
                {
                    int number = paidIstallment.Number;
                    OCurrency rpeCapital = 0;
                    OCurrency rpeInterests = 0;
                    OCurrency rpeCommission = 0;
                    OCurrency rpePenalty = 0;
                    int overdueDays = paidIstallment.ExpectedDate >= payDate ? 0 : pastDueDays;

                    foreach (RepaymentEvent rpe in Events.GetLoanRepaymentEvents())
                    {
                        if (rpe.InstallmentNumber == paidIstallment.Number && !rpe.Deleted)
                        {
                            if (rpe.RepaymentType != OPaymentType.PersonTotalPayment)
                            {
                                rpeCapital += rpe.Principal;
                                rpeInterests += rpe.Interests;
                                rpePenalty += rpe.Penalties;
                            }

                            rpeCommission += rpe.Commissions;
                            if (rpe.RepaymentType == OPaymentType.PersonTotalPayment && cCr.LoanOptions.ManualCommissionAmount != 0)
                                rpeCommission -= rpe.Commissions;
                        }
                    }

                    if (rpeCapital > paidIstallment.PaidCapital)
                        rpeCapital = 0;

                    if (rpeInterests < 0)
                        rpeInterests = 0;

                    if (rpeInterests > paidIstallment.InterestsRepayment)
                    {
                        rpeInterests = 0;
                    }

                    OCurrency principalAmount = paidIstallment.CapitalRepayment -
                                                (paidIstallment.CapitalRepayment - (paidIstallment.PaidCapital - rpeCapital));

                    OCurrency interestAmount = paidIstallment.InterestsRepayment -
                                               (paidIstallment.InterestsRepayment - (paidIstallment.PaidInterests - rpeInterests));

                    principalEvent -= principalAmount;
                    interestEvent -= interestAmount;

                    if (principalAmount == 0 && interestAmount == 0 && paidIstallment.PaidCapital == 0)
                    {
                        principalAmount = principalEvent;
                        interestAmount = interestEvent;
                    }

                    if (interestAmount < 0)
                        interestAmount = 0;

                    OCurrency commissionAmount = paidIstallment.CommissionsUnpaid -
                                               (paidIstallment.CommissionsUnpaid - (paidIstallment.PaidCommissions - rpeCommission));

                    OCurrency penaltyAmount = paidIstallment.FeesUnpaid -
                                               (paidIstallment.FeesUnpaid - (paidIstallment.PaidFees - rpePenalty));
                    //just to be sure that we do not have negative in the base
                    penaltyAmount = penaltyAmount < 0 ? 0 : penaltyAmount;

                    rpEvent = CreateRepaymentEvent(number,
                                                       payDate,
                                                       penaltyAmount,
                                                       commissionAmount,
                                                       interestAmount,
                                                       interestAmount,
                                                       principalAmount,
                                                       overdueDays,
                                                       _clientType == OClientTypes.Group,
                                                       paymentType,
                                                       isPending);
                    rpEvent.PaymentMethod = paymentMethods;
                    listOfLoanEvents.Add(rpEvent);
                }
            }
            else
            {
                rpEvent = CreateRepaymentEvent(instNumber,
                                               payDate,
                                               penaltiesEvent,
                                               commissionsEvent,
                                               interestEvent,
                                               interestPrepayment,
                                               principalEvent,
                                               pastDueDays,
                                               _clientType == OClientTypes.Group,
                                               paymentType,
                                               isPending);
                rpEvent.PaymentMethod = paymentMethods;
                listOfLoanEvents.Add(rpEvent);
            }
            #endregion

            return listOfLoanEvents;
        }
        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));
        }
        private static OCurrency _AnticipateCalculateNonRepaymentPenalties(Loan pContract, DateTime pDate, int installmentNumber,
                                                                           OPaymentType pPaymentType, ApplicationSettings pGeneralSettings)
        {
            Installment installment = pContract.GetInstallment(installmentNumber - 1);
            Installment preInstallment;
            DateTime    expectedDate;

            if (installmentNumber != 1)
            {
                preInstallment = pContract.GetInstallment(installmentNumber - 2);
                expectedDate   = preInstallment.ExpectedDate;
            }
            else
            {
                preInstallment = pContract.GetInstallment(installmentNumber - 1);
                expectedDate   = pContract.StartDate;
            }

            OCurrency amountHasToPay;

            //calculation of remaining interest
            if (((preInstallment.IsRepaid) || (installmentNumber == 1)) || (!preInstallment.IsRepaid && preInstallment.ExpectedDate < pDate))
            {
                int daysInInstallment = installment.Number == 1
                                                       ? (installment.ExpectedDate - pContract.StartDate).Days
                                                       : (installment.ExpectedDate -
                                                          pContract.GetInstallment(installment.Number - 2).ExpectedDate)
                                        .Days;

                int days = (pDate - expectedDate).Days < 0 ? daysInInstallment : daysInInstallment - (pDate - expectedDate).Days;

                if (pGeneralSettings.AccountingProcesses == OAccountingProcesses.Accrual)
                {
                    amountHasToPay = installment.InterestsRepayment / daysInInstallment * days;

                    if (pContract.EscapedMember != null)
                    {
                        amountHasToPay = installment.InterestsRepayment * pContract.EscapedMember.LoanShareAmount / pContract.Amount;
                        //amountHasToPay = (installment.InterestsRepayment - amountHasToPay) * pContract.EscapedMember.LoanShareAmount / pContract.Amount;
                        amountHasToPay = amountHasToPay / daysInInstallment * days;
                    }
                }
                else
                {
                    amountHasToPay = installment.InterestsRepayment - installment.PaidInterests;
                    if (pContract.EscapedMember != null)
                    {
                        amountHasToPay = amountHasToPay * pContract.EscapedMember.LoanShareAmount / pContract.Amount;
                    }
                }
            }
            else
            {
                amountHasToPay = installment.InterestsRepayment;
                if (pContract.EscapedMember != null)
                {
                    amountHasToPay = amountHasToPay * pContract.EscapedMember.LoanShareAmount / pContract.Amount;
                }
            }

            if (OPaymentType.TotalPayment == pPaymentType || 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);
        }
Ejemplo n.º 15
0
        public void Repay(OCurrency amountPaid,
                          ref OCurrency penaltiesEvent,
                          ref OCurrency commissionsEvent,
                          ref OCurrency interestsEvent,
                          ref OCurrency iterestPrepayment,
                          ref OCurrency principalEvent,
                          ref OCurrency manualInterestAmount,
                          ref OPaymentType paymentType)
        {
            _repaymentMethod.Repay(ref amountPaid, ref penaltiesEvent, ref commissionsEvent, ref interestsEvent);
            //repayLateInstallment + eventualy a good installment => Penalties
            _calculateInstallments.CalculateNewInstallmentsWithLateFees(_date);

            if (paymentType == OPaymentType.PartialPayment ||
                paymentType == OPaymentType.TotalPayment ||
                paymentType == OPaymentType.ProportionalPayment)
            {
                _calculateInstallments.CalculateAnticipateRepayment(_date, paymentType, amountPaid);
            }

            switch (paymentType)
            {
            case OPaymentType.StandardPayment:
            {
                if (LoanOptions.LoansType == OLoanTypes.DecliningFixedPrincipalWithRealInterest)
                {
                    _calculateRealInterestInstallments.RepayInstallments(_date,
                                                                         ref amountPaid,
                                                                         ref interestsEvent,
                                                                         ref principalEvent,
                                                                         ref penaltiesEvent,
                                                                         ref commissionsEvent,
                                                                         ref paymentType);
                    PaidIstallments.AddRange(AddInstallments(_calculateRealInterestInstallments.PaidIstallments, PaidIstallments));
                }
                else
                {
                    _calculateInstallments.RepayInstallments(_date,
                                                             ref amountPaid,
                                                             ref interestsEvent,
                                                             ref principalEvent,
                                                             ref penaltiesEvent,
                                                             ref commissionsEvent);
                }

                break;
            }

            case OPaymentType.TotalPayment:
            {
                _calculateInstallments.RepayTotalAnticipateInstallments(_date, ref amountPaid,
                                                                        ref interestsEvent, ref principalEvent,
                                                                        ref penaltiesEvent,
                                                                        ref commissionsEvent);
                break;
            }

            case OPaymentType.PartialPayment:
            {
                _calculateInstallments.RepayPartialAnticipateInstallments(_date, ref amountPaid,
                                                                          ref interestsEvent,
                                                                          ref principalEvent,
                                                                          ref penaltiesEvent,
                                                                          ref commissionsEvent);
                break;
            }

            case OPaymentType.ProportionalPayment:
            {
                _calculateInstallments.RepayProportinalyInstallments(_date, ref amountPaid,
                                                                     ref interestsEvent,
                                                                     ref principalEvent,
                                                                     ref penaltiesEvent,
                                                                     ref commissionsEvent);
                break;
            }
            }

            PaidIstallments.AddRange(AddInstallments(_calculateInstallments.PaidIstallments, PaidIstallments));
            PaidIstallments.AddRange(AddInstallments(_repaymentMethod.PaidIstallments, PaidIstallments));

            //old legacy one day we will remove it
            if (paymentType == OPaymentType.StandardPayment)
            {
                _feesForAnticipatedRepayment.calculateFees(_date, ref amountPaid, ref commissionsEvent);
            }

            //repaynextinstallment
            if (amountPaid > 0)
            {
                _repayNextInstallments.RepayNextInstallments(ref amountPaid, ref interestsEvent, ref iterestPrepayment,
                                                             ref principalEvent, ref penaltiesEvent,
                                                             ref commissionsEvent);

                PaidIstallments.AddRange(AddInstallments(_repayNextInstallments.PaidInstallments, PaidIstallments));
            }
        }
Ejemplo n.º 16
0
        public static OCurrency AnticipateFeesBasedOnOlb(Loan pContract, DateTime pDate, int pInstallmentNumber, bool pForClosure, ApplicationSettings pGeneralSettings, NonWorkingDateSingleton pNonWorkingDate, OPaymentType pPaymentType)
        {
            OCurrency fees = AnticipateCalculateFeesBasedOnOlb(pContract, pDate, pInstallmentNumber, pPaymentType);

            return fees;
        }
Ejemplo n.º 17
0
        private RepaymentEvent CreateRepaymentEvent(int installmentNumber, 
                                                    DateTime pDate, 
                                                    OCurrency penaltiesEvent, 
                                                    OCurrency commissionsEvent,
                                                    OCurrency interestEvent, 
                                                    OCurrency interestPrepayment, 
                                                    OCurrency pincipalEvent, 
                                                    int overDueDays,
                                                    bool isGroup, 
                                                    OPaymentType repaymentType, 
                                                    bool pending)
        {
            //We need to generate specific RepaymentEvent in case of bad loan or rescheduled loan
            RepaymentEvent rPe = !_badLoan && Rescheduled && !_writtenOff
                                     ? new RescheduledLoanRepaymentEvent()
                                     : (_badLoan && !_writtenOff
                                        ? new BadLoanRepaymentEvent()
                                            : (_writtenOff ?
                                                new RepaymentOverWriteOffEvent()
                                                : new RepaymentEvent()));

            if ((overDueDays > 0 || penaltiesEvent > 0) && !_writtenOff)
                rPe = new BadLoanRepaymentEvent();
            penaltiesEvent = penaltiesEvent > 0 ? penaltiesEvent : (-1.0)*penaltiesEvent;
            //identification of pending event must be the last action
            if (pending) rPe = new PendingRepaymentEvent(rPe);

            rPe.PastDueDays = overDueDays;
            rPe.InstallmentNumber = installmentNumber;
            rPe.Date = pDate;
            rPe.Penalties = penaltiesEvent;
            rPe.Commissions = commissionsEvent;
            rPe.Interests = interestEvent;

            if (_product.LoanType == OLoanTypes.DecliningFixedPrincipalWithRealInterest
                && repaymentType == OPaymentType.TotalPayment)
            {
                repaymentType = OPaymentType.TotalPayment;
            }
            else
            {
                if (InstallmentList[installmentNumber - 1].ExpectedDate <= pDate)
                {
                    repaymentType = OPaymentType.StandardPayment;
                }
            }

            rPe.RepaymentType = repaymentType;

            if(EscapedMember != null)
            {
                rPe.RepaymentType = OPaymentType.PersonTotalPayment;
            }

            rPe.InterestPrepayment = interestPrepayment;
            rPe.Principal = pincipalEvent;
            rPe.Cancelable = true;
            rPe.ClientType = isGroup ? OClientTypes.Group : OClientTypes.Person;

            // Test if the client has repaid the total principal, interests and penalties owed at date D
            //	In this case, the loan will be regraded to good loan and provision will be cancelled.
            if (_badLoan && !pending)
                _badLoan = _IsBadLoan(rPe, pDate);

            return rPe;
        }
Ejemplo n.º 18
0
        public static OCurrency AnticipateFeesBasedOnOverdueInterest(Loan pContract, DateTime pDate, int pInstallmentNumber, bool pForClosure, ApplicationSettings pGeneralSettings, NonWorkingDateSingleton pNonWorkingDate, OPaymentType pPaymentType)
        {
            OCurrency fees = _AnticipateCalculateNonRepaymentPenalties(pContract, pDate, pInstallmentNumber, pPaymentType, pGeneralSettings);

            return fees.Value;
        }
Ejemplo n.º 19
0
 public OCurrency CalculateAnticipateInteresAmountForClosure(DateTime pDate, OPaymentType pPaymentType, bool payProportion)
 {
     if(payProportion)
     {
         OCurrency amount = 0;
         foreach (Installment installment in _installmentList)
         {
             if (!installment.IsRepaid && installment.CapitalRepayment != 0)
             {
                 amount += installment.InterestsRepayment;
             }
         }
         return amount;
     }
     return CalculationBaseForLateFees.CalculateAnticipateRepayment(this, pDate, _generalSettings, _nwdS, pPaymentType);
 }
Ejemplo n.º 20
0
        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 void RepayInstallments(DateTime payDate,
                                      ref OCurrency amountPaid,
                                      ref OCurrency interestEvent,
                                      ref OCurrency principalEvent,
                                      ref OCurrency feesEvent,
                                      ref OCurrency commissionsEvent,
                                      ref OPaymentType paymentType)
        {
            if (amountPaid == 0)
            {
                return;
            }
            // we need date without time part
            payDate = payDate.Date;

            Installment installment = null;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                        int d = (date - dateOfInstallment).Days;

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

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

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

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

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

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

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

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

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

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

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

                    interestsToRepay -= paymentOfInterest;

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

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

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

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

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

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

                    interestsToRepay -= paymentOfInterest;

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

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

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

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

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

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

                    interestsToRepay -= paymentOfInterest;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                        int days = (expectedDate - beginDate).Days;

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

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


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

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

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

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

            if (installment != null)
            {
                for (int i = installment.Number; i < _contract.NbOfInstallments; i++)
                {
                    _contract.GetInstallment(i).FeesUnpaid = 0;
                }
            }
        }
Ejemplo n.º 22
0
        private static OCurrency _AnticipateCalculateNonRepaymentPenalties(Loan pContract, DateTime pDate, int installmentNumber, 
            OPaymentType pPaymentType, ApplicationSettings pGeneralSettings)
        {
            Installment installment = pContract.GetInstallment(installmentNumber - 1);
            Installment preInstallment;
            DateTime expectedDate;

            if (installmentNumber != 1)
            {
                preInstallment = pContract.GetInstallment(installmentNumber - 2);
                expectedDate = preInstallment.ExpectedDate;
            }
            else
            {
                preInstallment = pContract.GetInstallment(installmentNumber - 1);
                expectedDate = pContract.StartDate;
            }

            OCurrency amountHasToPay;
            //calculation of remaining interest
            if (((preInstallment.IsRepaid) || (installmentNumber == 1)) || (!preInstallment.IsRepaid && preInstallment.ExpectedDate < pDate))
            {
                int daysInInstallment = installment.Number == 1
                                                       ? (installment.ExpectedDate - pContract.StartDate).Days
                                                       : (installment.ExpectedDate -
                                                          pContract.GetInstallment(installment.Number - 2).ExpectedDate)
                                                             .Days;

                int days = (pDate - expectedDate).Days < 0 ? daysInInstallment : daysInInstallment - (pDate - expectedDate).Days;
                
                if (pGeneralSettings.AccountingProcesses == OAccountingProcesses.Accrual)
                {

                    amountHasToPay = installment.InterestsRepayment / daysInInstallment * days;
                    
                    if (pContract.EscapedMember != null)
                    {
                        amountHasToPay = installment.InterestsRepayment * pContract.EscapedMember.LoanShareAmount / pContract.Amount;
                        //amountHasToPay = (installment.InterestsRepayment - amountHasToPay) * pContract.EscapedMember.LoanShareAmount / pContract.Amount;
                        amountHasToPay = amountHasToPay / daysInInstallment * days;
                    }
                }
                else
                {
                    amountHasToPay = installment.InterestsRepayment - installment.PaidInterests;
                    if (pContract.EscapedMember != null)
                    {
                        amountHasToPay = amountHasToPay * pContract.EscapedMember.LoanShareAmount / pContract.Amount;
                    }
                }
            }
            else
            {
                amountHasToPay = installment.InterestsRepayment;
                if (pContract.EscapedMember != null)
                {
                    amountHasToPay = amountHasToPay * pContract.EscapedMember.LoanShareAmount / pContract.Amount;
                }
            }

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

            return amountHasToPay.Value * Convert.ToDecimal(pContract.AnticipatedPartialRepaymentPenalties);
        }
Ejemplo n.º 23
0
        public void CalculateAnticipateRepayment(DateTime pDate, OPaymentType pPaymentType, OCurrency paidAmount)
        {
            Installment installment = null;
            OCurrency interests = 0;
            OCurrency commission = 0;
            Installment priorInstallment;
            bool calculated = false;
            OCurrency aTprComission = 0;
            OCurrency willBePaidAmount = 0;
            //to calculate what will be paid before apr or atr
            foreach (Installment willBePaidInstallment in _contract.InstallmentList)
            {
                if(!willBePaidInstallment.IsRepaid && willBePaidInstallment.ExpectedDate <= pDate)
                {
                    willBePaidAmount += willBePaidInstallment.InterestsRepayment - willBePaidInstallment.PaidInterests;
                    willBePaidAmount += willBePaidInstallment.CapitalRepayment - willBePaidInstallment.PaidCapital;
                    willBePaidAmount += willBePaidInstallment.FeesUnpaid;
                }
            }

            for (int i = 0; i < _contract.NbOfInstallments; i++)
            {
                Installment getInstallment = _contract.GetInstallment(i);

                if (!getInstallment.IsRepaid && getInstallment.ExpectedDate > pDate
                    || (getInstallment.ExpectedDate == pDate && _contract.EscapedMember != null))
                {
                    if (installment == null)
                    {
                        installment = getInstallment;

                        if (_generalSettings.AccountingProcesses == OAccountingProcesses.Accrual)
                        {
                            DateTime expectedDate;
                            //int daysInTheInstallment = _contract.NumberOfDaysInTheInstallment(installment.Number, pDate);

                            int daysInTheInstallment = installment.Number == 1
                                                       ? (installment.ExpectedDate - _contract.StartDate).Days
                                                       : (installment.ExpectedDate -
                                                          _contract.GetInstallment(installment.Number - 2).ExpectedDate)
                                                             .Days;

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

                                if(_contract.GetLastRepaymentDate() > expectedDate)
                                {
                                    expectedDate = _contract.GetLastRepaymentDate();
                                    daysInTheInstallment = (installment.ExpectedDate - expectedDate).Days;
                                }
                            }

                            if(getInstallment.ExpectedDate == pDate && _contract.EscapedMember != null)
                            {
                                expectedDate = getInstallment.ExpectedDate;
                            }

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

                            if (_contract.EscapedMember != null)
                            {
                                //calculate new interes for the person of the group
                                OCurrency amount = _contract.Product.LoanType == OLoanTypes.Flat
                                                  ? _contract.Amount
                                                  : _contract.GetOlb();

                                if (daySpan != 0)
                                {
                                    interests = (amount*_contract.EscapedMember.LoanShareAmount/_contract.Amount)*
                                                daySpan/
                                                daysInTheInstallment*_contract.InterestRate;
                                }
                                else
                                {
                                    interests = (amount * _contract.EscapedMember.LoanShareAmount / _contract.Amount) * _contract.InterestRate;
                                }
                            }
                            else
                            {
                                interests = installment.InterestsRepayment * daySpan / daysInTheInstallment;
                                if (installment.PaidInterests > interests)
                                {
                                    interests = 0;
                                    installment.PaidInterests = 0;
                                }
                            }

                        }
                        else
                        {
                            if (_contract.EscapedMember != null)
                            {
                                if (installment.ExpectedDate == pDate)
                                {
                                    OCurrency amount = _contract.Product.LoanType == OLoanTypes.Flat
                                                           ? _contract.Amount
                                                           : _contract.GetOlb();

                                    interests = (amount*_contract.EscapedMember.LoanShareAmount/_contract.Amount)*
                                                _contract.InterestRate;
                                }
                            }
                            else
                            {

                                interests = installment.InterestsRepayment == installment.PaidInterests
                                                ? installment.InterestsRepayment
                                                : (installment.ExpectedDate > pDate ? 0 : installment.InterestsRepayment);
                            }
                        }
                    }

                    commission += CalculateCommision(pDate, getInstallment.Number, pPaymentType, paidAmount - interests - willBePaidAmount, ref calculated);

                    if (getInstallment.ExpectedDate == pDate && _contract.EscapedMember != null && _contract.Product.AnticipatedTotalRepaymentPenaltiesBase != OAnticipatedRepaymentPenaltiesBases.RemainingInterest)
                        aTprComission = commission;

                    if (getInstallment.ExpectedDate > pDate && _contract.EscapedMember != null && aTprComission > 0 && _contract.Product.AnticipatedTotalRepaymentPenaltiesBase != OAnticipatedRepaymentPenaltiesBases.RemainingInterest)
                        commission = aTprComission;

                    if (_generalSettings.AccountingProcesses == OAccountingProcesses.Cash)
                    {
                        if (installment.PaidInterests > interests)
                        {
                            interests = 0;
                            installment.PaidInterests = 0;
                        }
                    }

                    foreach (RepaymentEvent rPayment in _contract.Events.GetRepaymentEvents())
                    {
                        if (rPayment.Date == pDate && installment.Number == rPayment.InstallmentNumber)
                        {
                            installment.FeesUnpaid = 0;
                        }
                    }
                }
            }

            if (installment != null)
            {
                if (interests == 0 && installment.PaidInterests == 0)
                    installment.NotPaidYet = true;

                installment.InterestsRepayment = _contract.UseCents ? Math.Round(interests.Value, 2, MidpointRounding.AwayFromZero) : Math.Round(interests.Value, 0, MidpointRounding.AwayFromZero);
                installment.CommissionsUnpaid = _contract.UseCents ? Math.Round(commission.Value, 2, MidpointRounding.AwayFromZero) : Math.Round(commission.Value, 0, MidpointRounding.AwayFromZero);
            }
        }
        public static OCurrency AnticipateFeesBasedOnOlb(Loan pContract, DateTime pDate, int pInstallmentNumber, bool pForClosure, ApplicationSettings pGeneralSettings, NonWorkingDateSingleton pNonWorkingDate, OPaymentType pPaymentType)
        {
            OCurrency fees = AnticipateCalculateFeesBasedOnOlb(pContract, pDate, pInstallmentNumber, pPaymentType);

            return(fees);
        }