FINERACT-2181: Fix for certain interest recalculation settings making prepay api and payment allocation inconsistent

This commit is contained in:
mark.vituska
2025-07-07 17:04:17 +02:00
committed by Adam Saghy
parent 01f850aecc
commit df995bc932
11 changed files with 332 additions and 146 deletions
@@ -35,6 +35,7 @@ import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
import org.apache.fineract.portfolio.loanaccount.domain.ChangedTransactionDetail;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
import org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalculationDetails;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
@@ -73,6 +74,13 @@ public class LoanTransactionProcessingServiceImpl implements LoanTransactionProc
if (!DateUtils.isEqualBusinessDate(loanTransaction.getTransactionDate())) {
return false;
}
LoanInterestRecalculationDetails interestRecalculationDetails = loan.getLoanInterestRecalculationDetails();
if (interestRecalculationDetails != null && ((interestRecalculationDetails.getRestFrequencyType().isSameAsRepayment()
&& interestRecalculationDetails.getPreCloseInterestCalculationStrategy().calculateTillPreClosureDateEnabled())
|| (interestRecalculationDetails.getRestFrequencyType().isDaily()
&& interestRecalculationDetails.getPreCloseInterestCalculationStrategy().calculateTillRestFrequencyEnabled()))) {
return false;
}
if (loan.isProgressiveSchedule()) {
return modelRepository.hasValidModelForDate(loan.getId(), loanTransaction.getTransactionDate());
}
@@ -1246,6 +1246,22 @@ public final class LoanProductDataValidator {
baseDataValidator.reset().parameter(LoanProductConstants.preClosureInterestCalculationStrategyParamName)
.value(preCloseInterestCalculationStrategy).ignoreIfNull().inMinMaxRange(
LoanPreCloseInterestCalculationStrategy.getMinValue(), LoanPreCloseInterestCalculationStrategy.getMaxValue());
String loanScheduleType = LoanScheduleType.CUMULATIVE.toString();
if (fromApiJsonHelper.parameterExists(LoanProductConstants.LOAN_SCHEDULE_TYPE, element)) {
loanScheduleType = fromApiJsonHelper.extractStringNamed(LoanProductConstants.LOAN_SCHEDULE_TYPE, element);
}
if (LoanScheduleType.PROGRESSIVE.equals(LoanScheduleType.valueOf(loanScheduleType))
&& preCloseInterestCalculationStrategy != null) {
LoanPreCloseInterestCalculationStrategy preCloseStrategy = LoanPreCloseInterestCalculationStrategy
.fromInt(preCloseInterestCalculationStrategy);
if (preCloseStrategy.calculateTillRestFrequencyEnabled() && !frequencyType.isSameAsRepayment() && !frequencyType.isDaily()) {
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
"when.preclose.strategy.is.till.rest.frequency.then.frequency.type.is.daily.or.same.as.repayment",
"When the pre-close interest calculation strategy is set to `Till Rest Frequency Date` "
+ "the frequency of outstanding principal calculation must be `Daily` or `Same as repayment period`.");
}
}
}
public void validateForUpdate(final JsonCommand command, final LoanProduct loanProduct) {