Example usage for org.joda.time LocalDate isAfter

List of usage examples for org.joda.time LocalDate isAfter

Introduction

In this page you can find the example usage for org.joda.time LocalDate isAfter.

Prototype

public boolean isAfter(ReadablePartial partial) 

Source Link

Document

Is this partial later than the specified partial.

Usage

From source file:com.gst.portfolio.loanaccount.domain.transactionprocessor.impl.HeavensFamilyLoanRepaymentScheduleTransactionProcessor.java

License:Apache License

@Override
protected boolean isTransactionInAdvanceOfInstallment(final int currentInstallmentIndex,
        final List<LoanRepaymentScheduleInstallment> installments, final LocalDate transactionDate,
        final Money transactionAmount) {

    boolean isInAdvance = false;

    LocalDate lastInstallmentDueDate = null;
    int previousInstallmentIndex = 0;
    if (currentInstallmentIndex > 0) {
        previousInstallmentIndex = currentInstallmentIndex - 1;
    }/*  w w w.  j av  a  2 s . c  o m*/

    final LoanRepaymentScheduleInstallment previousInstallment = installments.get(previousInstallmentIndex);
    lastInstallmentDueDate = previousInstallment.getDueDate();

    isInAdvance = !(transactionDate.isAfter(lastInstallmentDueDate)
            || (transactionDate.isEqual(lastInstallmentDueDate)));

    return isInAdvance;
}

From source file:com.gst.portfolio.loanaccount.loanschedule.domain.AbstractLoanScheduleGenerator.java

License:Apache License

private LoanScheduleModel generate(final MathContext mc, final LoanApplicationTerms loanApplicationTerms,
        final Set<LoanCharge> loanCharges, final HolidayDetailDTO holidayDetailDTO,
        final LoanScheduleParams loanScheduleParams) {

    final ApplicationCurrency applicationCurrency = loanApplicationTerms.getApplicationCurrency();
    // generate list of proposed schedule due dates
    LocalDate loanEndDate = this.scheduledDateGenerator.getLastRepaymentDate(loanApplicationTerms,
            holidayDetailDTO);/* www  .j  a  va2  s  .  c  om*/
    LoanTermVariationsData lastDueDateVariation = loanApplicationTerms.getLoanTermVariations()
            .fetchLoanTermDueDateVariationsData(loanEndDate);
    if (lastDueDateVariation != null) {
        loanEndDate = lastDueDateVariation.getDateValue();
    }
    loanApplicationTerms.updateLoanEndDate(loanEndDate);

    // determine the total charges due at time of disbursement
    final BigDecimal chargesDueAtTimeOfDisbursement = deriveTotalChargesDueAtTimeOfDisbursement(loanCharges);

    // setup variables for tracking important facts required for loan
    // schedule generation.

    final MonetaryCurrency currency = loanApplicationTerms.getCurrency();
    final int numberOfRepayments = loanApplicationTerms.fetchNumberOfRepaymentsAfterExceptions();
    LoanScheduleParams scheduleParams = null;
    if (loanScheduleParams == null) {
        scheduleParams = LoanScheduleParams.createLoanScheduleParams(currency,
                Money.of(currency, chargesDueAtTimeOfDisbursement),
                loanApplicationTerms.getExpectedDisbursementDate(),
                getPrincipalToBeScheduled(loanApplicationTerms));
    } else if (!loanScheduleParams.isPartialUpdate()) {
        scheduleParams = LoanScheduleParams.createLoanScheduleParams(currency,
                Money.of(currency, chargesDueAtTimeOfDisbursement),
                loanApplicationTerms.getExpectedDisbursementDate(),
                getPrincipalToBeScheduled(loanApplicationTerms), loanScheduleParams);
    } else {
        scheduleParams = loanScheduleParams;
    }

    final Collection<RecalculationDetail> transactions = scheduleParams.getRecalculationDetails();
    final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = scheduleParams
            .getLoanRepaymentScheduleTransactionProcessor();

    Collection<LoanScheduleModelPeriod> periods = new ArrayList<>();
    if (!scheduleParams.isPartialUpdate()) {
        periods = createNewLoanScheduleListWithDisbursementDetails(numberOfRepayments, loanApplicationTerms,
                chargesDueAtTimeOfDisbursement);
    }

    // Determine the total interest owed over the full loan for FLAT
    // interest method .
    if (!scheduleParams.isPartialUpdate()) {
        Money totalInterestChargedForFullLoanTerm = loanApplicationTerms
                .calculateTotalInterestCharged(this.paymentPeriodsInOneYearCalculator, mc);
        loanApplicationTerms.updateTotalInterestDue(totalInterestChargedForFullLoanTerm);
    }

    boolean isFirstRepayment = true;
    LocalDate firstRepaymentdate = this.scheduledDateGenerator.generateNextRepaymentDate(
            loanApplicationTerms.getExpectedDisbursementDate(), loanApplicationTerms, isFirstRepayment,
            holidayDetailDTO);
    final LocalDate idealDisbursementDate = this.scheduledDateGenerator
            .idealDisbursementDateBasedOnFirstRepaymentDate(
                    loanApplicationTerms.getLoanTermPeriodFrequencyType(),
                    loanApplicationTerms.getRepaymentEvery(), firstRepaymentdate,
                    loanApplicationTerms.getLoanCalendar(), loanApplicationTerms.getHolidayDetailDTO(),
                    loanApplicationTerms);

    if (!scheduleParams.isPartialUpdate()) {
        // Set Fixed Principal Amount
        updateAmortization(mc, loanApplicationTerms, scheduleParams.getPeriodNumber(),
                scheduleParams.getOutstandingBalance());

        if (loanApplicationTerms.isMultiDisburseLoan()) {
            // fetches the first tranche amount and also updates other
            // tranche
            // details to map
            BigDecimal disburseAmt = getDisbursementAmount(loanApplicationTerms,
                    scheduleParams.getPeriodStartDate(), periods, chargesDueAtTimeOfDisbursement,
                    scheduleParams.getDisburseDetailMap(), scheduleParams.applyInterestRecalculation());
            scheduleParams.setPrincipalToBeScheduled(Money.of(currency, disburseAmt));
            loanApplicationTerms.setPrincipal(loanApplicationTerms.getPrincipal().zero().plus(disburseAmt));
            scheduleParams.setOutstandingBalance(Money.of(currency, disburseAmt));
            scheduleParams.setOutstandingBalanceAsPerRest(Money.of(currency, disburseAmt));
        }
    }

    // charges which depends on total loan interest will be added to this
    // set and handled separately after all installments generated
    final Set<LoanCharge> nonCompoundingCharges = seperateTotalCompoundingPercentageCharges(loanCharges);

    LocalDate currentDate = DateUtils.getLocalDateOfTenant();
    LocalDate lastRestDate = currentDate;
    if (loanApplicationTerms.getRestCalendarInstance() != null) {
        lastRestDate = getNextRestScheduleDate(currentDate.minusDays(1), loanApplicationTerms,
                holidayDetailDTO);
    }

    boolean isNextRepaymentAvailable = true;
    Boolean extendTermForDailyRepayments = false;

    if (holidayDetailDTO.getWorkingDays().getExtendTermForDailyRepayments() == true
            && loanApplicationTerms.getRepaymentPeriodFrequencyType() == PeriodFrequencyType.DAYS
            && loanApplicationTerms.getRepaymentEvery() == 1) {
        holidayDetailDTO.getWorkingDays()
                .setRepaymentReschedulingType(RepaymentRescheduleType.MOVE_TO_NEXT_WORKING_DAY.getValue());
        extendTermForDailyRepayments = true;
    }

    final Collection<LoanTermVariationsData> interestRates = loanApplicationTerms.getLoanTermVariations()
            .getInterestRateChanges();
    final Collection<LoanTermVariationsData> interestRatesForInstallments = loanApplicationTerms
            .getLoanTermVariations().getInterestRateFromInstallment();

    // this block is to start the schedule generation from specified date
    if (scheduleParams.isPartialUpdate()) {
        if (loanApplicationTerms.isMultiDisburseLoan()) {
            loanApplicationTerms.setPrincipal(scheduleParams.getPrincipalToBeScheduled());
        }

        applyLoanVariationsForPartialScheduleGenerate(loanApplicationTerms, scheduleParams, interestRates,
                interestRatesForInstallments);

        isFirstRepayment = false;
    }
    while (!scheduleParams.getOutstandingBalance().isZero()
            || !scheduleParams.getDisburseDetailMap().isEmpty()) {
        LocalDate previousRepaymentDate = scheduleParams.getActualRepaymentDate();
        scheduleParams.setActualRepaymentDate(
                this.scheduledDateGenerator.generateNextRepaymentDate(scheduleParams.getActualRepaymentDate(),
                        loanApplicationTerms, isFirstRepayment, holidayDetailDTO));
        isFirstRepayment = false;
        LocalDate scheduledDueDate = this.scheduledDateGenerator.adjustRepaymentDate(
                scheduleParams.getActualRepaymentDate(), loanApplicationTerms, holidayDetailDTO);

        // calculated interest start date for the period
        LocalDate periodStartDateApplicableForInterest = calculateInterestStartDateForPeriod(
                loanApplicationTerms, scheduleParams.getPeriodStartDate(), idealDisbursementDate,
                firstRepaymentdate, loanApplicationTerms.isInterestChargedFromDateSameAsDisbursalDateEnabled(),
                loanApplicationTerms.getExpectedDisbursementDate());

        // Loan Schedule Exceptions that need to be applied for Loan Account
        LoanTermVariationParams termVariationParams = applyLoanTermVariations(loanApplicationTerms,
                scheduleParams, previousRepaymentDate, scheduledDueDate, interestRatesForInstallments,
                this.paymentPeriodsInOneYearCalculator, mc);

        scheduledDueDate = termVariationParams.getScheduledDueDate();
        // Updates total days in term
        scheduleParams.addLoanTermInDays(
                Days.daysBetween(scheduleParams.getPeriodStartDate(), scheduledDueDate).getDays());
        if (termVariationParams.isSkipPeriod()) {
            continue;
        }

        if (scheduleParams.getPeriodStartDate().isAfter(scheduledDueDate)) {
            throw new ScheduleDateException("Due date can't be before period start date", scheduledDueDate);
        }

        if (extendTermForDailyRepayments) {
            scheduleParams.setActualRepaymentDate(scheduledDueDate);
        }

        // this block is to generate the schedule till the specified
        // date(used for calculating preclosure)
        if (scheduleParams.getScheduleTillDate() != null
                && !scheduledDueDate.isBefore(scheduleParams.getScheduleTillDate())) {
            scheduledDueDate = scheduleParams.getScheduleTillDate();
            isNextRepaymentAvailable = false;
        }
        if (loanApplicationTerms.isInterestRecalculationEnabled()) {
            populateCompoundingDatesInPeriod(scheduleParams.getPeriodStartDate(), scheduledDueDate,
                    loanApplicationTerms, holidayDetailDTO, scheduleParams, loanCharges, currency);
        }

        // populates the collection with transactions till the due date of
        // the period for interest recalculation enabled loans
        Collection<RecalculationDetail> applicableTransactions = getApplicableTransactionsForPeriod(
                scheduleParams.applyInterestRecalculation(), scheduledDueDate, transactions);

        final double interestCalculationGraceOnRepaymentPeriodFraction = this.paymentPeriodsInOneYearCalculator
                .calculatePortionOfRepaymentPeriodInterestChargingGrace(periodStartDateApplicableForInterest,
                        scheduledDueDate, loanApplicationTerms.getInterestChargedFromLocalDate(),
                        loanApplicationTerms.getLoanTermPeriodFrequencyType(),
                        loanApplicationTerms.getRepaymentEvery());
        ScheduleCurrentPeriodParams currentPeriodParams = new ScheduleCurrentPeriodParams(currency,
                interestCalculationGraceOnRepaymentPeriodFraction);

        if (loanApplicationTerms.isMultiDisburseLoan()) {
            updateBalanceBasedOnDisbursement(loanApplicationTerms, chargesDueAtTimeOfDisbursement,
                    scheduleParams, periods, scheduledDueDate);
        }

        // process repayments to the schedule as per the repayment
        // transaction processor configuration
        // will add a new schedule with interest till the transaction date
        // for a loan repayment which falls between the
        // two periods for interest first repayment strategies
        handleRecalculationForNonDueDateTransactions(mc, loanApplicationTerms, loanCharges, holidayDetailDTO,
                scheduleParams, periods, loanApplicationTerms.getTotalInterestDue(), idealDisbursementDate,
                firstRepaymentdate, lastRestDate, scheduledDueDate, periodStartDateApplicableForInterest,
                applicableTransactions, currentPeriodParams);

        if (currentPeriodParams.isSkipCurrentLoop()) {
            continue;
        }
        periodStartDateApplicableForInterest = calculateInterestStartDateForPeriod(loanApplicationTerms,
                scheduleParams.getPeriodStartDate(), idealDisbursementDate, firstRepaymentdate,
                loanApplicationTerms.isInterestChargedFromDateSameAsDisbursalDateEnabled(),
                loanApplicationTerms.getExpectedDisbursementDate());

        // backup for pre-close transaction
        updateCompoundingDetails(scheduleParams, periodStartDateApplicableForInterest);

        // 5 determine principal,interest of repayment period
        PrincipalInterest principalInterestForThisPeriod = calculatePrincipalInterestComponentsForPeriod(
                this.paymentPeriodsInOneYearCalculator,
                currentPeriodParams.getInterestCalculationGraceOnRepaymentPeriodFraction(),
                scheduleParams.getTotalCumulativePrincipal().minus(scheduleParams.getReducePrincipal()),
                scheduleParams.getTotalCumulativeInterest(), loanApplicationTerms.getTotalInterestDue(),
                scheduleParams.getTotalOutstandingInterestPaymentDueToGrace(),
                scheduleParams.getOutstandingBalanceAsPerRest(), loanApplicationTerms,
                scheduleParams.getPeriodNumber(), mc, mergeVariationsToMap(scheduleParams),
                scheduleParams.getCompoundingMap(), periodStartDateApplicableForInterest, scheduledDueDate,
                interestRates);

        // will check for EMI amount greater than interest calculated
        if (loanApplicationTerms.getFixedEmiAmount() != null && loanApplicationTerms.getFixedEmiAmount()
                .compareTo(principalInterestForThisPeriod.interest().getAmount()) == -1) {
            String errorMsg = "EMI amount must be greater than : "
                    + principalInterestForThisPeriod.interest().getAmount();
            throw new MultiDisbursementEmiAmountException(errorMsg,
                    principalInterestForThisPeriod.interest().getAmount(),
                    loanApplicationTerms.getFixedEmiAmount());
        }

        // update cumulative fields for principal & interest
        currentPeriodParams.setInterestForThisPeriod(principalInterestForThisPeriod.interest());
        Money lastTotalOutstandingInterestPaymentDueToGrace = scheduleParams
                .getTotalOutstandingInterestPaymentDueToGrace();
        scheduleParams.setTotalOutstandingInterestPaymentDueToGrace(
                principalInterestForThisPeriod.interestPaymentDueToGrace());
        currentPeriodParams.setPrincipalForThisPeriod(principalInterestForThisPeriod.principal());

        // applies early payments on principal portion
        updatePrincipalPortionBasedOnPreviousEarlyPayments(currency, scheduleParams, currentPeriodParams);

        // updates amounts with current earlyPaidAmount
        updateAmountsBasedOnCurrentEarlyPayments(mc, loanApplicationTerms, scheduleParams, currentPeriodParams);

        if (scheduleParams.getOutstandingBalance().isLessThanZero() || !isNextRepaymentAvailable) {
            currentPeriodParams.plusPrincipalForThisPeriod(scheduleParams.getOutstandingBalance());
            scheduleParams.setOutstandingBalance(Money.zero(currency));
        }

        if (!isNextRepaymentAvailable) {
            scheduleParams.getDisburseDetailMap().clear();
        }

        // applies charges for the period
        applyChargesForCurrentPeriod(loanCharges, currency, scheduleParams, scheduledDueDate,
                currentPeriodParams);

        // sum up real totalInstallmentDue from components
        final Money totalInstallmentDue = currentPeriodParams.fetchTotalAmountForPeriod();

        // if previous installment is last then add interest to same
        // installment
        if (currentPeriodParams.getLastInstallment() != null
                && currentPeriodParams.getPrincipalForThisPeriod().isZero()) {
            currentPeriodParams.getLastInstallment()
                    .addInterestAmount(currentPeriodParams.getInterestForThisPeriod());
            continue;
        }

        // create repayment period from parts
        LoanScheduleModelPeriod installment = LoanScheduleModelRepaymentPeriod.repayment(
                scheduleParams.getInstalmentNumber(), scheduleParams.getPeriodStartDate(), scheduledDueDate,
                currentPeriodParams.getPrincipalForThisPeriod(), scheduleParams.getOutstandingBalance(),
                currentPeriodParams.getInterestForThisPeriod(),
                currentPeriodParams.getFeeChargesForInstallment(),
                currentPeriodParams.getPenaltyChargesForInstallment(), totalInstallmentDue, false);

        addLoanRepaymentScheduleInstallment(scheduleParams.getInstallments(), installment);
        // apply loan transactions on installments to identify early/late
        // payments for interest recalculation
        installment = handleRecalculationForTransactions(mc, loanApplicationTerms, holidayDetailDTO, currency,
                scheduleParams, loanRepaymentScheduleTransactionProcessor,
                loanApplicationTerms.getTotalInterestDue(), lastRestDate, scheduledDueDate,
                periodStartDateApplicableForInterest, applicableTransactions, currentPeriodParams,
                lastTotalOutstandingInterestPaymentDueToGrace, installment, loanCharges);
        periods.add(installment);

        // Updates principal paid map with efective date for reducing
        // the amount from outstanding balance(interest calculation)
        updateAmountsWithEffectiveDate(loanApplicationTerms, holidayDetailDTO, scheduleParams, scheduledDueDate,
                currentPeriodParams, installment, lastRestDate);

        // handle cumulative fields

        scheduleParams.addTotalCumulativePrincipal(currentPeriodParams.getPrincipalForThisPeriod());
        scheduleParams.addTotalRepaymentExpected(totalInstallmentDue);
        scheduleParams.addTotalCumulativeInterest(currentPeriodParams.getInterestForThisPeriod());
        scheduleParams.setPeriodStartDate(scheduledDueDate);
        scheduleParams.incrementInstalmentNumber();
        scheduleParams.incrementPeriodNumber();
        if (termVariationParams.isRecalculateAmounts()) {
            loanApplicationTerms.setCurrentPeriodFixedEmiAmount(null);
            loanApplicationTerms.setCurrentPeriodFixedPrincipalAmount(null);
            adjustInstallmentOrPrincipalAmount(loanApplicationTerms,
                    scheduleParams.getTotalCumulativePrincipal(), scheduleParams.getPeriodNumber(), mc);
        }
    }

    // this condition is to add the interest from grace period if not
    // already applied.
    if (scheduleParams.getTotalOutstandingInterestPaymentDueToGrace().isGreaterThanZero()) {
        LoanScheduleModelPeriod installment = ((List<LoanScheduleModelPeriod>) periods).get(periods.size() - 1);
        installment.addInterestAmount(scheduleParams.getTotalOutstandingInterestPaymentDueToGrace());
        scheduleParams.addTotalRepaymentExpected(scheduleParams.getTotalOutstandingInterestPaymentDueToGrace());
        scheduleParams
                .addTotalCumulativeInterest(scheduleParams.getTotalOutstandingInterestPaymentDueToGrace());
        scheduleParams.setTotalOutstandingInterestPaymentDueToGrace(Money.zero(currency));
    }

    // determine fees and penalties for charges which depends on total
    // loan interest
    updatePeriodsWithCharges(currency, scheduleParams, periods, nonCompoundingCharges);

    // this block is to add extra re-payment schedules with interest portion
    // if the loan not paid with in loan term

    if (scheduleParams.getScheduleTillDate() != null) {
        currentDate = scheduleParams.getScheduleTillDate();
    }
    if (scheduleParams.applyInterestRecalculation() && scheduleParams.getLatePaymentMap().size() > 0
            && currentDate.isAfter(scheduleParams.getPeriodStartDate())) {
        Money totalInterest = addInterestOnlyRepaymentScheduleForCurrentdate(mc, loanApplicationTerms,
                holidayDetailDTO, currency, periods, currentDate, loanRepaymentScheduleTransactionProcessor,
                transactions, loanCharges, scheduleParams);
        scheduleParams.addTotalCumulativeInterest(totalInterest);
    }

    loanApplicationTerms.resetFixedEmiAmount();
    final BigDecimal totalPrincipalPaid = BigDecimal.ZERO;
    final BigDecimal totalOutstanding = BigDecimal.ZERO;

    updateCompoundingDetails(periods, scheduleParams, loanApplicationTerms);
    return LoanScheduleModel.from(periods, applicationCurrency, scheduleParams.getLoanTermInDays(),
            scheduleParams.getPrincipalToBeScheduled(),
            scheduleParams.getTotalCumulativePrincipal().getAmount(), totalPrincipalPaid,
            scheduleParams.getTotalCumulativeInterest().getAmount(),
            scheduleParams.getTotalFeeChargesCharged().getAmount(),
            scheduleParams.getTotalPenaltyChargesCharged().getAmount(),
            scheduleParams.getTotalRepaymentExpected().getAmount(), totalOutstanding);
}

From source file:com.gst.portfolio.loanaccount.loanschedule.domain.AbstractLoanScheduleGenerator.java

License:Apache License

private void updateCompoundingMap(final LoanApplicationTerms loanApplicationTerms,
        final HolidayDetailDTO holidayDetailDTO, final LoanScheduleParams params, final LocalDate lastRestDate,
        final LocalDate scheduledDueDate) {
    if (loanApplicationTerms.isInterestRecalculationEnabled()
            && loanApplicationTerms.getInterestRecalculationCompoundingMethod().isCompoundingEnabled()) {
        final MonetaryCurrency currency = params.getCurrency();
        Money totalCompoundedAmount = Money.zero(currency);
        boolean lastInstallmentIsPastDate = false;
        for (LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment : params.getInstallments()) {
            if (params.getCompoundingDateVariations()
                    .containsKey(loanRepaymentScheduleInstallment.getFromDate())) {
                lastInstallmentIsPastDate = params.applyInterestRecalculation()
                        && loanRepaymentScheduleInstallment.getDueDate()
                                .isBefore(DateUtils.getLocalDateOfTenant());
            } else {
                final boolean isPastDate = params.applyInterestRecalculation()
                        && loanRepaymentScheduleInstallment.getDueDate()
                                .isBefore(DateUtils.getLocalDateOfTenant());
                boolean periodHasCompoundingDate = false;
                Money amountCharged = Money.zero(currency);
                if (loanApplicationTerms.getInterestRecalculationCompoundingMethod() != null) {
                    amountCharged = getIncomeForCompounding(loanApplicationTerms, currency,
                            loanRepaymentScheduleInstallment);
                }/*from  w  ww  . ja v  a 2s. c om*/
                final Map<LocalDate, Money> compoundingMap = params.getCompoundingMap();
                LocalDate effectiveStartDate = loanRepaymentScheduleInstallment.getFromDate();
                if (loanApplicationTerms.allowCompoundingOnEod()) {
                    effectiveStartDate = loanRepaymentScheduleInstallment.getFromDate().minusDays(1);
                }
                LocalDate compoundingEffectiveDate = getNextCompoundScheduleDate(effectiveStartDate,
                        loanApplicationTerms, holidayDetailDTO);
                final LocalDate restDate = getNextRestScheduleDate(scheduledDueDate.minusDays(1),
                        loanApplicationTerms, holidayDetailDTO);
                if (!compoundingEffectiveDate.isAfter(loanRepaymentScheduleInstallment.getDueDate())) {
                    Money amountCompoundedFromLastPeriod = params.getCompoundedInLastInstallment();
                    if (amountCompoundedFromLastPeriod.isZero()) {
                        amountCompoundedFromLastPeriod = params.getUnCompoundedAmount();
                    }
                    totalCompoundedAmount = totalCompoundedAmount.minus(amountCompoundedFromLastPeriod);
                    periodHasCompoundingDate = true;
                }
                while (!compoundingEffectiveDate.isAfter(loanRepaymentScheduleInstallment.getDueDate())) {
                    if (compoundingEffectiveDate.isEqual(loanRepaymentScheduleInstallment.getDueDate())) {
                        Money amountToBeCompounding = amountCharged.minus(totalCompoundedAmount);
                        updateMapWithAmount(compoundingMap, amountToBeCompounding, compoundingEffectiveDate);
                        totalCompoundedAmount = totalCompoundedAmount.plus(amountToBeCompounding);

                    } else if (compoundingMap.containsKey(compoundingEffectiveDate)) {
                        Money compounedAmount = compoundingMap.get(compoundingEffectiveDate);
                        totalCompoundedAmount = totalCompoundedAmount.plus(compounedAmount);
                    }

                    if (!loanApplicationTerms.allowCompoundingOnEod()) {
                        compoundingEffectiveDate = compoundingEffectiveDate.plusDays(1);
                    }
                    compoundingEffectiveDate = getNextCompoundScheduleDate(compoundingEffectiveDate,
                            loanApplicationTerms, holidayDetailDTO);
                }
                if (periodHasCompoundingDate) {
                    if (isPastDate) {
                        updateMapWithAmount(params.getPrincipalPortionMap(),
                                totalCompoundedAmount.plus(params.getUnCompoundedAmount()), lastRestDate);
                    } else {
                        Money amountToBeEffected = amountCharged;
                        if (lastInstallmentIsPastDate) {
                            amountToBeEffected = amountToBeEffected.plus(params.getUnCompoundedAmount());
                        }
                        updateMapWithAmount(params.getPrincipalPortionMap(), amountToBeEffected, restDate);
                    }
                }
                if (totalCompoundedAmount.isGreaterThanZero()) {
                    params.getCompoundingDateVariations().put(loanRepaymentScheduleInstallment.getFromDate(),
                            new TreeMap<>(params.getCompoundingMap()));
                    for (Map.Entry<LocalDate, Money> mapEntry : params.getCompoundingMap().entrySet()) {
                        if (!mapEntry.getKey().isAfter(loanRepaymentScheduleInstallment.getDueDate())) {
                            updateMapWithAmount(params.getPrincipalPortionMap(), mapEntry.getValue().negated(),
                                    mapEntry.getKey());
                        }
                    }
                    params.minusUnCompoundedAmount(params.getUnCompoundedAmount());
                    params.getCompoundingMap().clear();
                    params.addUnCompoundedAmount(amountCharged.minus(totalCompoundedAmount));
                } else {
                    params.getCompoundingMap().clear();
                    params.getCompoundingDateVariations().put(loanRepaymentScheduleInstallment.getFromDate(),
                            new TreeMap<>(params.getCompoundingMap()));
                    params.addUnCompoundedAmount(amountCharged);
                }
                params.setCompoundedInLastInstallment(amountCharged.zero());
                lastInstallmentIsPastDate = isPastDate;
            }

        }
    }

}

From source file:com.gst.portfolio.loanaccount.loanschedule.domain.AbstractLoanScheduleGenerator.java

License:Apache License

/**
 * calculates Interest stating date as per the settings
 * /*from   w  ww .  ja va  2 s  . c  o m*/
 * @param firstRepaymentdate
 *            TODO
 * @param boolean1
 * @param localDate
 */
private LocalDate calculateInterestStartDateForPeriod(final LoanApplicationTerms loanApplicationTerms,
        LocalDate periodStartDate, final LocalDate idealDisbursementDate, final LocalDate firstRepaymentdate,
        final Boolean isInterestChargedFromDateSameAsDisbursalDateEnabled,
        final LocalDate expectedDisbursementDate) {
    LocalDate periodStartDateApplicableForInterest = periodStartDate;
    if (periodStartDate.isBefore(idealDisbursementDate) || firstRepaymentdate.isAfter(periodStartDate)) {
        if (loanApplicationTerms.getInterestChargedFromLocalDate() != null) {
            if (periodStartDate.isEqual(loanApplicationTerms.getExpectedDisbursementDate())
                    || loanApplicationTerms.getInterestChargedFromLocalDate().isAfter(periodStartDate)) {
                periodStartDateApplicableForInterest = loanApplicationTerms.getInterestChargedFromLocalDate();
            }
        } else if (loanApplicationTerms.getInterestChargedFromLocalDate() == null
                && isInterestChargedFromDateSameAsDisbursalDateEnabled) {
            periodStartDateApplicableForInterest = expectedDisbursementDate;
        } else if (periodStartDate.isEqual(loanApplicationTerms.getExpectedDisbursementDate())) {
            periodStartDateApplicableForInterest = idealDisbursementDate;
        }
    }
    return periodStartDateApplicableForInterest;
}

From source file:com.gst.portfolio.loanaccount.loanschedule.domain.DefaultScheduledDateGenerator.java

License:Apache License

@Override
public LocalDate generateNextScheduleDateStartingFromDisburseDate(LocalDate lastRepaymentDate,
        LoanApplicationTerms loanApplicationTerms, final HolidayDetailDTO holidayDetailDTO) {

    LocalDate generatedDate = loanApplicationTerms.getExpectedDisbursementDate();
    boolean isFirstRepayment = true;
    while (!generatedDate.isAfter(lastRepaymentDate)) {
        generatedDate = generateNextRepaymentDate(generatedDate, loanApplicationTerms, isFirstRepayment,
                holidayDetailDTO);/*  w w w.ja v a  2  s  . c  o m*/
        isFirstRepayment = false;
    }
    generatedDate = adjustRepaymentDate(generatedDate, loanApplicationTerms, holidayDetailDTO);
    return generatedDate;
}

From source file:com.gst.portfolio.loanaccount.loanschedule.service.LoanScheduleAssembler.java

License:Apache License

private LocalDate deriveFirstRepaymentDate(final AccountType loanType, final Integer repaymentEvery,
        final LocalDate expectedDisbursementDate, final PeriodFrequencyType repaymentPeriodFrequencyType,
        final Integer minimumDaysBetweenDisbursalAndFirstRepayment, final Calendar calendar) {

    LocalDate derivedFirstRepayment = null;

    final LocalDate dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment = expectedDisbursementDate
            .plusDays(minimumDaysBetweenDisbursalAndFirstRepayment);

    if (calendar != null) {

        final LocalDate refernceDateForCalculatingFirstRepaymentDate = expectedDisbursementDate;
        derivedFirstRepayment = deriveFirstRepaymentDateForLoans(repaymentEvery, expectedDisbursementDate,
                refernceDateForCalculatingFirstRepaymentDate, repaymentPeriodFrequencyType,
                minimumDaysBetweenDisbursalAndFirstRepayment, calendar);

    } /*** Individual or group account, or JLG not linked to a meeting ***/
    else {/*from  w ww .ja  v  a2  s . c o  m*/
        LocalDate dateBasedOnRepaymentFrequency;
        // Derive the first repayment date as greater date among
        // (disbursement date + plus frequency) or
        // (disbursement date + minimum between disbursal and first
        // repayment )
        if (repaymentPeriodFrequencyType.isDaily()) {
            dateBasedOnRepaymentFrequency = expectedDisbursementDate.plusDays(repaymentEvery);
        } else if (repaymentPeriodFrequencyType.isWeekly()) {
            dateBasedOnRepaymentFrequency = expectedDisbursementDate.plusWeeks(repaymentEvery);
        } else if (repaymentPeriodFrequencyType.isMonthly()) {
            dateBasedOnRepaymentFrequency = expectedDisbursementDate.plusMonths(repaymentEvery);
        } /** yearly loan **/
        else {
            dateBasedOnRepaymentFrequency = expectedDisbursementDate.plusYears(repaymentEvery);
        }
        derivedFirstRepayment = dateBasedOnRepaymentFrequency.isAfter(
                dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment) ? dateBasedOnRepaymentFrequency
                        : dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment;
    }

    return derivedFirstRepayment;
}

From source file:com.gst.portfolio.loanaccount.serialization.CalculateLoanScheduleQueryFromApiJsonHelper.java

License:Apache License

private void validateRepaymentsStartingFromDateIsAfterDisbursementDate(
        final List<ApiParameterError> dataValidationErrors, final LocalDate expectedDisbursementDate,
        final LocalDate repaymentsStartingFromDate) {
    if (expectedDisbursementDate != null) {
        if (repaymentsStartingFromDate != null
                && expectedDisbursementDate.isAfter(repaymentsStartingFromDate)) {
            final ApiParameterError error = ApiParameterError.parameterError(
                    "validation.msg.loan.expectedDisbursementDate.cannot.be.after.first.repayment.date",
                    "The parameter expectedDisbursementDate has a date which falls after the date for repaymentsStartingFromDate.",
                    "expectedDisbursementDate", expectedDisbursementDate, repaymentsStartingFromDate);
            dataValidationErrors.add(error);
        }// www  .  ja v  a 2s. com
    }
}

From source file:com.gst.portfolio.loanaccount.serialization.LoanApplicationCommandFromApiJsonHelper.java

License:Apache License

private void validateDisbursementsAreDatewiseOrdered(JsonElement element,
        final DataValidatorBuilder baseDataValidator) {
    final JsonObject topLevelJsonElement = element.getAsJsonObject();
    final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(topLevelJsonElement);
    final String dateFormat = this.fromApiJsonHelper.extractDateFormatParameter(topLevelJsonElement);
    final JsonArray variationArray = this.fromApiJsonHelper
            .extractJsonArrayNamed(LoanApiConstants.disbursementDataParameterName, element);
    if (variationArray != null) {
        for (int i = 0; i < variationArray.size(); i++) {
            final JsonObject jsonObject1 = variationArray.get(i).getAsJsonObject();
            if (jsonObject1.has(LoanApiConstants.disbursementDateParameterName)) {
                LocalDate date1 = this.fromApiJsonHelper.extractLocalDateNamed(
                        LoanApiConstants.disbursementDateParameterName, jsonObject1, dateFormat, locale);

                for (int j = i + 1; j < variationArray.size(); j++) {
                    final JsonObject jsonObject2 = variationArray.get(j).getAsJsonObject();
                    if (jsonObject2.has(LoanApiConstants.disbursementDateParameterName)) {
                        LocalDate date2 = this.fromApiJsonHelper.extractLocalDateNamed(
                                LoanApiConstants.disbursementDateParameterName, jsonObject2, dateFormat,
                                locale);
                        if (date1.isAfter(date2)) {
                            baseDataValidator.reset().parameter(LoanApiConstants.disbursementDataParameterName)
                                    .failWithCode(LoanApiConstants.DISBURSEMENT_DATES_NOT_IN_ORDER);
                        }//from   w w w .  ja  va  2s.c  om
                    }
                }
            }

        }
    }
}

From source file:com.gst.portfolio.loanaccount.service.LoanApplicationWritePlatformServiceJpaRepositoryImpl.java

License:Apache License

private void validateSubmittedOnDate(final Loan loan) {
    final LocalDate startDate = loan.loanProduct().getStartDate();
    final LocalDate closeDate = loan.loanProduct().getCloseDate();
    final LocalDate expectedFirstRepaymentOnDate = loan.getExpectedFirstRepaymentOnDate();
    final LocalDate submittedOnDate = loan.getSubmittedOnDate();

    String defaultUserMessage = "";
    if (startDate != null && submittedOnDate.isBefore(startDate)) {
        defaultUserMessage = "submittedOnDate cannot be before the loan product startDate.";
        throw new LoanApplicationDateException("submitted.on.date.cannot.be.before.the.loan.product.start.date",
                defaultUserMessage, submittedOnDate.toString(), startDate.toString());
    }/*from w  ww.  j av a 2 s  .  c  om*/

    if (closeDate != null && submittedOnDate.isAfter(closeDate)) {
        defaultUserMessage = "submittedOnDate cannot be after the loan product closeDate.";
        throw new LoanApplicationDateException("submitted.on.date.cannot.be.after.the.loan.product.close.date",
                defaultUserMessage, submittedOnDate.toString(), closeDate.toString());
    }

    if (expectedFirstRepaymentOnDate != null && submittedOnDate.isAfter(expectedFirstRepaymentOnDate)) {
        defaultUserMessage = "submittedOnDate cannot be after the loans  expectedFirstRepaymentOnDate.";
        throw new LoanApplicationDateException(
                "submitted.on.date.cannot.be.after.the.loan.expected.first.repayment.date", defaultUserMessage,
                submittedOnDate.toString(), expectedFirstRepaymentOnDate.toString());
    }
}

From source file:com.gst.portfolio.loanaccount.service.LoanArrearsAgingServiceImpl.java

License:Apache License

private String constructUpdateStatement(final Loan loan, boolean isInsertStatement) {
    String updateSql = null;/*from ww w .  j  ava2  s.  com*/
    List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
    BigDecimal principalOverdue = BigDecimal.ZERO;
    BigDecimal interestOverdue = BigDecimal.ZERO;
    BigDecimal feeOverdue = BigDecimal.ZERO;
    BigDecimal penaltyOverdue = BigDecimal.ZERO;
    LocalDate overDueSince = LocalDate.now();
    for (LoanRepaymentScheduleInstallment installment : installments) {
        if (installment.getDueDate().isBefore(LocalDate.now())) {
            principalOverdue = principalOverdue
                    .add(installment.getPrincipalOutstanding(loan.getCurrency()).getAmount());
            interestOverdue = interestOverdue
                    .add(installment.getInterestOutstanding(loan.getCurrency()).getAmount());
            feeOverdue = feeOverdue.add(installment.getFeeChargesOutstanding(loan.getCurrency()).getAmount());
            penaltyOverdue = penaltyOverdue
                    .add(installment.getPenaltyChargesOutstanding(loan.getCurrency()).getAmount());
            if (installment.isNotFullyPaidOff() && overDueSince.isAfter(installment.getDueDate())) {
                overDueSince = installment.getDueDate();
            }
        }
    }

    BigDecimal totalOverDue = principalOverdue.add(interestOverdue).add(feeOverdue).add(penaltyOverdue);
    if (totalOverDue.compareTo(BigDecimal.ZERO) == 1) {
        if (isInsertStatement) {
            updateSql = constructInsertStatement(loan.getId(), principalOverdue, interestOverdue, feeOverdue,
                    penaltyOverdue, overDueSince);
        } else {
            updateSql = constructUpdateStatement(loan.getId(), principalOverdue, interestOverdue, feeOverdue,
                    penaltyOverdue, overDueSince);
        }
    }
    return updateSql;
}