FINERACT-2220: Use stored ProgressiveLoanInterestScheduleModel for calculation
This commit is contained in:
+6
-5
@@ -1187,7 +1187,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
||||
.sorted(Comparator.comparing(LoanRepaymentScheduleInstallment::getInstallmentNumber)).toList();
|
||||
}
|
||||
|
||||
private void recalculateInterestForDate(LocalDate targetDate, ProgressiveTransactionCtx ctx) {
|
||||
public void recalculateInterestForDate(LocalDate targetDate, ProgressiveTransactionCtx ctx) {
|
||||
if (ctx.getInstallments() != null && !ctx.getInstallments().isEmpty()) {
|
||||
Loan loan = ctx.getInstallments().get(0).getLoan();
|
||||
if (loan.isInterestBearingAndInterestRecalculationEnabled() && !loan.isNpa() && !ctx.isChargedOff()) {
|
||||
@@ -1240,17 +1240,18 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
||||
LocalDate toDate = currentInstallment.getDueDate();
|
||||
boolean hasUpdate = false;
|
||||
|
||||
if (!currentDate.equals(ctx.getLastOverdueBalanceChange())) {
|
||||
if (!currentDate.equals(ctx.getModel().lastOverdueBalanceChange())) {
|
||||
// if we have same date for fromDate & last overdue balance change then it means we have the up-to-date
|
||||
// model.
|
||||
if (ctx.getLastOverdueBalanceChange() == null || currentInstallment.getFromDate().isAfter(ctx.getLastOverdueBalanceChange())) {
|
||||
if (ctx.getModel().lastOverdueBalanceChange() == null
|
||||
|| currentInstallment.getFromDate().isAfter(ctx.getModel().lastOverdueBalanceChange())) {
|
||||
// first overdue hit for installment. setting overdue balance correction from instalment from date.
|
||||
emiCalculator.addBalanceCorrection(ctx.getModel(), fromDate, overduePrincipal);
|
||||
} else {
|
||||
// not the first balance correction on installment period, then setting overdue balance correction from
|
||||
// last balance change's current date. previous interest period already has the correct balance
|
||||
// correction.
|
||||
emiCalculator.addBalanceCorrection(ctx.getModel(), ctx.getLastOverdueBalanceChange(), overduePrincipal);
|
||||
emiCalculator.addBalanceCorrection(ctx.getModel(), ctx.getModel().lastOverdueBalanceChange(), overduePrincipal);
|
||||
}
|
||||
|
||||
hasUpdate = true;
|
||||
@@ -1263,7 +1264,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
||||
lastOverdueBalanceChange = currentDate;
|
||||
}
|
||||
emiCalculator.addBalanceCorrection(ctx.getModel(), lastOverdueBalanceChange, aggregatedOverDuePrincipal.negated());
|
||||
ctx.setLastOverdueBalanceChange(lastOverdueBalanceChange);
|
||||
ctx.getModel().lastOverdueBalanceChange(lastOverdueBalanceChange);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-3
@@ -18,7 +18,6 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -38,8 +37,6 @@ import org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanIntere
|
||||
public class ProgressiveTransactionCtx extends TransactionCtx {
|
||||
|
||||
private final ProgressiveLoanInterestScheduleModel model;
|
||||
@Setter
|
||||
private LocalDate lastOverdueBalanceChange = null;
|
||||
private List<LoanTransaction> alreadyProcessedTransactions = new ArrayList<>();
|
||||
@Setter
|
||||
private Money sumOfInterestRefundAmount;
|
||||
|
||||
+7
@@ -18,16 +18,23 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.service;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.Optional;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.ProgressiveLoanModel;
|
||||
import org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
|
||||
|
||||
public interface InterestScheduleModelRepositoryWrapper {
|
||||
|
||||
Optional<ProgressiveLoanModel> findOneByLoanId(Long loanId);
|
||||
|
||||
Optional<ProgressiveLoanInterestScheduleModel> extractModel(Optional<ProgressiveLoanModel> progressiveLoanModel);
|
||||
|
||||
String writeInterestScheduleModel(Loan loan, ProgressiveLoanInterestScheduleModel model);
|
||||
|
||||
Optional<ProgressiveLoanInterestScheduleModel> readProgressiveLoanInterestScheduleModel(Long loanId,
|
||||
LoanProductMinimumRepaymentScheduleRelatedDetail detail, Integer installmentAmountInMultipliesOf);
|
||||
|
||||
Optional<ProgressiveLoanInterestScheduleModel> getSavedModel(Loan loan, LocalDate businessDate);
|
||||
}
|
||||
|
||||
+57
-9
@@ -18,14 +18,23 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.service;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.FlushModeType;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import jakarta.transaction.Transactional;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.ChangedTransactionDetail;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.ProgressiveLoanModel;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.AdvancedPaymentScheduleTransactionProcessor;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.ProgressiveTransactionCtx;
|
||||
import org.apache.fineract.portfolio.loanaccount.repository.ProgressiveLoanModelRepository;
|
||||
import org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
|
||||
@@ -37,6 +46,9 @@ public class InterestScheduleModelRepositoryWrapperImpl implements InterestSched
|
||||
|
||||
private final ProgressiveLoanModelRepository loanModelRepository;
|
||||
private final ProgressiveLoanInterestScheduleModelParserService progressiveLoanInterestScheduleModelParserService;
|
||||
private final AdvancedPaymentScheduleTransactionProcessor advancedPaymentScheduleTransactionProcessor;
|
||||
@PersistenceContext
|
||||
private final EntityManager entityManager;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
@@ -45,18 +57,54 @@ public class InterestScheduleModelRepositoryWrapperImpl implements InterestSched
|
||||
return null;
|
||||
}
|
||||
String jsonModel = progressiveLoanInterestScheduleModelParserService.toJson(model);
|
||||
ProgressiveLoanModel progressiveLoanModel = loanModelRepository.findOneByLoanId(loan.getId()).orElseGet(() -> {
|
||||
ProgressiveLoanModel plm = new ProgressiveLoanModel();
|
||||
plm.setLoan(loan);
|
||||
return plm;
|
||||
});
|
||||
progressiveLoanModel.setBusinessDate(ThreadLocalContextUtil.getBusinessDate());
|
||||
progressiveLoanModel.setLastModifiedDate(DateUtils.getAuditOffsetDateTime());
|
||||
progressiveLoanModel.setJsonModel(jsonModel);
|
||||
loanModelRepository.save(progressiveLoanModel);
|
||||
try {
|
||||
entityManager.setFlushMode(FlushModeType.COMMIT);
|
||||
ProgressiveLoanModel progressiveLoanModel = loanModelRepository.findOneByLoanId(loan.getId()).orElseGet(() -> {
|
||||
ProgressiveLoanModel plm = new ProgressiveLoanModel();
|
||||
plm.setLoan(loan);
|
||||
return plm;
|
||||
});
|
||||
progressiveLoanModel.setBusinessDate(ThreadLocalContextUtil.getBusinessDate());
|
||||
progressiveLoanModel.setLastModifiedDate(DateUtils.getAuditOffsetDateTime());
|
||||
progressiveLoanModel.setJsonModel(jsonModel);
|
||||
loanModelRepository.save(progressiveLoanModel);
|
||||
} finally {
|
||||
entityManager.setFlushMode(FlushModeType.AUTO);
|
||||
}
|
||||
return jsonModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ProgressiveLoanModel> findOneByLoanId(Long loanId) {
|
||||
return loanModelRepository.findOneByLoanId(loanId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ProgressiveLoanInterestScheduleModel> extractModel(Optional<ProgressiveLoanModel> progressiveLoanModel) {
|
||||
return progressiveLoanModel.map(ProgressiveLoanModel::getJsonModel) //
|
||||
.map(jsonModel -> progressiveLoanInterestScheduleModelParserService.fromJson(jsonModel,
|
||||
progressiveLoanModel.get().getLoan().getLoanProductRelatedDetail(), MoneyHelper.getMathContext(),
|
||||
progressiveLoanModel.get().getLoan().getLoanProduct().getInstallmentAmountInMultiplesOf()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ProgressiveLoanInterestScheduleModel> getSavedModel(Loan loan, LocalDate businessDate) {
|
||||
Optional<ProgressiveLoanModel> progressiveLoanModel = findOneByLoanId(loan.getId());
|
||||
Optional<ProgressiveLoanInterestScheduleModel> savedModel;
|
||||
if (progressiveLoanModel.isPresent() && !progressiveLoanModel.get().getBusinessDate().isAfter(businessDate)) {
|
||||
savedModel = extractModel(progressiveLoanModel);
|
||||
if (progressiveLoanModel.get().getBusinessDate().isBefore(businessDate) && savedModel.isPresent()) {
|
||||
ProgressiveTransactionCtx ctx = new ProgressiveTransactionCtx(loan.getCurrency(), loan.getRepaymentScheduleInstallments(),
|
||||
Set.of(), new MoneyHolder(loan.getTotalOverpaidAsMoney()), new ChangedTransactionDetail(), savedModel.get());
|
||||
ctx.setChargedOff(loan.isChargedOff());
|
||||
advancedPaymentScheduleTransactionProcessor.recalculateInterestForDate(businessDate, ctx);
|
||||
}
|
||||
} else {
|
||||
savedModel = Optional.empty();
|
||||
}
|
||||
return savedModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ProgressiveLoanInterestScheduleModel> readProgressiveLoanInterestScheduleModel(final Long loanId,
|
||||
final LoanProductMinimumRepaymentScheduleRelatedDetail detail, final Integer installmentAmountInMultipliesOf) {
|
||||
|
||||
+4
@@ -41,6 +41,7 @@ import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.apache.fineract.infrastructure.core.serialization.gson.JsonExclude;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
@@ -67,6 +68,9 @@ public class ProgressiveLoanInterestScheduleModel {
|
||||
private final Money zero;
|
||||
private final Map<LoanInterestScheduleModelModifiers, Boolean> modifiers;
|
||||
|
||||
@Setter
|
||||
private LocalDate lastOverdueBalanceChange;
|
||||
|
||||
public ProgressiveLoanInterestScheduleModel(final List<RepaymentPeriod> repaymentPeriods,
|
||||
final LoanProductMinimumRepaymentScheduleRelatedDetail loanProductRelatedDetail,
|
||||
final List<LoanTermVariationsData> loanTermVariations, final Integer installmentAmountInMultiplesOf, final MathContext mc) {
|
||||
|
||||
Reference in New Issue
Block a user