Skip to content

Conversation

ruzeynalov
Copy link
Contributor

Description

Describe the changes made and why they were made.

Ignore if these details are present on the associated Apache Fineract JIRA ticket.

Checklist

Please make sure these boxes are checked before submitting your pull request - thanks!

  • Write the commit message as per https://github.com/apache/fineract/#pull-requests
  • 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.
  • [] Create/update unit or integration tests for verifying the changes made.
  • Follow coding conventions at https://cwiki.apache.org/confluence/display/FINERACT/Coding+Conventions.
  • [] 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
  • Submission is not a "code dump". (Large changes can be made "in repository" via a branch. Ask on the developer mailing list for guidance, if required.)

FYI our guidelines for code reviews are at https://cwiki.apache.org/confluence/display/FINERACT/Code+Review+Guide.

@ruzeynalov ruzeynalov marked this pull request as draft September 24, 2025 11:58
@ruzeynalov ruzeynalov force-pushed the FINERACT-2354/reaging-for-interest-bearing-products-interest-calculation-default-behaviour branch 4 times, most recently from 2ca485f to f9b159c Compare October 2, 2025 11:22
@ruzeynalov ruzeynalov force-pushed the FINERACT-2354/reaging-for-interest-bearing-products-interest-calculation-default-behaviour branch from f9b159c to 966268f Compare October 7, 2025 12:51
@mariiaKraievska mariiaKraievska force-pushed the FINERACT-2354/reaging-for-interest-bearing-products-interest-calculation-default-behaviour branch 2 times, most recently from 913e0a7 to a68ea39 Compare October 13, 2025 08:23
@ruzeynalov ruzeynalov force-pushed the FINERACT-2354/reaging-for-interest-bearing-products-interest-calculation-default-behaviour branch from e6d847a to 391fbda Compare October 15, 2025 08:00
@ruzeynalov ruzeynalov marked this pull request as ready for review October 15, 2025 08:01
@mariiaKraievska mariiaKraievska force-pushed the FINERACT-2354/reaging-for-interest-bearing-products-interest-calculation-default-behaviour branch from 391fbda to c70e3c5 Compare October 15, 2025 08:07
…t bearing products with interest calculation: default behavior
@adamsaghy adamsaghy force-pushed the FINERACT-2354/reaging-for-interest-bearing-products-interest-calculation-default-behaviour branch from c70e3c5 to c354140 Compare October 15, 2025 09:45
.isEqualTo("validation.msg.loan.reAge.numberOfInstallments.not.greater.than.zero");
}

@Disabled
Copy link
Contributor

@adamsaghy adamsaghy Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this test is not valid anymore, remove it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

.isEqualTo("error.msg.loan.reage.supported.only.for.progressive.loan.schedule.type");
}

@Disabled
Copy link
Contributor

@adamsaghy adamsaghy Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this test is not valid anymore, remove it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment on lines 3061 to 3084
final LoanApplicationTerms loanApplicationTerms = new LoanApplicationTerms.Builder().submittedOnDate(expectedDisbursementDate)
.currency(currency.getCurrencyData()).repaymentsStartingFromDate(reAgingStartDate)
.expectedDisbursementDate(expectedDisbursementDate).principal(outstandingPrincipalBalance.get())
.loanTermFrequency(loanTransaction.getLoanReAgeParameter().getNumberOfInstallments())
.loanTermPeriodFrequencyType(loanTransaction.getLoanReAgeParameter().getFrequencyType())
.numberOfRepayments(loanTransaction.getLoanReAgeParameter().getNumberOfInstallments())
.repaymentEvery(loanTransaction.getLoanReAgeParameter().getFrequencyNumber())
.repaymentPeriodFrequencyType(loanTransaction.getLoanReAgeParameter().getFrequencyType())
.interestRatePerPeriod(interestRate)
.interestRatePeriodFrequencyType(loan.getLoanRepaymentScheduleDetail().getRepaymentPeriodFrequencyType())
.annualNominalInterestRate(interestRate).daysInMonthType(loan.getLoanProduct().fetchDaysInMonthType())
.daysInYearType(loan.getLoanProduct().fetchDaysInYearType()).inArrearsTolerance(Money.zero(currency, mc))
.disbursementDatas(disbursementData).isDownPaymentEnabled(false).downPaymentPercentage(ZERO).seedDate(reAgingStartDate)
.interestRecognitionOnDisbursementDate(
loan.getLoanProduct().getLoanProductRelatedDetail().isInterestRecognitionOnDisbursementDate())
.daysInYearCustomStrategy(loan.getLoanProduct().getLoanProductRelatedDetail().getDaysInYearCustomStrategy())
.interestMethod(loan.getLoanProductRelatedDetail().getInterestMethod()).allowPartialPeriodInterestCalculation(
loan.getLoanProduct().getLoanProductRelatedDetail().isAllowPartialPeriodInterestCalculation())
.mc(mc).build();
final LoanScheduleModel loanScheduleModelForReAging = scheduleGenerator.generate(mc, loanApplicationTerms, null, null);

// Now merge the temporary schedule with existing installments
mergeTemporaryScheduleWithExistingInstallments(loanScheduleModelForReAging, installments, repaymentPeriods, currency,
transactionDate, ctx, loan);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mariiaKraievska Do we need this? I mean ProgressiveEMICalculator and existing ProgressiveLoanInterestScheduleModel + reage parameters would be enough to generate and update the existing ProgressiveLoanInterestScheduleModel and once its done, just update the LoanRepaymentScheduleInstallment based on the model. what do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, please check

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what changed here?

if (chargeOffTransaction.isPresent()) {
repaymentPeriods.stream().filter(rp -> !rp.getDueDate().isBefore(reAgingStartDate) && !rp.isFullyPaid())
.forEach(repaymentPeriod -> {
repaymentPeriod.getInterestPeriods().forEach(interestPeriod -> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why to set 0 rate factor and mark them as paused?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, it's enough to pause them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why to pause them? :D

…ult Behavior, interestRecalculation = true, without dueDate change
@mariiaKraievska mariiaKraievska force-pushed the FINERACT-2354/reaging-for-interest-bearing-products-interest-calculation-default-behaviour branch from c354140 to 3329a93 Compare October 15, 2025 12:00
@mariiaKraievska
Copy link
Contributor

PTAL

Comment on lines +2989 to +2992
final Optional<LoanTransaction> chargeOffTransaction = ctx.getAlreadyProcessedTransactions().stream()
.filter(t -> ((t.isChargeOff() && (loan.hasAccelerateChargeOffStrategy() || loan.hasZeroInterestChargeOffStrategy()))
|| t.isContractTermination()) && !t.isReversed() && t.getTransactionDate().isBefore(reAgingStartDate))
.findFirst();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its 2 types of transactions: chargeoff and contract termination

Comment on lines +2989 to +2992
final Optional<LoanTransaction> chargeOffTransaction = ctx.getAlreadyProcessedTransactions().stream()
.filter(t -> ((t.isChargeOff() && (loan.hasAccelerateChargeOffStrategy() || loan.hasZeroInterestChargeOffStrategy()))
|| t.isContractTermination()) && !t.isReversed() && t.getTransactionDate().isBefore(reAgingStartDate))
.findFirst();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if txn date and reage start date are matching?

Comment on lines +3078 to +3080
loan.getLoanProduct().getLoanProductRelatedDetail().isAllowPartialPeriodInterestCalculation())
.mc(mc).build();
final LoanScheduleModel loanScheduleModelForReAging = scheduleGenerator.generate(mc, loanApplicationTerms, null, null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think we need this. scheduleGenerator we should use the existing model + the EmiCalculator and introduce a new action: "reage" and provide its parameters. THe EmiCalculator can calculate interim models and update existing one based on that. After the model is updated we can use to update the existing repayment installments based on the model alone.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants