FINERACT-2354: In case full transaction reprocessing, we need to recalculate the schedule as well
This commit is contained in:
+2
-3
@@ -51,11 +51,10 @@ public class ProgressivePossibleNextRepaymentCalculationServiceImpl extends Abst
|
||||
Optional<ProgressiveLoanModel> progressiveLoanModel = interestScheduleModelRepository.findOneByLoan(loan);
|
||||
Optional<ProgressiveLoanInterestScheduleModel> optionalScheduleModel = interestScheduleModelRepository
|
||||
.extractModel(progressiveLoanModel);
|
||||
ProgressiveLoanInterestScheduleModel scheduleModel = optionalScheduleModel.orElseGet(
|
||||
() -> advancedPaymentScheduleTransactionProcessor.calculateInterestScheduleModel(loan.getId(), nextPaymentDueDate));
|
||||
if (scheduleModel == null) {
|
||||
if (optionalScheduleModel.isEmpty()) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
ProgressiveLoanInterestScheduleModel scheduleModel = optionalScheduleModel.get();
|
||||
List<LoanRepaymentScheduleInstallment> repaymentScheduleInstallments = loan.getRepaymentScheduleInstallments();
|
||||
ProgressiveTransactionCtx ctx = new ProgressiveTransactionCtx(loan.getCurrency(), repaymentScheduleInstallments, Set.of(),
|
||||
new MoneyHolder(loan.getTotalOverpaidAsMoney()), new ChangedTransactionDetail(), scheduleModel);
|
||||
|
||||
+6
-34
@@ -84,14 +84,12 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalculatio
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanPaymentAllocationRule;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleProcessingWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariations;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionComparator;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelation;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelationTypeEnum;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionToRepaymentScheduleMapping;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.SingleLoanChargeRepaymentScheduleProcessingWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeParameter;
|
||||
@@ -119,8 +117,6 @@ import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationType;
|
||||
import org.apache.fineract.util.LoopContext;
|
||||
import org.apache.fineract.util.LoopGuard;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRepaymentScheduleTransactionProcessor {
|
||||
@@ -129,23 +125,18 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
||||
public static final String ADVANCED_PAYMENT_ALLOCATION_STRATEGY_NAME = "Advanced payment allocation strategy";
|
||||
|
||||
private final EMICalculator emiCalculator;
|
||||
private final LoanRepositoryWrapper loanRepositoryWrapper;
|
||||
private final InterestRefundService interestRefundService;
|
||||
private final LoanScheduleComponent loanSchedule;
|
||||
private final LoanTransactionRepository loanTransactionRepository;
|
||||
private final LoanChargeService loanChargeService;
|
||||
private final SingleLoanChargeRepaymentScheduleProcessingWrapper loanChargeRepaymentScheduleProcessing;
|
||||
|
||||
public AdvancedPaymentScheduleTransactionProcessor(final EMICalculator emiCalculator, final LoanRepositoryWrapper loanRepositoryWrapper,
|
||||
final InterestRefundService interestRefundService, final ExternalIdFactory externalIdFactory,
|
||||
final LoanScheduleComponent loanSchedule, final LoanTransactionRepository loanTransactionRepository,
|
||||
public AdvancedPaymentScheduleTransactionProcessor(final EMICalculator emiCalculator, final InterestRefundService interestRefundService,
|
||||
final ExternalIdFactory externalIdFactory, final LoanScheduleComponent loanSchedule,
|
||||
final LoanChargeValidator loanChargeValidator, final LoanBalanceService loanBalanceService,
|
||||
final LoanChargeService loanChargeService) {
|
||||
super(externalIdFactory, loanChargeValidator, loanBalanceService);
|
||||
this.emiCalculator = emiCalculator;
|
||||
this.loanRepositoryWrapper = loanRepositoryWrapper;
|
||||
this.interestRefundService = interestRefundService;
|
||||
this.loanTransactionRepository = loanTransactionRepository;
|
||||
this.loanSchedule = loanSchedule;
|
||||
this.loanChargeService = loanChargeService;
|
||||
this.loanChargeRepaymentScheduleProcessing = new SingleLoanChargeRepaymentScheduleProcessingWrapper();
|
||||
@@ -195,13 +186,6 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Pair<ChangedTransactionDetail, ProgressiveLoanInterestScheduleModel> reprocessProgressiveLoanTransactionsTransactional(
|
||||
final LocalDate disbursementDate, final LocalDate targetDate, final List<LoanTransaction> loanTransactions,
|
||||
final MonetaryCurrency currency, final List<LoanRepaymentScheduleInstallment> installments, final Set<LoanCharge> charges) {
|
||||
return reprocessProgressiveLoanTransactions(disbursementDate, targetDate, loanTransactions, currency, installments, charges);
|
||||
}
|
||||
|
||||
// only for progressive loans
|
||||
public Pair<ChangedTransactionDetail, ProgressiveLoanInterestScheduleModel> reprocessProgressiveLoanTransactions(
|
||||
LocalDate disbursementDate, LocalDate targetDate, List<LoanTransaction> loanTransactions, MonetaryCurrency currency,
|
||||
@@ -302,18 +286,6 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
||||
return result.getLeft();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
|
||||
public ProgressiveLoanInterestScheduleModel calculateInterestScheduleModel(@NotNull Long loanId, LocalDate targetDate) {
|
||||
Loan loan = loanRepositoryWrapper.findOneWithNotFoundDetection(loanId);
|
||||
final List<LoanTransaction> transactions = loanTransactionRepository.findNonReversedTransactionsForReprocessingByLoan(loan);
|
||||
MonetaryCurrency currency = loan.getLoanRepaymentScheduleDetail().getCurrency();
|
||||
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
|
||||
Set<LoanCharge> charges = loan.getActiveCharges();
|
||||
return reprocessProgressiveLoanTransactions(loan.getDisbursementDate(), targetDate, transactions, currency, installments, charges)
|
||||
.getRight();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static LoanTransaction getProcessedTransaction(final ChangedTransactionDetail changedTransactionDetail,
|
||||
final LoanTransaction transaction) {
|
||||
@@ -2937,9 +2909,8 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
||||
|
||||
private void updateInstallmentsByModelForReAging(final LoanTransaction loanTransaction, final ProgressiveTransactionCtx ctx) {
|
||||
ctx.getModel().repaymentPeriods().forEach(rp -> {
|
||||
final LoanRepaymentScheduleInstallment installment = ctx.getInstallments().stream().filter(
|
||||
ri -> ri.getFromDate().equals(rp.getFromDate()) && ri.getDueDate().equals(rp.getDueDate()) && !ri.isDownPayment())
|
||||
.findFirst().orElse(null);
|
||||
final LoanRepaymentScheduleInstallment installment = ctx.getInstallments().stream()
|
||||
.filter(ri -> ri.getFromDate().equals(rp.getFromDate()) && !ri.isDownPayment()).findFirst().orElse(null);
|
||||
final LocalDate transactionDate = loanTransaction.getTransactionDate();
|
||||
if (installment != null) {
|
||||
installment.setFromDate(rp.getFromDate());
|
||||
@@ -2953,6 +2924,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
||||
installment.updateInterestCharged(rp.getDueInterest().getAmount());
|
||||
}
|
||||
installment.setReAged(true);
|
||||
installment.setAdditional(false);
|
||||
installment.updateObligationsMet(ctx.getCurrency(), transactionDate);
|
||||
} else {
|
||||
final LoanRepaymentScheduleInstallment lastInstallment = ctx.getInstallments().getLast();
|
||||
@@ -3247,7 +3219,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
||||
final BigDecimal interestRate = loan.getLoanRepaymentScheduleDetail().getAnnualNominalInterestRate();
|
||||
final Money totalOutstandingPrincipal = ctx.getModel().getTotalOutstandingPrincipal();
|
||||
|
||||
final LoanApplicationTerms loanApplicationTerms = new LoanApplicationTerms.Builder().currency(currency.getCurrencyData())
|
||||
final LoanApplicationTerms loanApplicationTerms = new LoanApplicationTerms.Builder().currency(currency.toData())
|
||||
.repaymentsStartingFromDate(reAgingStartDate).principal(totalOutstandingPrincipal)
|
||||
.loanTermFrequency(loanTransaction.getLoanReAgeParameter().getNumberOfInstallments())
|
||||
.loanTermPeriodFrequencyType(loanTransaction.getLoanReAgeParameter().getFrequencyType())
|
||||
|
||||
+6
-6
@@ -202,8 +202,7 @@ public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
|
||||
|
||||
Optional<ProgressiveLoanInterestScheduleModel> savedModel = interestScheduleModelRepositoryWrapper.getSavedModel(loan,
|
||||
transactionDate);
|
||||
ProgressiveLoanInterestScheduleModel model = savedModel
|
||||
.orElseGet(() -> processor.calculateInterestScheduleModel(loan.getId(), transactionDate));
|
||||
ProgressiveLoanInterestScheduleModel model = savedModel.orElseThrow();
|
||||
OutstandingDetails outstandingAmounts = emiCalculator.getOutstandingAmountsTillDate(model, transactionDate);
|
||||
// TODO: We should add all the past due outstanding amounts as well
|
||||
OutstandingAmountsDTO result = new OutstandingAmountsDTO(currency) //
|
||||
@@ -245,8 +244,7 @@ public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
|
||||
return Money.zero(loan.getCurrency());
|
||||
}
|
||||
Optional<ProgressiveLoanInterestScheduleModel> savedModel = interestScheduleModelRepositoryWrapper.getSavedModel(loan, targetDate);
|
||||
ProgressiveLoanInterestScheduleModel model = savedModel
|
||||
.orElseGet(() -> processor.calculateInterestScheduleModel(loan.getId(), targetDate));
|
||||
ProgressiveLoanInterestScheduleModel model = savedModel.orElseThrow();
|
||||
return emiCalculator.getPeriodInterestTillDate(model, installment.getDueDate(), targetDate, false);
|
||||
}
|
||||
|
||||
@@ -438,7 +436,8 @@ public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
|
||||
} else {
|
||||
amount = amount.add(principalInterestForThisPeriod.principal().getAmount());
|
||||
}
|
||||
BigDecimal loanChargeAmt = amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100), mc);
|
||||
Money loanChargeAmt = Money.of(cumulative.getCurrency(),
|
||||
amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100), mc));
|
||||
cumulative = cumulative.plus(loanChargeAmt);
|
||||
} else {
|
||||
cumulative = cumulative.plus(loanCharge.amountOrPercentage());
|
||||
@@ -456,7 +455,8 @@ public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
|
||||
} else {
|
||||
amount = amount.add(principalDisbursed.getAmount());
|
||||
}
|
||||
BigDecimal loanChargeAmt = amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100), mc);
|
||||
Money loanChargeAmt = Money.of(cumulative.getCurrency(),
|
||||
amount.multiply(loanCharge.getPercentage()).divide(BigDecimal.valueOf(100), mc));
|
||||
cumulative = cumulative.plus(loanChargeAmt);
|
||||
return cumulative;
|
||||
}
|
||||
|
||||
+37
-2
@@ -1,3 +1,21 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.mapper;
|
||||
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
@@ -7,7 +25,9 @@ import org.apache.fineract.portfolio.common.domain.DaysInYearType;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanproduct.data.LoanConfigurationDetails;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanPreCloseInterestCalculationStrategy;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.RecalculationFrequencyType;
|
||||
|
||||
public final class LoanConfigurationDetailsMapper {
|
||||
|
||||
@@ -36,7 +56,22 @@ public final class LoanConfigurationDetailsMapper {
|
||||
loanProductRelatedDetail.getRepaymentPeriodFrequencyType(), loanProductRelatedDetail.getRepayEvery(),
|
||||
loanProductRelatedDetail.getNumberOfRepayments(), loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate(),
|
||||
loanProductRelatedDetail.getDaysInYearCustomStrategy(), loanProductRelatedDetail.isAllowPartialPeriodInterestCalculation(),
|
||||
loan.isInterestRecalculationEnabled(), loan.getLoanInterestRecalculationDetails().getRestFrequencyType(),
|
||||
loan.getLoanInterestRecalculationDetails().getPreCloseInterestCalculationStrategy());
|
||||
loan.isInterestRecalculationEnabled(), getRestFrequencyType(loan), getPreCloseInterestCalculationStrategy(loan));
|
||||
}
|
||||
|
||||
private static RecalculationFrequencyType getRestFrequencyType(Loan loan) {
|
||||
if (loan.getLoanInterestRecalculationDetails() != null) {
|
||||
return loan.getLoanInterestRecalculationDetails().getRestFrequencyType();
|
||||
} else {
|
||||
return RecalculationFrequencyType.INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
private static LoanPreCloseInterestCalculationStrategy getPreCloseInterestCalculationStrategy(Loan loan) {
|
||||
if (loan.getLoanInterestRecalculationDetails() != null) {
|
||||
return loan.getLoanInterestRecalculationDetails().getPreCloseInterestCalculationStrategy();
|
||||
} else {
|
||||
return LoanPreCloseInterestCalculationStrategy.NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-7
@@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.loanaccount.service;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -69,6 +70,7 @@ public class CapitalizedIncomeWritePlatformServiceImpl implements CapitalizedInc
|
||||
private final LoanLifecycleStateMachine loanLifecycleStateMachine;
|
||||
private final BusinessEventNotifierService businessEventNotifierService;
|
||||
private final CodeValueRepository codeValueRepository;
|
||||
private final LoanScheduleService loanScheduleService;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
@@ -87,13 +89,13 @@ public class CapitalizedIncomeWritePlatformServiceImpl implements CapitalizedInc
|
||||
final Money capitalizedIncomeAmount = calculateCapitalizedIncomeAmount(loan, transactionAmount);
|
||||
final LoanTransaction capitalizedIncomeTransaction = LoanTransaction.capitalizedIncome(loan, capitalizedIncomeAmount, paymentDetail,
|
||||
transactionDate, txnExternalId);
|
||||
// Update loan with capitalized income
|
||||
loan.addLoanTransaction(capitalizedIncomeTransaction);
|
||||
// Add Loan Transaction classification
|
||||
addClassificationCodeToTransaction(command, LoanTransactionApiConstants.CAPITALIZED_INCOME_CLASSIFICATION_CODE,
|
||||
capitalizedIncomeTransaction);
|
||||
// Recalculate loan transactions
|
||||
recalculateLoanTransactions(loan, transactionDate, capitalizedIncomeTransaction);
|
||||
recalculateLoanTransactions(loan, capitalizedIncomeTransaction);
|
||||
// Update loan with capitalized income
|
||||
loan.addLoanTransaction(capitalizedIncomeTransaction);
|
||||
// Save and flush (PK is set)
|
||||
loanTransactionRepository.saveAndFlush(capitalizedIncomeTransaction);
|
||||
// Create capitalized income balances
|
||||
@@ -144,8 +146,8 @@ public class CapitalizedIncomeWritePlatformServiceImpl implements CapitalizedInc
|
||||
capitalizedIncomeAdjustment.getLoanTransactionRelations().add(LoanTransactionRelation.linkToTransaction(capitalizedIncomeAdjustment,
|
||||
capitalizedIncome.get(), LoanTransactionRelationTypeEnum.ADJUSTMENT));
|
||||
capitalizedIncomeAdjustment.setClassification(capitalizedIncome.get().getClassification());
|
||||
recalculateLoanTransactions(loan, capitalizedIncomeAdjustment);
|
||||
loan.addLoanTransaction(capitalizedIncomeAdjustment);
|
||||
recalculateLoanTransactions(loan, transactionDate, capitalizedIncomeAdjustment);
|
||||
LoanTransaction savedCapitalizedIncomeAdjustment = loanTransactionRepository.saveAndFlush(capitalizedIncomeAdjustment);
|
||||
|
||||
// Update outstanding loan balances
|
||||
@@ -182,9 +184,10 @@ public class CapitalizedIncomeWritePlatformServiceImpl implements CapitalizedInc
|
||||
.build();
|
||||
}
|
||||
|
||||
private void recalculateLoanTransactions(Loan loan, LocalDate transactionDate, LoanTransaction transaction) {
|
||||
if (loan.isInterestRecalculationEnabled() || DateUtils.isBeforeBusinessDate(transactionDate)) {
|
||||
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||
private void recalculateLoanTransactions(Loan loan, LoanTransaction transaction) {
|
||||
if (loan.isInterestRecalculationEnabled() || DateUtils.isBeforeBusinessDate(transaction.getTransactionDate())) {
|
||||
loanScheduleService.regenerateRepaymentSchedule(loan);
|
||||
reprocessLoanTransactionsService.reprocessTransactions(loan, List.of(transaction));
|
||||
} else {
|
||||
reprocessLoanTransactionsService.processLatestTransaction(transaction, loan);
|
||||
}
|
||||
|
||||
+1
-1
@@ -108,7 +108,7 @@ public class InterestScheduleModelRepositoryWrapperImpl implements InterestSched
|
||||
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)) {
|
||||
if (progressiveLoanModel.isPresent()) {
|
||||
savedModel = extractModel(progressiveLoanModel);
|
||||
if (savedModel.isPresent() && progressiveLoanModel.get().getBusinessDate().isBefore(businessDate)) {
|
||||
ProgressiveTransactionCtx ctx = new ProgressiveTransactionCtx(loan.getCurrency(), loan.getRepaymentScheduleInstallments(),
|
||||
|
||||
+6
-27
@@ -28,26 +28,18 @@ import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.fineract.infrastructure.core.boot.FineractProfiles;
|
||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.ChangedTransactionDetail;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.AdvancedPaymentScheduleTransactionProcessor;
|
||||
import org.apache.fineract.portfolio.loanaccount.mapper.LoanConfigurationDetailsMapper;
|
||||
import org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@@ -58,9 +50,9 @@ import org.springframework.stereotype.Component;
|
||||
public class InternalProgressiveLoanApiResource implements InitializingBean {
|
||||
|
||||
private final LoanRepositoryWrapper loanRepository;
|
||||
private final AdvancedPaymentScheduleTransactionProcessor advancedPaymentScheduleTransactionProcessor;
|
||||
private final InterestScheduleModelRepositoryWrapper writePlatformService;
|
||||
private final LoanTransactionRepository loanTransactionRepository;
|
||||
private final InterestScheduleModelRepositoryWrapper interestScheduleModelRepositoryWrapper;
|
||||
private final LoanScheduleService loanScheduleService;
|
||||
|
||||
@Override
|
||||
@SuppressFBWarnings("SLF4J_SIGN_ONLY_FORMAT")
|
||||
@@ -89,28 +81,15 @@ public class InternalProgressiveLoanApiResource implements InitializingBean {
|
||||
}
|
||||
|
||||
private ProgressiveLoanInterestScheduleModel reprocessTransactionsAndGetModel(final Loan loan) {
|
||||
final List<LoanTransaction> transactionsToReprocess = loanTransactionRepository
|
||||
.findNonReversedTransactionsForReprocessingByLoan(loan);
|
||||
final LocalDate businessDate = ThreadLocalContextUtil.getBusinessDate();
|
||||
final Pair<ChangedTransactionDetail, ProgressiveLoanInterestScheduleModel> changedTransactionDetailProgressiveLoanInterestScheduleModelPair = advancedPaymentScheduleTransactionProcessor
|
||||
.reprocessProgressiveLoanTransactionsTransactional(loan.getDisbursementDate(), businessDate, transactionsToReprocess,
|
||||
loan.getCurrency(), loan.getRepaymentScheduleInstallments(), loan.getActiveCharges());
|
||||
final ProgressiveLoanInterestScheduleModel model = changedTransactionDetailProgressiveLoanInterestScheduleModelPair.getRight();
|
||||
final List<Long> replayedTransactions = changedTransactionDetailProgressiveLoanInterestScheduleModelPair.getLeft()
|
||||
.getTransactionChanges().stream().filter(change -> change.getOldTransaction() != null)
|
||||
.map(change -> change.getNewTransaction().getId()).filter(Objects::nonNull).toList();
|
||||
|
||||
if (!replayedTransactions.isEmpty()) {
|
||||
log.warn("Reprocessed transactions show differences: There are unsaved changes of the following transactions: {}",
|
||||
replayedTransactions);
|
||||
}
|
||||
return model;
|
||||
loanScheduleService.regenerateScheduleWithReprocessingTransactions(loan);
|
||||
return interestScheduleModelRepositoryWrapper.extractModel(interestScheduleModelRepositoryWrapper.findOneByLoan(loan)).get();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("{loanId}/model")
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Update and Save ProgressiveLoanInterestScheduleModel", description = "DO NOT USE THIS IN PRODUCTION!")
|
||||
@Transactional
|
||||
public ProgressiveLoanInterestScheduleModel updateModel(@PathParam("loanId") @Parameter(description = "loanId") long loanId) {
|
||||
Loan loan = loanRepository.findOneWithNotFoundDetection(loanId);
|
||||
if (!loan.isProgressiveSchedule()) {
|
||||
|
||||
+3
-2
@@ -38,6 +38,7 @@ import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanBalanceService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanJournalEntryPoster;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanMaximumAmountCalculator;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanScheduleService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.ProgressiveLoanTransactionValidator;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.ProgressiveLoanTransactionValidatorImpl;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.ReprocessLoanTransactionsService;
|
||||
@@ -59,11 +60,11 @@ public class ProgressiveLoanAccountConfiguration {
|
||||
LoanCapitalizedIncomeBalanceRepository capitalizedIncomeBalanceRepository,
|
||||
ReprocessLoanTransactionsService reprocessLoanTransactionsService, LoanBalanceService loanBalanceService,
|
||||
LoanLifecycleStateMachine loanLifecycleStateMachine, BusinessEventNotifierService businessEventNotifierService,
|
||||
CodeValueRepository codeValueRepository) {
|
||||
CodeValueRepository codeValueRepository, LoanScheduleService loanScheduleService) {
|
||||
return new CapitalizedIncomeWritePlatformServiceImpl(loanTransactionValidator, loanAssembler, loanTransactionRepository,
|
||||
paymentDetailWritePlatformService, journalEntryPoster, noteWritePlatformService, externalIdFactory,
|
||||
capitalizedIncomeBalanceRepository, reprocessLoanTransactionsService, loanBalanceService, loanLifecycleStateMachine,
|
||||
businessEventNotifierService, codeValueRepository);
|
||||
businessEventNotifierService, codeValueRepository, loanScheduleService);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
+2
-5
@@ -64,11 +64,9 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanCreditAllocationRule
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalculationDetails;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanPaymentAllocationRule;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelation;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelationTypeEnum;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
||||
@@ -120,9 +118,8 @@ class AdvancedPaymentScheduleTransactionProcessorTest {
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
underTest = new AdvancedPaymentScheduleTransactionProcessor(emiCalculator, Mockito.mock(LoanRepositoryWrapper.class),
|
||||
Mockito.mock(InterestRefundService.class), Mockito.mock(ExternalIdFactory.class), Mockito.mock(LoanScheduleComponent.class),
|
||||
Mockito.mock(LoanTransactionRepository.class), Mockito.mock(LoanChargeValidator.class),
|
||||
underTest = new AdvancedPaymentScheduleTransactionProcessor(emiCalculator, Mockito.mock(InterestRefundService.class),
|
||||
Mockito.mock(ExternalIdFactory.class), Mockito.mock(LoanScheduleComponent.class), Mockito.mock(LoanChargeValidator.class),
|
||||
Mockito.mock(LoanBalanceService.class), Mockito.mock(LoanChargeService.class));
|
||||
|
||||
ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
|
||||
|
||||
Reference in New Issue
Block a user