diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java index 7e3060e1b..529ad40c7 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java @@ -836,6 +836,9 @@ public class Loan extends AbstractPersistable { */ private BigDecimal calculateAmountPercentageAppliedTo(final LoanCharge loanCharge) { BigDecimal amount = BigDecimal.ZERO; + if(loanCharge.isOverdueInstallmentCharge()){ + return loanCharge.getAmountPercentageAppliedTo(); + } switch (loanCharge.getChargeCalculation()) { case PERCENT_OF_AMOUNT: amount = getPrincpal().getAmount(); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java index 2515994a0..02f8df98e 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java @@ -1482,6 +1482,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { final StringBuilder sqlBuilder = new StringBuilder(400); sqlBuilder.append("select ").append(rm.schema()).append(" where DATE_SUB(CURDATE(),INTERVAL ? DAY) > ls.duedate ") .append(" and ls.completed_derived <> 1 and mc.charge_applies_to_enum =1 ") + .append(" and ls.recalculated_interest_component <> 1 ") .append(" and mc.charge_time_enum = 9 and ml.loan_status_id = 300 "); if (backdatePenalties) { return this.jdbcTemplate.query(sqlBuilder.toString(), rm, new Object[] { penaltyWaitPeriod }); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 1ce5db5d2..193c11720 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -2474,6 +2474,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final List existingReversedTransactionIds = new ArrayList<>(); boolean runInterestRecalculation = false; LocalDate recalculateFrom = DateUtils.getLocalDateOfTenant(); + LocalDate lastChargeDate = null; for (final OverdueLoanScheduleData overdueInstallment : overdueLoanScheduleDatas) { final JsonElement parsedCommand = this.fromApiJsonHelper.parse(overdueInstallment.toString()); @@ -2486,6 +2487,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf if (recalculateFrom.isAfter(overdueDTO.getRecalculateFrom())) { recalculateFrom = overdueDTO.getRecalculateFrom(); } + if (lastChargeDate == null || overdueDTO.getLastChargeAppliedDate().isAfter(lastChargeDate)) { + lastChargeDate = overdueDTO.getLastChargeAppliedDate(); + } } if (loan != null) { boolean reprocessRequired = true; @@ -2503,6 +2507,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf } if (reprocessRequired) { + addInstallmentIfPenaltyAppliedAfterLastDueDate(loan, lastChargeDate); ChangedTransactionDetail changedTransactionDetail = loan.reprocessTransactions(); if (changedTransactionDetail != null) { for (final Map.Entry mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) { @@ -2528,6 +2533,28 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf } } + private void addInstallmentIfPenaltyAppliedAfterLastDueDate(Loan loan, LocalDate lastChargeDate) { + if (lastChargeDate != null) { + List installments = loan.fetchRepaymentScheduleInstallments(); + LoanRepaymentScheduleInstallment lastInstallment = loan.fetchRepaymentScheduleInstallment(installments.size()); + if (lastChargeDate.isAfter(lastInstallment.getDueDate())) { + if (lastInstallment.isRecalculatedInterestComponent()) { + installments.remove(lastInstallment); + lastInstallment = loan.fetchRepaymentScheduleInstallment(installments.size()); + } + boolean recalculatedInterestComponent = true; + BigDecimal principal = BigDecimal.ZERO; + BigDecimal interest = BigDecimal.ZERO; + BigDecimal feeCharges = BigDecimal.ZERO; + BigDecimal penaltyCharges = BigDecimal.ONE; + LoanRepaymentScheduleInstallment newEntry = new LoanRepaymentScheduleInstallment(loan, installments.size() + 1, + lastInstallment.getDueDate(), lastChargeDate, principal, interest, feeCharges, penaltyCharges, + recalculatedInterestComponent); + installments.add(newEntry); + } + } + } + public LoanOverdueDTO applyChargeToOverdueLoanInstallment(final Long loanId, final Long loanChargeId, final Integer periodNumber, final JsonCommand command, Loan loan, final List existingTransactionIds, final List existingReversedTransactionIds) { boolean runInterestRecalculation = false; @@ -2565,6 +2592,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf } LoanRepaymentScheduleInstallment installment = null; + LocalDate lastChargeAppliedDate = dueDate; if (!scheduleDates.isEmpty()) { if (loan == null) { loan = this.loanAssembler.assembleFrom(loanId); @@ -2573,8 +2601,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds()); } installment = loan.fetchRepaymentScheduleInstallment(periodNumber); + lastChargeAppliedDate = installment.getDueDate(); } LocalDate recalculateFrom = DateUtils.getLocalDateOfTenant(); + if (loan != null) { this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.LOAN_APPLY_OVERDUE_CHARGE, constructEntityMap(BUSINESS_ENTITY.LOAN, loan)); @@ -2591,10 +2621,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf if (entry.getValue().isBefore(recalculateFrom)) { recalculateFrom = entry.getValue(); } + if (entry.getValue().isAfter(lastChargeAppliedDate)) { + lastChargeAppliedDate = entry.getValue(); + } } } - return new LoanOverdueDTO(loan, runInterestRecalculation, recalculateFrom); + return new LoanOverdueDTO(loan, runInterestRecalculation, recalculateFrom, lastChargeAppliedDate); } @Override @@ -3079,11 +3112,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf boolean isFloatingInterestRate = loan.getIsFloatingInterestRate(); BigDecimal interestRateDiff = loan.getInterestRateDifferential(); List baseLendingRatePeriods = null; - try{ - baseLendingRatePeriods = this.floatingRatesReadPlatformService.retrieveBaseLendingRate() - .getRatePeriods(); - }catch(final FloatingRateNotFoundException ex){ - // Do not do anything + try { + baseLendingRatePeriods = this.floatingRatesReadPlatformService.retrieveBaseLendingRate().getRatePeriods(); + } catch (final FloatingRateNotFoundException ex) { + // Do not do anything } floatingRateDTO = new FloatingRateDTO(isFloatingInterestRate, loan.getDisbursementDate(), interestRateDiff, baseLendingRatePeriods); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/LoanOverdueDTO.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/LoanOverdueDTO.java index 50915a319..18c24f2ed 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/LoanOverdueDTO.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/data/LoanOverdueDTO.java @@ -13,11 +13,14 @@ public class LoanOverdueDTO { private final Loan loan; private final boolean runInterestRecalculation; private final LocalDate recalculateFrom; + private final LocalDate lastChargeAppliedDate; - public LoanOverdueDTO(final Loan loan, final boolean runInterestRecalculation, final LocalDate recalculateFrom) { + public LoanOverdueDTO(final Loan loan, final boolean runInterestRecalculation, final LocalDate recalculateFrom, + final LocalDate lastChargeAppliedDate) { this.loan = loan; this.runInterestRecalculation = runInterestRecalculation; this.recalculateFrom = recalculateFrom; + this.lastChargeAppliedDate = lastChargeAppliedDate; } public boolean isRunInterestRecalculation() { @@ -28,8 +31,12 @@ public class LoanOverdueDTO { return this.loan; } - public LocalDate getRecalculateFrom() { return this.recalculateFrom; } + + + public LocalDate getLastChargeAppliedDate() { + return this.lastChargeAppliedDate; + } }