You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@fineract.apache.org by "San-43 (via GitHub)" <gi...@apache.org> on 2026/03/24 18:05:43 UTC
[PR] FINERACT-1152: Use projected schedule to validate EMI end date in loan reschedule [fineract]
San-43 opened a new pull request, #5689:
URL: https://github.com/apache/fineract/pull/5689
## Description
This PR fixes [FINERACT-1152](https://issues.apache.org/jira/browse/FINERACT-1152); loan reschedule validation and term-variation generation for EMI changes with `endDate` when other reschedule changes (for example `extraTerms`) are submitted together.
Previously, EMI/end-date validation effectively depended on the current installment schedule, which could reject valid requests where the end date only exists in the projected post-reschedule schedule.
## Changes
- Updates EMI/end-date validation to enforce:
- both fields are required together
- `emi` must be positive
- `endDate` must not be before `rescheduleFromDate`
- Builds projected installment due dates using pending reschedule variations, then creates EMI term variations using those projected dates up to `endDate`
- Returns a validation error when `endDate` is before the next projected installment date
- Adds/updates tests:
- unit tests for validator behavior
- integration test covering EMI + extra terms using projected future schedule
- Updates Swagger request model with `endDate` and `emi` fields for create-reschedule request payload examples
I would like to mention #5619 since it helped me to have a better overall view of the problem and the potential fix. Hope this goes well. Pls let me know if anything should be changed.
## Checklist
- [x] Write the commit message as per [our guidelines](https://github.com/apache/fineract/blob/develop/CONTRIBUTING.md#pull-requests)
- [x] Acknowledge that we will not review PRs that are not passing the build _("green")_ - it is your responsibility to get a proposed PR to pass the build, not primarily the project's maintainers.
- [x] Create/update [unit or integration tests](https://fineract.apache.org/docs/current/#_testing) for verifying the changes made.
- [x] Follow our [coding conventions](https://cwiki.apache.org/confluence/display/FINERACT/Coding+Conventions).
- [x] Add required Swagger annotation and update API documentation at fineract-provider/src/main/resources/static/legacy-docs/apiLive.htm with details of any API changes
- [x] [This PR must not be a "code dump"](https://cwiki.apache.org/confluence/display/FINERACT/Pull+Request+Size+Limit). Large changes can be made in a branch, with assistance. Ask for help on the [developer mailing list](https://fineract.apache.org/#contribute).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] FINERACT-1152: Use projected schedule to validate EMI end date in loan reschedule [fineract]
Posted by "San-43 (via GitHub)" <gi...@apache.org>.
San-43 commented on PR #5689:
URL: https://github.com/apache/fineract/pull/5689#issuecomment-4164723027
> Other than that I like this approach ,LGTM
Thank you very much @DeathGun44! I really appreciate your review.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] FINERACT-1152: Use projected schedule to validate EMI end date in loan reschedule [fineract]
Posted by "San-43 (via GitHub)" <gi...@apache.org>.
San-43 commented on PR #5689:
URL: https://github.com/apache/fineract/pull/5689#issuecomment-4136466159
I believe this is ready for review/merge.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] FINERACT-1152: Use projected schedule to validate EMI end date in loan reschedule [fineract]
Posted by "DeathGun44 (via GitHub)" <gi...@apache.org>.
DeathGun44 commented on code in PR #5689:
URL: https://github.com/apache/fineract/pull/5689#discussion_r3013881531
##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java:
##########
@@ -289,32 +279,111 @@ private void createLoanTermVariationsForRegularLoans(final Loan loan, final Inte
parent = createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate,
loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(graceOnPrincipal),
parent);
+ pendingRescheduleVariations.add(parent);
BigDecimal extraTermsBasedOnGracePeriods = BigDecimal.valueOf(graceOnPrincipal);
- createLoanTermVariations(loanRescheduleRequest, LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue(), loan,
- rescheduleFromDate, dueDate, loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment,
- extraTermsBasedOnGracePeriods, parent);
+ LoanTermVariations extraTermsVariation = createLoanTermVariations(loanRescheduleRequest,
+ LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue(), loan, rescheduleFromDate, dueDate,
+ loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, extraTermsBasedOnGracePeriods, parent);
+ pendingRescheduleVariations.add(extraTermsVariation);
}
if (rescheduleFromDate != null && graceOnInterest != null) {
LoanTermVariations parent = null;
final Integer termType = LoanTermVariationType.GRACE_ON_INTEREST.getValue();
- createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate,
- loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(graceOnInterest),
- parent);
+ LoanTermVariations loanTermVariation = createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate,
+ dueDate, loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment,
+ BigDecimal.valueOf(graceOnInterest), parent);
+ pendingRescheduleVariations.add(loanTermVariation);
}
if (rescheduleFromDate != null && extraTerms != null) {
LoanTermVariations parent = null;
final Integer termType = LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue();
- createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate,
- loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(extraTerms),
- parent);
+ LoanTermVariations loanTermVariation = createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate,
+ dueDate, loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment,
+ BigDecimal.valueOf(extraTerms), parent);
+ pendingRescheduleVariations.add(loanTermVariation);
+ }
+
+ if (rescheduleFromDate != null && endDate != null && emi != null) {
+ LoanTermVariations parent = null;
+ final Integer termType = LoanTermVariationType.EMI_AMOUNT.getValue();
+ int emiVariationsCreated = 0;
+ List<LocalDate> projectedInstallmentDueDates = getProjectedInstallmentDueDates(loan, rescheduleFromDate,
+ pendingRescheduleVariations);
+ for (LocalDate installmentDueDate : projectedInstallmentDueDates) {
+ if (!DateUtils.isBefore(installmentDueDate, rescheduleFromDate) && !DateUtils.isAfter(installmentDueDate, endDate)) {
+ createLoanTermVariations(loanRescheduleRequest, termType, loan, installmentDueDate, installmentDueDate,
+ loanRescheduleRequestToTermVariationMappings, isActive, true, emi, parent);
+ emiVariationsCreated++;
+ }
+ if (DateUtils.isAfter(installmentDueDate, endDate)) {
+ break;
+ }
+ }
+ if (emiVariationsCreated == 0) {
+ List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+ final DataValidatorBuilder dataValidatorBuilder = new DataValidatorBuilder(dataValidationErrors)
+ .resource(RescheduleLoansApiConstants.ENTITY_NAME);
+ dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.endDateParamName).failWithCode(
+ "end.date.before.next.installment", "End date must be on or after the next projected installment date");
+ throw new PlatformApiDataValidationException(dataValidationErrors);
+ }
}
loanRescheduleRequest.updateLoanRescheduleRequestToTermVariationMappings(loanRescheduleRequestToTermVariationMappings);
}
+ private List<LocalDate> getProjectedInstallmentDueDates(final Loan loan, final LocalDate rescheduleFromDate,
+ final List<LoanTermVariations> pendingRescheduleVariations) {
+ ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, rescheduleFromDate);
+ final LoanApplicationTerms loanApplicationTerms = loanTermVariationsMapper.constructLoanApplicationTerms(scheduleGeneratorDTO,
+ loan);
+ List<LoanTermVariationsData> projectedVariations = buildProjectedLoanTermVariatons(loanApplicationTerms,
Review Comment:
minor typo here should be "Variations"
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] FINERACT-1152: Use projected schedule to validate EMI end date in loan reschedule [fineract]
Posted by "San-43 (via GitHub)" <gi...@apache.org>.
San-43 commented on code in PR #5689:
URL: https://github.com/apache/fineract/pull/5689#discussion_r3031899110
##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java:
##########
@@ -289,32 +279,111 @@ private void createLoanTermVariationsForRegularLoans(final Loan loan, final Inte
parent = createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate,
loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(graceOnPrincipal),
parent);
+ pendingRescheduleVariations.add(parent);
BigDecimal extraTermsBasedOnGracePeriods = BigDecimal.valueOf(graceOnPrincipal);
- createLoanTermVariations(loanRescheduleRequest, LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue(), loan,
- rescheduleFromDate, dueDate, loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment,
- extraTermsBasedOnGracePeriods, parent);
+ LoanTermVariations extraTermsVariation = createLoanTermVariations(loanRescheduleRequest,
+ LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue(), loan, rescheduleFromDate, dueDate,
+ loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, extraTermsBasedOnGracePeriods, parent);
+ pendingRescheduleVariations.add(extraTermsVariation);
}
if (rescheduleFromDate != null && graceOnInterest != null) {
LoanTermVariations parent = null;
final Integer termType = LoanTermVariationType.GRACE_ON_INTEREST.getValue();
- createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate,
- loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(graceOnInterest),
- parent);
+ LoanTermVariations loanTermVariation = createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate,
+ dueDate, loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment,
+ BigDecimal.valueOf(graceOnInterest), parent);
+ pendingRescheduleVariations.add(loanTermVariation);
}
if (rescheduleFromDate != null && extraTerms != null) {
LoanTermVariations parent = null;
final Integer termType = LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue();
- createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate,
- loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(extraTerms),
- parent);
+ LoanTermVariations loanTermVariation = createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate,
+ dueDate, loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment,
+ BigDecimal.valueOf(extraTerms), parent);
+ pendingRescheduleVariations.add(loanTermVariation);
+ }
+
+ if (rescheduleFromDate != null && endDate != null && emi != null) {
+ LoanTermVariations parent = null;
+ final Integer termType = LoanTermVariationType.EMI_AMOUNT.getValue();
+ int emiVariationsCreated = 0;
+ List<LocalDate> projectedInstallmentDueDates = getProjectedInstallmentDueDates(loan, rescheduleFromDate,
+ pendingRescheduleVariations);
+ for (LocalDate installmentDueDate : projectedInstallmentDueDates) {
+ if (!DateUtils.isBefore(installmentDueDate, rescheduleFromDate) && !DateUtils.isAfter(installmentDueDate, endDate)) {
+ createLoanTermVariations(loanRescheduleRequest, termType, loan, installmentDueDate, installmentDueDate,
+ loanRescheduleRequestToTermVariationMappings, isActive, true, emi, parent);
+ emiVariationsCreated++;
+ }
+ if (DateUtils.isAfter(installmentDueDate, endDate)) {
+ break;
+ }
+ }
+ if (emiVariationsCreated == 0) {
+ List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+ final DataValidatorBuilder dataValidatorBuilder = new DataValidatorBuilder(dataValidationErrors)
+ .resource(RescheduleLoansApiConstants.ENTITY_NAME);
+ dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.endDateParamName).failWithCode(
+ "end.date.before.next.installment", "End date must be on or after the next projected installment date");
+ throw new PlatformApiDataValidationException(dataValidationErrors);
+ }
}
loanRescheduleRequest.updateLoanRescheduleRequestToTermVariationMappings(loanRescheduleRequestToTermVariationMappings);
}
+ private List<LocalDate> getProjectedInstallmentDueDates(final Loan loan, final LocalDate rescheduleFromDate,
+ final List<LoanTermVariations> pendingRescheduleVariations) {
+ ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, rescheduleFromDate);
+ final LoanApplicationTerms loanApplicationTerms = loanTermVariationsMapper.constructLoanApplicationTerms(scheduleGeneratorDTO,
+ loan);
+ List<LoanTermVariationsData> projectedVariations = buildProjectedLoanTermVariatons(loanApplicationTerms,
Review Comment:
Done 😅, I also rebased onto the latest develop
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] FINERACT-1152: Use projected schedule to validate EMI end date in loan reschedule [fineract]
Posted by "DeathGun44 (via GitHub)" <gi...@apache.org>.
DeathGun44 commented on code in PR #5689:
URL: https://github.com/apache/fineract/pull/5689#discussion_r3031815404
##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java:
##########
@@ -289,32 +279,111 @@ private void createLoanTermVariationsForRegularLoans(final Loan loan, final Inte
parent = createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate,
loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(graceOnPrincipal),
parent);
+ pendingRescheduleVariations.add(parent);
BigDecimal extraTermsBasedOnGracePeriods = BigDecimal.valueOf(graceOnPrincipal);
- createLoanTermVariations(loanRescheduleRequest, LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue(), loan,
- rescheduleFromDate, dueDate, loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment,
- extraTermsBasedOnGracePeriods, parent);
+ LoanTermVariations extraTermsVariation = createLoanTermVariations(loanRescheduleRequest,
+ LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue(), loan, rescheduleFromDate, dueDate,
+ loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, extraTermsBasedOnGracePeriods, parent);
+ pendingRescheduleVariations.add(extraTermsVariation);
}
if (rescheduleFromDate != null && graceOnInterest != null) {
LoanTermVariations parent = null;
final Integer termType = LoanTermVariationType.GRACE_ON_INTEREST.getValue();
- createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate,
- loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(graceOnInterest),
- parent);
+ LoanTermVariations loanTermVariation = createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate,
+ dueDate, loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment,
+ BigDecimal.valueOf(graceOnInterest), parent);
+ pendingRescheduleVariations.add(loanTermVariation);
}
if (rescheduleFromDate != null && extraTerms != null) {
LoanTermVariations parent = null;
final Integer termType = LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue();
- createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate,
- loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(extraTerms),
- parent);
+ LoanTermVariations loanTermVariation = createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate,
+ dueDate, loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment,
+ BigDecimal.valueOf(extraTerms), parent);
+ pendingRescheduleVariations.add(loanTermVariation);
+ }
+
+ if (rescheduleFromDate != null && endDate != null && emi != null) {
+ LoanTermVariations parent = null;
+ final Integer termType = LoanTermVariationType.EMI_AMOUNT.getValue();
+ int emiVariationsCreated = 0;
+ List<LocalDate> projectedInstallmentDueDates = getProjectedInstallmentDueDates(loan, rescheduleFromDate,
+ pendingRescheduleVariations);
+ for (LocalDate installmentDueDate : projectedInstallmentDueDates) {
+ if (!DateUtils.isBefore(installmentDueDate, rescheduleFromDate) && !DateUtils.isAfter(installmentDueDate, endDate)) {
+ createLoanTermVariations(loanRescheduleRequest, termType, loan, installmentDueDate, installmentDueDate,
+ loanRescheduleRequestToTermVariationMappings, isActive, true, emi, parent);
+ emiVariationsCreated++;
+ }
+ if (DateUtils.isAfter(installmentDueDate, endDate)) {
+ break;
+ }
+ }
+ if (emiVariationsCreated == 0) {
+ List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+ final DataValidatorBuilder dataValidatorBuilder = new DataValidatorBuilder(dataValidationErrors)
+ .resource(RescheduleLoansApiConstants.ENTITY_NAME);
+ dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.endDateParamName).failWithCode(
+ "end.date.before.next.installment", "End date must be on or after the next projected installment date");
+ throw new PlatformApiDataValidationException(dataValidationErrors);
+ }
}
loanRescheduleRequest.updateLoanRescheduleRequestToTermVariationMappings(loanRescheduleRequestToTermVariationMappings);
}
+ private List<LocalDate> getProjectedInstallmentDueDates(final Loan loan, final LocalDate rescheduleFromDate,
+ final List<LoanTermVariations> pendingRescheduleVariations) {
+ ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, rescheduleFromDate);
+ final LoanApplicationTerms loanApplicationTerms = loanTermVariationsMapper.constructLoanApplicationTerms(scheduleGeneratorDTO,
+ loan);
+ List<LoanTermVariationsData> projectedVariations = buildProjectedLoanTermVariatons(loanApplicationTerms,
Review Comment:
Line 343 buildProjectedLoanTermVariatons
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] FINERACT-1152: Use projected schedule to validate EMI end date in loan reschedule [fineract]
Posted by "San-43 (via GitHub)" <gi...@apache.org>.
San-43 commented on PR #5689:
URL: https://github.com/apache/fineract/pull/5689#issuecomment-4135349059
Another baseline/pipeline drift?
```
Then Loan is closed with zero outstanding balance and it's all installments have obligations met # org.apache.fineract.test.stepdef.loan.LoanStepDef.loanClosedAndInstallmentsObligationsMet()
Failed scenarios:
file:///home/runner/work/fineract/fineract/fineract-e2e-tests-runner/src/test/resources/features/LoanCapitalizedIncome-Part2.feature:53 # Verify Capitalized income and Caplitalized income adjustment - Accounting and repayment schedule handling in case of loan is overpaid (Capitalized Income Scenarios - UC9)
32 Scenarios (1 failed, 31 passed)
723 Steps (1 failed, 1 skipped, 721 passed)
4m11.799s
org.opentest4j.AssertionFailedError:
expected: 600L
but was: 700L
at org.apache.fineract.test.messaging.event.EventCheckHelper.lambda$loanAccountDataV1Check$6(EventCheckHelper.java:208)
at org.apache.fineract.test.messaging.EventAssertion$EventAssertionBuilder.extractingData(EventAssertion.java:145)
at org.apache.fineract.test.messaging.event.EventCheckHelper.loanAccountDataV1Check(EventCheckHelper.java:173)
at org.apache.fineract.test.messaging.event.EventCheckHelper.loanBalanceChangedEventCheck(EventCheckHelper.java:160)
at org.apache.fineract.test.stepdef.loan.LoanStepDef.createCBR(LoanStepDef.java:629)
at ✽.Admin makes Credit Balance Refund transaction on "15 April 2024" with 15 EUR transaction amount(file:///home/runner/work/fineract/fineract/fineract-e2e-tests-runner/src/test/resources/features/LoanCapitalizedIncome-Part2.feature:720)
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] FINERACT-1152: Use projected schedule to validate EMI end date in loan reschedule [fineract]
Posted by "San-43 (via GitHub)" <gi...@apache.org>.
San-43 commented on PR #5689:
URL: https://github.com/apache/fineract/pull/5689#issuecomment-4157638633
> Another baseline/pipeline drift?
>
> ```
> Then Loan is closed with zero outstanding balance and it's all installments have obligations met # org.apache.fineract.test.stepdef.loan.LoanStepDef.loanClosedAndInstallmentsObligationsMet()
>
> Failed scenarios:
> file:///home/runner/work/fineract/fineract/fineract-e2e-tests-runner/src/test/resources/features/LoanCapitalizedIncome-Part2.feature:53 # Verify Capitalized income and Caplitalized income adjustment - Accounting and repayment schedule handling in case of loan is overpaid (Capitalized Income Scenarios - UC9)
>
> 32 Scenarios (1 failed, 31 passed)
> 723 Steps (1 failed, 1 skipped, 721 passed)
> 4m11.799s
>
>
> org.opentest4j.AssertionFailedError:
> expected: 600L
> but was: 700L
> at org.apache.fineract.test.messaging.event.EventCheckHelper.lambda$loanAccountDataV1Check$6(EventCheckHelper.java:208)
> at org.apache.fineract.test.messaging.EventAssertion$EventAssertionBuilder.extractingData(EventAssertion.java:145)
> at org.apache.fineract.test.messaging.event.EventCheckHelper.loanAccountDataV1Check(EventCheckHelper.java:173)
> at org.apache.fineract.test.messaging.event.EventCheckHelper.loanBalanceChangedEventCheck(EventCheckHelper.java:160)
> at org.apache.fineract.test.stepdef.loan.LoanStepDef.createCBR(LoanStepDef.java:629)
> at ✽.Admin makes Credit Balance Refund transaction on "15 April 2024" with 15 EUR transaction amount(file:///home/runner/work/fineract/fineract/fineract-e2e-tests-runner/src/test/resources/features/LoanCapitalizedIncome-Part2.feature:720)
> ```
Same error
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] FINERACT-1152: Use projected schedule to validate EMI end date in loan reschedule [fineract]
Posted by "adamsaghy (via GitHub)" <gi...@apache.org>.
adamsaghy merged PR #5689:
URL: https://github.com/apache/fineract/pull/5689
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] FINERACT-1152: Use projected schedule to validate EMI end date in loan reschedule [fineract]
Posted by "San-43 (via GitHub)" <gi...@apache.org>.
San-43 commented on code in PR #5689:
URL: https://github.com/apache/fineract/pull/5689#discussion_r3031899110
##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java:
##########
@@ -289,32 +279,111 @@ private void createLoanTermVariationsForRegularLoans(final Loan loan, final Inte
parent = createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate,
loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(graceOnPrincipal),
parent);
+ pendingRescheduleVariations.add(parent);
BigDecimal extraTermsBasedOnGracePeriods = BigDecimal.valueOf(graceOnPrincipal);
- createLoanTermVariations(loanRescheduleRequest, LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue(), loan,
- rescheduleFromDate, dueDate, loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment,
- extraTermsBasedOnGracePeriods, parent);
+ LoanTermVariations extraTermsVariation = createLoanTermVariations(loanRescheduleRequest,
+ LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue(), loan, rescheduleFromDate, dueDate,
+ loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, extraTermsBasedOnGracePeriods, parent);
+ pendingRescheduleVariations.add(extraTermsVariation);
}
if (rescheduleFromDate != null && graceOnInterest != null) {
LoanTermVariations parent = null;
final Integer termType = LoanTermVariationType.GRACE_ON_INTEREST.getValue();
- createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate,
- loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(graceOnInterest),
- parent);
+ LoanTermVariations loanTermVariation = createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate,
+ dueDate, loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment,
+ BigDecimal.valueOf(graceOnInterest), parent);
+ pendingRescheduleVariations.add(loanTermVariation);
}
if (rescheduleFromDate != null && extraTerms != null) {
LoanTermVariations parent = null;
final Integer termType = LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue();
- createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate,
- loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(extraTerms),
- parent);
+ LoanTermVariations loanTermVariation = createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate,
+ dueDate, loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment,
+ BigDecimal.valueOf(extraTerms), parent);
+ pendingRescheduleVariations.add(loanTermVariation);
+ }
+
+ if (rescheduleFromDate != null && endDate != null && emi != null) {
+ LoanTermVariations parent = null;
+ final Integer termType = LoanTermVariationType.EMI_AMOUNT.getValue();
+ int emiVariationsCreated = 0;
+ List<LocalDate> projectedInstallmentDueDates = getProjectedInstallmentDueDates(loan, rescheduleFromDate,
+ pendingRescheduleVariations);
+ for (LocalDate installmentDueDate : projectedInstallmentDueDates) {
+ if (!DateUtils.isBefore(installmentDueDate, rescheduleFromDate) && !DateUtils.isAfter(installmentDueDate, endDate)) {
+ createLoanTermVariations(loanRescheduleRequest, termType, loan, installmentDueDate, installmentDueDate,
+ loanRescheduleRequestToTermVariationMappings, isActive, true, emi, parent);
+ emiVariationsCreated++;
+ }
+ if (DateUtils.isAfter(installmentDueDate, endDate)) {
+ break;
+ }
+ }
+ if (emiVariationsCreated == 0) {
+ List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+ final DataValidatorBuilder dataValidatorBuilder = new DataValidatorBuilder(dataValidationErrors)
+ .resource(RescheduleLoansApiConstants.ENTITY_NAME);
+ dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.endDateParamName).failWithCode(
+ "end.date.before.next.installment", "End date must be on or after the next projected installment date");
+ throw new PlatformApiDataValidationException(dataValidationErrors);
+ }
}
loanRescheduleRequest.updateLoanRescheduleRequestToTermVariationMappings(loanRescheduleRequestToTermVariationMappings);
}
+ private List<LocalDate> getProjectedInstallmentDueDates(final Loan loan, final LocalDate rescheduleFromDate,
+ final List<LoanTermVariations> pendingRescheduleVariations) {
+ ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, rescheduleFromDate);
+ final LoanApplicationTerms loanApplicationTerms = loanTermVariationsMapper.constructLoanApplicationTerms(scheduleGeneratorDTO,
+ loan);
+ List<LoanTermVariationsData> projectedVariations = buildProjectedLoanTermVariatons(loanApplicationTerms,
Review Comment:
Done 😅
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] FINERACT-1152: Use projected schedule to validate EMI end date in loan reschedule [fineract]
Posted by "San-43 (via GitHub)" <gi...@apache.org>.
San-43 commented on PR #5689:
URL: https://github.com/apache/fineract/pull/5689#issuecomment-4132579755
Hello @adamsaghy, sorry to bother you. After carefully reviewing everything, running tests in my local environment, and double-checking the failure causes, I’m convinced this was baseline/pipeline drift, as I suggested in a comment on [FINERACT-1152](https://issues.apache.org/jira/browse/FINERACT-1152). Could you please approve the workflows again? And if you have time, could you also review my changes?
I’m also posting evidence of the corresponding e2e checks passing locally:
**EMICalculation-Part2**
<img width="1600" height="860" alt="image" src="https://github.com/user-attachments/assets/5cbc4a3f-96e3-44e3-9b8a-847ea007c0ac" />
**LoanChargeOff-part4**
<img width="1600" height="860" alt="image" src="https://github.com/user-attachments/assets/a8f60ec1-bc4b-4ec3-b194-cee2ae4beb16" />
Please let me know if there is anything wrong.
[WorkflowLink](https://github.com/apache/fineract/actions/runs/23504920482/job/68411700556)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] FINERACT-1152: Use projected schedule to validate EMI end date in loan reschedule [fineract]
Posted by "DeathGun44 (via GitHub)" <gi...@apache.org>.
DeathGun44 commented on PR #5689:
URL: https://github.com/apache/fineract/pull/5689#issuecomment-4160384556
Other than that I like this approach ,LGTM
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] FINERACT-1152: Use projected schedule to validate EMI end date in loan reschedule [fineract]
Posted by "San-43 (via GitHub)" <gi...@apache.org>.
San-43 commented on code in PR #5689:
URL: https://github.com/apache/fineract/pull/5689#discussion_r3031809882
##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java:
##########
@@ -289,32 +279,111 @@ private void createLoanTermVariationsForRegularLoans(final Loan loan, final Inte
parent = createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate,
loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(graceOnPrincipal),
parent);
+ pendingRescheduleVariations.add(parent);
BigDecimal extraTermsBasedOnGracePeriods = BigDecimal.valueOf(graceOnPrincipal);
- createLoanTermVariations(loanRescheduleRequest, LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue(), loan,
- rescheduleFromDate, dueDate, loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment,
- extraTermsBasedOnGracePeriods, parent);
+ LoanTermVariations extraTermsVariation = createLoanTermVariations(loanRescheduleRequest,
+ LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue(), loan, rescheduleFromDate, dueDate,
+ loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, extraTermsBasedOnGracePeriods, parent);
+ pendingRescheduleVariations.add(extraTermsVariation);
}
if (rescheduleFromDate != null && graceOnInterest != null) {
LoanTermVariations parent = null;
final Integer termType = LoanTermVariationType.GRACE_ON_INTEREST.getValue();
- createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate,
- loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(graceOnInterest),
- parent);
+ LoanTermVariations loanTermVariation = createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate,
+ dueDate, loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment,
+ BigDecimal.valueOf(graceOnInterest), parent);
+ pendingRescheduleVariations.add(loanTermVariation);
}
if (rescheduleFromDate != null && extraTerms != null) {
LoanTermVariations parent = null;
final Integer termType = LoanTermVariationType.EXTEND_REPAYMENT_PERIOD.getValue();
- createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate, dueDate,
- loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment, BigDecimal.valueOf(extraTerms),
- parent);
+ LoanTermVariations loanTermVariation = createLoanTermVariations(loanRescheduleRequest, termType, loan, rescheduleFromDate,
+ dueDate, loanRescheduleRequestToTermVariationMappings, isActive, isSpecificToInstallment,
+ BigDecimal.valueOf(extraTerms), parent);
+ pendingRescheduleVariations.add(loanTermVariation);
+ }
+
+ if (rescheduleFromDate != null && endDate != null && emi != null) {
+ LoanTermVariations parent = null;
+ final Integer termType = LoanTermVariationType.EMI_AMOUNT.getValue();
+ int emiVariationsCreated = 0;
+ List<LocalDate> projectedInstallmentDueDates = getProjectedInstallmentDueDates(loan, rescheduleFromDate,
+ pendingRescheduleVariations);
+ for (LocalDate installmentDueDate : projectedInstallmentDueDates) {
+ if (!DateUtils.isBefore(installmentDueDate, rescheduleFromDate) && !DateUtils.isAfter(installmentDueDate, endDate)) {
+ createLoanTermVariations(loanRescheduleRequest, termType, loan, installmentDueDate, installmentDueDate,
+ loanRescheduleRequestToTermVariationMappings, isActive, true, emi, parent);
+ emiVariationsCreated++;
+ }
+ if (DateUtils.isAfter(installmentDueDate, endDate)) {
+ break;
+ }
+ }
+ if (emiVariationsCreated == 0) {
+ List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+ final DataValidatorBuilder dataValidatorBuilder = new DataValidatorBuilder(dataValidationErrors)
+ .resource(RescheduleLoansApiConstants.ENTITY_NAME);
+ dataValidatorBuilder.reset().parameter(RescheduleLoansApiConstants.endDateParamName).failWithCode(
+ "end.date.before.next.installment", "End date must be on or after the next projected installment date");
+ throw new PlatformApiDataValidationException(dataValidationErrors);
+ }
}
loanRescheduleRequest.updateLoanRescheduleRequestToTermVariationMappings(loanRescheduleRequestToTermVariationMappings);
}
+ private List<LocalDate> getProjectedInstallmentDueDates(final Loan loan, final LocalDate rescheduleFromDate,
+ final List<LoanTermVariations> pendingRescheduleVariations) {
+ ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, rescheduleFromDate);
+ final LoanApplicationTerms loanApplicationTerms = loanTermVariationsMapper.constructLoanApplicationTerms(scheduleGeneratorDTO,
+ loan);
+ List<LoanTermVariationsData> projectedVariations = buildProjectedLoanTermVariatons(loanApplicationTerms,
Review Comment:
Thanks @DeathGun44, I may be missing it, but I don’t see the typo here. Could you point out which part should be Variations?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: issues-unsubscribe@fineract.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org