diff --git a/fineract-avro-schemas/src/main/avro/loan/v1/LoanAccountDataV1.avsc b/fineract-avro-schemas/src/main/avro/loan/v1/LoanAccountDataV1.avsc index de0455b0f..048dee057 100644 --- a/fineract-avro-schemas/src/main/avro/loan/v1/LoanAccountDataV1.avsc +++ b/fineract-avro-schemas/src/main/avro/loan/v1/LoanAccountDataV1.avsc @@ -853,6 +853,14 @@ "items": "org.apache.fineract.avro.loan.v1.OriginatorDetailsV1" } ] + }, + { + "default": null, + "name": "actualNoTerm", + "type": [ + "null", + "int" + ] } ] } diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/EventCheckHelper.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/EventCheckHelper.java index 94449abdc..a3c6762a2 100644 --- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/EventCheckHelper.java +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/EventCheckHelper.java @@ -201,6 +201,8 @@ public class EventCheckHelper { BigDecimal delinquentFeeExpected = body.getDelinquent().getDelinquentFee(); BigDecimal delinquentPenaltyActual = loanAccountDataV1.getDelinquent().getDelinquentPenalty(); BigDecimal delinquentPenaltyExpected = body.getDelinquent().getDelinquentPenalty(); + Integer actualNoTermActual = loanAccountDataV1.getActualNoTerm(); + Integer actualNoTermExpected = body.getActualNoTerm(); assertThat(idActual).isEqualTo(idExpected); assertThat(statusIdActual).isEqualTo(statusIdExpected); @@ -217,6 +219,7 @@ public class EventCheckHelper { assertThat(areBigDecimalValuesEqual(delinquentInterestActual, delinquentInterestExpected)).isTrue(); assertThat(areBigDecimalValuesEqual(delinquentFeeActual, delinquentFeeExpected)).isTrue(); assertThat(areBigDecimalValuesEqual(delinquentPenaltyActual, delinquentPenaltyExpected)).isTrue(); + assertThat(actualNoTermActual).isEqualTo(actualNoTermExpected); return null; }); diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java index 7507129d8..26d5a0536 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java @@ -104,6 +104,7 @@ public class LoanAccountData { private Integer termFrequency; private EnumOptionData termPeriodFrequencyType; private Integer numberOfRepayments; + private Integer actualNoTerm; private Integer repaymentEvery; private Integer fixedLength; private EnumOptionData repaymentFrequencyType; diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallmentRepository.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallmentRepository.java index c7c7af96e..325fbb360 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallmentRepository.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallmentRepository.java @@ -72,4 +72,7 @@ public interface LoanRepaymentScheduleInstallmentRepository """) List findByLoanId(@Param("loanId") Long loanId); + long countLoanRepaymentScheduleInstallmentsByLoan_IdAndAdditionalAndIsDownPayment(Long loanId, boolean additional, + boolean isDownPayment); + } diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java index f8c5e0294..f372b117b 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java @@ -168,4 +168,6 @@ public interface LoanReadPlatformService { LoanTransactionData retrieveLoanReAgeTemplate(Long loanId); LoanTransactionData retrieveLoanReAmortizationTemplate(Long loanId); + + Integer countInstallmentsByLoanIdWhereIsAdditionalFalseAndIsDownPaymentFalse(Long loanId); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanBusinessEventSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanBusinessEventSerializer.java index 792d60809..52b1c0a97 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanBusinessEventSerializer.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanBusinessEventSerializer.java @@ -102,6 +102,10 @@ public class LoanBusinessEventSerializer extends AbstractBusinessEventWithCustom data.setLoanTermVariations(activeLoanTermVariations.stream().map(LoanTermVariations::toData).toList()); } + Integer actualNoTerms = Math.toIntExact( + event.get().getRepaymentScheduleInstallments().stream().filter(i -> !i.isAdditional() && !i.isDownPayment()).count()); + data.setActualNoTerm(actualNoTerms); + final LoanAccountDataV1 result = mapper.map(data); result.getDelinquent().setInstallmentDelinquencyBuckets(installmentsDelinquencyData); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java index 306230d68..c7c3c0bdc 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java @@ -1024,6 +1024,8 @@ public class LoansApiResource { loanBasicDetails = loanBasicDetails.setMeeting(calendarData); } } + loanBasicDetails.setActualNoTerm( + loanReadPlatformService.countInstallmentsByLoanIdWhereIsAdditionalFalseAndIsDownPaymentFalse(resolvedLoanId)); Collection interestRatesPeriods = this.loanReadPlatformService .retrieveLoanInterestRatePeriodData(loanBasicDetails); Collection loanRepayments = null; 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 1ef9b7ce9..a2349178a 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 @@ -1286,6 +1286,8 @@ final class LoansApiResourceSwagger { public StringEnumOptionData buyDownFeeStrategy; @Schema(example = "FEE") public StringEnumOptionData buyDownFeeIncomeType; + @Schema(example = "6") + public Integer actualNoTerm; } @Schema(description = "GetLoansResponse") diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java index 46e86e88a..711f1a878 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java @@ -1796,6 +1796,11 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa .reAmortizationInterestHandlingOptions(LoanReAmortizationInterestHandlingType.getValuesAsEnumOptionDataList()).build(); } + @Override + public Integer countInstallmentsByLoanIdWhereIsAdditionalFalseAndIsDownPaymentFalse(Long loanId) { + return loanRepaymentScheduleService.countInstallmentsByLoanIdWhereIsAdditionalFalseAndIsDownPaymentFalse(loanId); + } + @Override public LoanTransactionData retrieveLoanChargeOffTemplate(final Long loanId) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanRepaymentScheduleService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanRepaymentScheduleService.java index 9943a626a..7844b54e9 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanRepaymentScheduleService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanRepaymentScheduleService.java @@ -60,6 +60,11 @@ public class LoanRepaymentScheduleService { isInterestRecalculationEnabled, loanScheduleType); } + public Integer countInstallmentsByLoanIdWhereIsAdditionalFalseAndIsDownPaymentFalse(Long loanId) { + return Math.toIntExact(loanRepaymentScheduleInstallmentRepository + .countLoanRepaymentScheduleInstallmentsByLoan_IdAndAdditionalAndIsDownPayment(loanId, false, false)); + } + public LoanScheduleData extractLoanScheduleData(final List installments, final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedLoanData, Collection disbursementData, Collection capitalizedIncomeData, boolean isInterestRecalculationEnabled,