diff --git a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java index b2de4d1bda9..5415d9ce4c2 100644 --- a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java +++ b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/DateUtils.java @@ -335,6 +335,10 @@ public static boolean isOnOrAfter(LocalDate first, LocalDate second) { return first != null && (second == null || first.isAfter(second) || first.isEqual(second)); } + public static boolean isOnOrBefore(LocalDate first, LocalDate second) { + return second != null && (first == null || first.isBefore(second) || first.isEqual(second)); + } + public static long getDifferenceInDays(final LocalDate localDateBefore, final LocalDate localDateAfter) { return DAYS.between(localDateBefore, localDateAfter); } diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java index 39ed1b99e0c..cb314079a5f 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java @@ -4248,16 +4248,16 @@ private Money calculateTotalOverpayment() { // if total paid in transactions doesnt match repayment schedule then // theres an overpayment. Money overpaid = totalPaidInRepayments.minus(cumulativeTotalPaidOnInstallments); - if (overpaid.isZero()) { - Money totalPrincipalPaid = Money.zero(this.getCurrency()); - for (final LoanRepaymentScheduleInstallment scheduledRepayment : installments) { - totalPrincipalPaid = totalPrincipalPaid.add( - scheduledRepayment.getPrincipalCompleted(this.getCurrency()).plus(scheduledRepayment.getAdvancePrincipalAmount())); - } - if (totalPrincipalPaid.isGreaterThan(this.getPrincipal())) { - overpaid = totalPrincipalPaid.minus(this.getPrincipal()); - } - } + + /* + * // This code was added initially under SU-320 to handle overpayments but later on it is no longer needed + * based on the way overpayment is now handled if (overpaid.isZero()) { Money totalPrincipalPaid = + * Money.zero(this.getCurrency()); for (final LoanRepaymentScheduleInstallment scheduledRepayment : + * installments) { totalPrincipalPaid = totalPrincipalPaid.add( + * scheduledRepayment.getPrincipalCompleted(this.getCurrency()).plus(scheduledRepayment. + * getAdvancePrincipalAmount())); } if (totalPrincipalPaid.isGreaterThan(this.getPrincipal())) { overpaid = + * totalPrincipalPaid.minus(this.getPrincipal()); } } + */ return overpaid; } diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java index ceea2793cd5..508e33911c4 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java @@ -1258,7 +1258,7 @@ private Money processAllocationsHorizontally(LoanTransaction loanTransaction, Mo if (transactionAmountUnprocessed.isGreaterThanZero()) { if (inAdvanceInstallment.isLastInstallment(installments) && inAdvanceInstallment.isOverpaidInAdvance(currency) && transactionAmountUnprocessed - .isGreaterThan(inAdvanceInstallment.getPrincipal(currency))) { + .isGreaterThanOrEqualTo(inAdvanceInstallment.getPrincipal(currency))) { // This MUST be true only in case of advance overpayment after repayment // schedule is regenerated // Process principal and move the remaining amount to overpaid diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/ExtrasSheetPopulator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/ExtrasSheetPopulator.java index 34871012450..d86b435d31a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/ExtrasSheetPopulator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/bulkimport/populator/ExtrasSheetPopulator.java @@ -92,28 +92,32 @@ public void populate(Workbook workbook, String dateFormat) { writeString(CURRENCY_CODE_COL, row, currencies.getCode()); } int channelRowIndex = 1; - for (ChannelData channelData : channelOptions) { - Row row; - if (channelRowIndex < currencyCodeRowIndex || currencyCodeRowIndex < paymentTypeRowIndex - || currencyCodeRowIndex < fundRowIndex) { - row = extrasSheet.getRow(channelRowIndex++); - } else { - row = extrasSheet.createRow(channelRowIndex++); + if (channelOptions != null) { + for (ChannelData channelData : channelOptions) { + Row row; + if (channelRowIndex < currencyCodeRowIndex || currencyCodeRowIndex < paymentTypeRowIndex + || currencyCodeRowIndex < fundRowIndex) { + row = extrasSheet.getRow(channelRowIndex++); + } else { + row = extrasSheet.createRow(channelRowIndex++); + } + writeLong(CHANNEL_ID_COL, row, channelData.getId()); + writeString(CHANNEL_NAME_COL, row, channelData.getName().trim().replaceAll("[ )(]", "_")); } - writeLong(CHANNEL_ID_COL, row, channelData.getId()); - writeString(CHANNEL_NAME_COL, row, channelData.getName().trim().replaceAll("[ )(]", "_")); } int bankRowIndex = 1; - for (CodeValueData bankCodeValueData : bankOptions) { - Row row; - if (bankRowIndex < channelRowIndex || channelRowIndex < currencyCodeRowIndex || currencyCodeRowIndex < paymentTypeRowIndex - || currencyCodeRowIndex < fundRowIndex) { - row = extrasSheet.getRow(bankRowIndex++); - } else { - row = extrasSheet.createRow(bankRowIndex++); + if (bankOptions != null) { + for (CodeValueData bankCodeValueData : bankOptions) { + Row row; + if (bankRowIndex < channelRowIndex || channelRowIndex < currencyCodeRowIndex || currencyCodeRowIndex < paymentTypeRowIndex + || currencyCodeRowIndex < fundRowIndex) { + row = extrasSheet.getRow(bankRowIndex++); + } else { + row = extrasSheet.createRow(bankRowIndex++); + } + writeLong(BANK_ID_COL, row, bankCodeValueData.getId()); + writeString(BANK_NAME_COL, row, bankCodeValueData.getName().trim().replaceAll("[ )(]", "_")); } - writeLong(BANK_ID_COL, row, bankCodeValueData.getId()); - writeString(BANK_NAME_COL, row, bankCodeValueData.getName().trim().replaceAll("[ )(]", "_")); } extrasSheet.protectSheet(""); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java index 6e8611b9889..54443a038ea 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java @@ -3071,7 +3071,9 @@ private LoanScheduleDTO rescheduleNextInstallmentsForProgressiveLoans(final Math } } // Extra amount paid in advance - if (outstandingBalance.isLessThanZero()) { + if (outstandingBalance.isZero() || outstandingBalance.isLessThanZero()) { + // Check outstandingBalance.isZero() in case customer pays exact amount equal to outstanding + // balance // If overpaid in advance then add the last installment to keep track of advance payment amount outstandingBalanceAsPerRest = outstandingBalance.zero(); outstandingBalance = outstandingBalance.zero(); @@ -3283,7 +3285,7 @@ private LoanScheduleDTO rescheduleNextInstallmentsForProgressiveLoans(final Math .plus(totalPenaltyChargesCharged); // for partial schedule generation - if (!newRepaymentScheduleInstallments.isEmpty() && totalCumulativeInterest.isGreaterThanZero()) { + if (!newRepaymentScheduleInstallments.isEmpty()) { Money totalOutstandingInterestPaymentDueToGrace = Money.zero(currency); loanScheduleParams = LoanScheduleParams.createLoanScheduleParamsForPartialUpdate(periodNumber, instalmentNumber, loanTermInDays, periodStartDate, actualRepaymentDate, totalCumulativePrincipal, totalCumulativeInterest, @@ -3362,7 +3364,7 @@ private List fetchRetainedInstallmentsForProgr MonetaryCurrency currency) { List newRepaymentScheduleInstallments = new ArrayList<>(); for (LoanRepaymentScheduleInstallment installment : repaymentScheduleInstallments) { - if (DateUtils.isBefore(installment.getFromDate(), rescheduleFrom)) { + if (DateUtils.isOnOrBefore(installment.getFromDate(), rescheduleFrom)) { newRepaymentScheduleInstallments.add(installment); } else { // Check if there is any installment having advance payment then add the installment to calculate