diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java index d6ad0e5fc8f..c09a71479e2 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java @@ -64,6 +64,11 @@ public CollectionData getOverdueCollectionData(final Loan loan, List 0) { @@ -248,8 +266,17 @@ private CollectionData calculateDelinquencyDataForOverdueInstallment(final Loan LocalDate overdueSinceDate = null; CollectionData collectionData = CollectionData.template(); BigDecimal outstandingAmount = BigDecimal.ZERO; + BigDecimal delinquentPrincipal = BigDecimal.ZERO; + BigDecimal delinquentInterest = BigDecimal.ZERO; + BigDecimal delinquentFee = BigDecimal.ZERO; + BigDecimal delinquentPenalty = BigDecimal.ZERO; outstandingAmount = outstandingAmount.add(installment.getTotalOutstanding(loanCurrency).getAmount()); + delinquentPrincipal = delinquentPrincipal.add(installment.getPrincipalOutstanding(loanCurrency).getAmount()); + delinquentInterest = delinquentInterest.add(installment.getInterestOutstanding(loanCurrency).getAmount()); + delinquentFee = delinquentFee.add(installment.getFeeChargesOutstanding(loanCurrency).getAmount()); + delinquentPenalty = delinquentPenalty.add(installment.getPenaltyChargesOutstanding(loanCurrency).getAmount()); + overdueSinceDate = installment.getDueDate(); BigDecimal amountAvailable = installment.getTotalPaid(loanCurrency).getAmount(); boolean isLatestInstallment = Objects.equals(installment.getId(), latestInstallment.getId()); @@ -272,6 +299,10 @@ private CollectionData calculateDelinquencyDataForOverdueInstallment(final Loan } collectionData.setDelinquentDate(overdueSinceDate); collectionData.setDelinquentAmount(outstandingAmount); + collectionData.setDelinquentPrincipal(delinquentPrincipal); + collectionData.setDelinquentInterest(delinquentInterest); + collectionData.setDelinquentFee(delinquentFee); + collectionData.setDelinquentPenalty(delinquentPenalty); return collectionData; } @@ -283,6 +314,10 @@ private CollectionData calculateDelinquencyDataForNonOverdueInstallment(final Lo LocalDate overdueSinceDate = null; CollectionData collectionData = CollectionData.template(); BigDecimal outstandingAmount = BigDecimal.ZERO; + BigDecimal delinquentPrincipal = BigDecimal.ZERO; + BigDecimal delinquentInterest = BigDecimal.ZERO; + BigDecimal delinquentFee = BigDecimal.ZERO; + BigDecimal delinquentPenalty = BigDecimal.ZERO; List chargebackTransactions = loan.getLoanTransactions(LoanTransaction::isChargeback); BigDecimal amountAvailable = installment.getTotalPaid(loanCurrency).getAmount(); @@ -306,6 +341,10 @@ private CollectionData calculateDelinquencyDataForNonOverdueInstallment(final Lo } collectionData.setDelinquentDate(overdueSinceDate); collectionData.setDelinquentAmount(outstandingAmount); + collectionData.setDelinquentPrincipal(delinquentPrincipal); + collectionData.setDelinquentInterest(delinquentInterest); + collectionData.setDelinquentFee(delinquentFee); + collectionData.setDelinquentPenalty(delinquentPenalty); return collectionData; } diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/CollectionData.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/CollectionData.java index f872d6d27d2..fa4e4f6c8ae 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/CollectionData.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/CollectionData.java @@ -47,9 +47,14 @@ public final class CollectionData { public Collection delinquencyPausePeriods; public Collection installmentLevelDelinquency; + private BigDecimal delinquentPrincipal; + private BigDecimal delinquentInterest; + private BigDecimal delinquentFee; + private BigDecimal delinquentPenalty; + public static CollectionData template() { final BigDecimal zero = BigDecimal.ZERO; - return new CollectionData(zero, 0L, null, 0L, null, zero, null, zero, null, zero, null, null); + return new CollectionData(zero, 0L, null, 0L, null, zero, null, zero, null, zero, null, null, zero, zero, zero, zero); } } diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanSummaryData.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanSummaryData.java index 42ebbd6bec4..945fa397b28 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanSummaryData.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanSummaryData.java @@ -91,9 +91,14 @@ public class LoanSummaryData { private BigDecimal totalCreditBalanceRefundReversed; private BigDecimal totalRepaymentTransaction; private BigDecimal totalRepaymentTransactionReversed; + private BigDecimal totalInterestRefund; + private BigDecimal totalInterestPaymentWaiver; private final Long chargeOffReasonId; private final String chargeOffReason; + private BigDecimal totalUnpaidAccruedDueInterest; + private BigDecimal totalUnpaidAccruedNotDueInterest; + public static LoanSummaryData withTransactionAmountsSummary(final LoanSummaryData defaultSummaryData, final Collection loanTransactions) { @@ -110,6 +115,8 @@ public static LoanSummaryData withTransactionAmountsSummary(final LoanSummaryDat BigDecimal totalCreditBalanceRefundReversed = BigDecimal.ZERO; BigDecimal totalRepaymentTransaction = BigDecimal.ZERO; BigDecimal totalRepaymentTransactionReversed = BigDecimal.ZERO; + BigDecimal totalInterestRefund = BigDecimal.ZERO; + BigDecimal totalInterestPaymentWaiver = BigDecimal.ZERO; if (!CollectionUtils.isEmpty(loanTransactions)) { @@ -131,6 +138,8 @@ public static LoanSummaryData withTransactionAmountsSummary(final LoanSummaryDat loanTransactions); totalRepaymentTransaction = computeTotalRepaymentTransactionAmount(loanTransactions); totalRepaymentTransactionReversed = computeTotalAmountForReversedTransactions(LoanTransactionType.REPAYMENT, loanTransactions); + totalInterestPaymentWaiver = computeTotalAmountForNonReversedTransactions(LoanTransactionType.INTEREST_PAYMENT_WAIVER, + loanTransactions); } return LoanSummaryData.builder().currency(defaultSummaryData.currency).principalDisbursed(defaultSummaryData.principalDisbursed) @@ -163,7 +172,8 @@ public static LoanSummaryData withTransactionAmountsSummary(final LoanSummaryDat .totalChargeAdjustment(totalChargeAdjustment).totalChargeAdjustmentReversed(totalChargeAdjustmentReversed) .totalChargeback(totalChargeback).totalCreditBalanceRefund(totalCreditBalanceRefund) .totalCreditBalanceRefundReversed(totalCreditBalanceRefundReversed).totalRepaymentTransaction(totalRepaymentTransaction) - .totalRepaymentTransactionReversed(totalRepaymentTransactionReversed).build(); + .totalRepaymentTransactionReversed(totalRepaymentTransactionReversed).totalInterestRefund(totalInterestRefund) + .totalInterestPaymentWaiver(totalInterestPaymentWaiver).build(); } public static LoanSummaryData withOnlyCurrencyData(CurrencyData currencyData) { diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionType.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionType.java index f78c1d67a47..debbe48aca5 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionType.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionType.java @@ -63,8 +63,7 @@ public enum LoanTransactionType { DOWN_PAYMENT(28, "loanTransactionType.downPayment"), // REAGE(29, "loanTransactionType.reAge"), // REAMORTIZE(30, "loanTransactionType.reAmortize"), // - INTEREST_PAYMENT_WAIVER(31, "loanTransactionType.interestPaymentWaiver"), // - ; + INTEREST_PAYMENT_WAIVER(31, "loanTransactionType.interestPaymentWaiver"); // private final Integer value; private final String code; diff --git a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/ChargeOrTransaction.java b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/ChargeOrTransaction.java index 4e69c90c3f8..3812d2efd6e 100644 --- a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/ChargeOrTransaction.java +++ b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/ChargeOrTransaction.java @@ -58,7 +58,7 @@ private LocalDate getEffectiveDate() { } private boolean isBackdatedCharge() { - return loanCharge.get().getDueDate().isBefore(loanCharge.get().getSubmittedOnDate()); + return (loanCharge.get().getDueDate() != null && loanCharge.get().getDueDate().isBefore(loanCharge.get().getSubmittedOnDate())); } private LocalDate getSubmittedOnDate() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java index 82417ea7e68..5b24fecc9db 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java @@ -616,6 +616,10 @@ private GetLoansLoanIdFeeFrequency() {} @Schema(example = "0.000000") public Double totalRepaymentTransaction; @Schema(example = "0.000000") + public Double totalInterestRefund; + @Schema(example = "0.000000") + public Double totalInterestPaymentWaiver; + @Schema(example = "0.000000") public Double totalRepaymentTransactionReversed; public Set overdueCharges; @Schema(example = "1") @@ -984,6 +988,14 @@ private GetLoansLoanIdDelinquencySummary() {} public LocalDate delinquentDate; @Schema(example = "100.000000") public Double delinquentAmount; + @Schema(example = "80.000000") + public Double delinquentPrincipal; + @Schema(example = "10.000000") + public Double delinquentInterest; + @Schema(example = "6.000000") + public Double delinquentFee; + @Schema(example = "4.000000") + public Double delinquentPenalty; @Schema(example = "[2022, 07, 01]") public LocalDate lastPaymentDate; @Schema(example = "100.000000") diff --git a/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/DelinquencyWritePlatformServiceRangeChangeEventTest.java b/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/DelinquencyWritePlatformServiceRangeChangeEventTest.java index 0a994567557..7524a9248be 100644 --- a/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/DelinquencyWritePlatformServiceRangeChangeEventTest.java +++ b/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/DelinquencyWritePlatformServiceRangeChangeEventTest.java @@ -167,8 +167,9 @@ public void givenLoanAccountWithDelinquencyBucketWhenRangeChangeThenEventIsRaise LocalDate overDueSinceDate = DateUtils.getBusinessLocalDate().minusDays(2); LoanScheduleDelinquencyData loanScheduleDelinquencyData = new LoanScheduleDelinquencyData(1L, overDueSinceDate, 1L, loanForProcessing); - CollectionData collectionData = new CollectionData(BigDecimal.ZERO, 2L, null, 2L, overDueSinceDate, BigDecimal.ZERO, null, null, - null, null, null, null); + final BigDecimal zero = BigDecimal.ZERO; + CollectionData collectionData = new CollectionData(zero, 2L, null, 2L, overDueSinceDate, zero, null, null, null, null, null, null, + zero, zero, zero, zero); Map installmentsCollection = new HashMap<>(); @@ -221,11 +222,11 @@ public void test_ApplyDelinquencyTagToLoan_ExecutesDelinquencyApplication_InTheR LocalDate overDueSinceDate = DateUtils.getBusinessLocalDate().minusDays(2); LoanScheduleDelinquencyData loanScheduleDelinquencyData = new LoanScheduleDelinquencyData(1L, overDueSinceDate, 1L, loanForProcessing); - CollectionData collectionData = new CollectionData(BigDecimal.ZERO, 2L, null, 2L, overDueSinceDate, BigDecimal.ZERO, null, null, - null, null, null, null); + CollectionData collectionData = new CollectionData(zeroAmount, 2L, null, 2L, overDueSinceDate, zeroAmount, null, null, null, null, + null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); - CollectionData installmentCollectionData = new CollectionData(BigDecimal.ZERO, 2L, null, 2L, overDueSinceDate, - installmentPrincipalAmount, null, null, null, null, null, null); + CollectionData installmentCollectionData = new CollectionData(zeroAmount, 2L, null, 2L, overDueSinceDate, + installmentPrincipalAmount, null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); Map installmentsCollection = new HashMap<>(); installmentsCollection.put(1L, installmentCollectionData); @@ -349,11 +350,12 @@ public void givenLoanAccountWithOverdueInstallmentAndEnableInstallmentThenDelinq LocalDate overDueSinceDate = DateUtils.getBusinessLocalDate().minusDays(2); LoanScheduleDelinquencyData loanScheduleDelinquencyData = new LoanScheduleDelinquencyData(1L, overDueSinceDate, 1L, loanForProcessing); - CollectionData collectionData = new CollectionData(BigDecimal.ZERO, 2L, null, 2L, overDueSinceDate, BigDecimal.ZERO, null, null, - null, null, null, null); - CollectionData installmentCollectionData = new CollectionData(BigDecimal.ZERO, 2L, null, 2L, overDueSinceDate, - installmentPrincipalAmount, null, null, null, null, null, null); + CollectionData collectionData = new CollectionData(zeroAmount, 2L, null, 2L, overDueSinceDate, zeroAmount, null, null, null, null, + null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); + + CollectionData installmentCollectionData = new CollectionData(zeroAmount, 2L, null, 2L, overDueSinceDate, + installmentPrincipalAmount, null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); Map installmentsCollection = new HashMap<>(); installmentsCollection.put(1L, installmentCollectionData); @@ -426,11 +428,11 @@ public void givenLoanAccountWithOverdueInstallmentAndEnableInstallmentThenDelinq LocalDate overDueSinceDate = DateUtils.getBusinessLocalDate().minusDays(29); LoanScheduleDelinquencyData loanScheduleDelinquencyData = new LoanScheduleDelinquencyData(1L, overDueSinceDate, 1L, loanForProcessing); - CollectionData collectionData = new CollectionData(BigDecimal.ZERO, 29L, null, 29L, overDueSinceDate, BigDecimal.ZERO, null, null, - null, null, null, null); + CollectionData collectionData = new CollectionData(BigDecimal.ZERO, 29L, null, 29L, overDueSinceDate, zeroAmount, null, null, null, + null, null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); - CollectionData installmentCollectionData = new CollectionData(BigDecimal.ZERO, 29L, null, 29L, overDueSinceDate, - installmentPrincipalAmount, null, null, null, null, null, null); + CollectionData installmentCollectionData = new CollectionData(zeroAmount, 29L, null, 29L, overDueSinceDate, + installmentPrincipalAmount, null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); Map installmentsCollection = new HashMap<>(); installmentsCollection.put(1L, installmentCollectionData); @@ -514,14 +516,14 @@ public void givenLoanAccountWithOverdueInstallmentsAndEnableInstallmentThenDelin LocalDate overDueSinceDate = DateUtils.getBusinessLocalDate().minusDays(29); LoanScheduleDelinquencyData loanScheduleDelinquencyData = new LoanScheduleDelinquencyData(1L, overDueSinceDate, 1L, loanForProcessing); - CollectionData collectionData = new CollectionData(BigDecimal.ZERO, 29L, null, 29L, overDueSinceDate, BigDecimal.ZERO, null, null, - null, null, null, null); + CollectionData collectionData = new CollectionData(zeroAmount, 29L, null, 29L, overDueSinceDate, zeroAmount, null, null, null, null, + null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); - CollectionData installmentCollectionData_1 = new CollectionData(BigDecimal.ZERO, 29L, null, 29L, overDueSinceDate, - installmentPrincipalAmount, null, null, null, null, null, null); + CollectionData installmentCollectionData_1 = new CollectionData(zeroAmount, 29L, null, 29L, overDueSinceDate, + installmentPrincipalAmount, null, null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); - CollectionData installmentCollectionData_2 = new CollectionData(BigDecimal.ZERO, 0L, null, 0L, null, installmentPrincipalAmount, - null, null, null, null, null, null); + CollectionData installmentCollectionData_2 = new CollectionData(zeroAmount, 0L, null, 0L, null, installmentPrincipalAmount, null, + null, null, null, null, null, zeroAmount, zeroAmount, zeroAmount, zeroAmount); Map installmentsCollection = new HashMap<>(); installmentsCollection.put(1L, installmentCollectionData_1);