List of usage examples for org.joda.time LocalDate isAfter
public boolean isAfter(ReadablePartial partial)
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; }