FINERACT-2080: separate LoanRepaymentScheduleTransactionProcessorFactory from loan
This commit is contained in:
+1
-144
@@ -107,13 +107,8 @@ import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.data.DisbursementData;
|
import org.apache.fineract.portfolio.loanaccount.data.DisbursementData;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO;
|
import org.apache.fineract.portfolio.loanaccount.data.HolidayDetailDTO;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
|
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.OutstandingAmountsDTO;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
import org.apache.fineract.portfolio.loanaccount.data.ScheduleGeneratorDTO;
|
||||||
import org.apache.fineract.portfolio.loanaccount.data.TransactionChangeData;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleDTO;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleGenerator;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleGenerator;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel;
|
||||||
@@ -365,8 +360,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
private boolean accountNumberRequiresAutoGeneration;
|
private boolean accountNumberRequiresAutoGeneration;
|
||||||
@Transient
|
|
||||||
private LoanRepaymentScheduleTransactionProcessorFactory transactionProcessorFactory;
|
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
private LoanLifecycleStateMachine loanLifecycleStateMachine;
|
private LoanLifecycleStateMachine loanLifecycleStateMachine;
|
||||||
@@ -769,37 +762,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
return applyLoanChargeTransaction;
|
return applyLoanChargeTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleChargePaidTransaction(final LoanCharge charge, final LoanTransaction chargesPayment,
|
|
||||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final Integer installmentNumber) {
|
|
||||||
chargesPayment.updateLoan(this);
|
|
||||||
final LoanChargePaidBy loanChargePaidBy = new LoanChargePaidBy(chargesPayment, charge,
|
|
||||||
chargesPayment.getAmount(getCurrency()).getAmount(), installmentNumber);
|
|
||||||
chargesPayment.getLoanChargesPaid().add(loanChargePaidBy);
|
|
||||||
addLoanTransaction(chargesPayment);
|
|
||||||
loanLifecycleStateMachine.transition(LoanEvent.LOAN_CHARGE_PAYMENT, this);
|
|
||||||
|
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = getTransactionProcessor();
|
|
||||||
final List<LoanRepaymentScheduleInstallment> chargePaymentInstallments = new ArrayList<>();
|
|
||||||
List<LoanRepaymentScheduleInstallment> installments = getRepaymentScheduleInstallments();
|
|
||||||
int firstNormalInstallmentNumber = LoanRepaymentScheduleProcessingWrapper
|
|
||||||
.fetchFirstNormalInstallmentNumber(repaymentScheduleInstallments);
|
|
||||||
for (final LoanRepaymentScheduleInstallment installment : installments) {
|
|
||||||
boolean isFirstInstallment = installment.getInstallmentNumber().equals(firstNormalInstallmentNumber);
|
|
||||||
if (installment.getInstallmentNumber().equals(installmentNumber) || (installmentNumber == null
|
|
||||||
&& charge.isDueInPeriod(installment.getFromDate(), installment.getDueDate(), isFirstInstallment))) {
|
|
||||||
chargePaymentInstallments.add(installment);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final Set<LoanCharge> loanCharges = new HashSet<>(1);
|
|
||||||
loanCharges.add(charge);
|
|
||||||
loanRepaymentScheduleTransactionProcessor.processLatestTransaction(chargesPayment, new TransactionCtx(getCurrency(),
|
|
||||||
chargePaymentInstallments, loanCharges, new MoneyHolder(getTotalOverpaidAsMoney()), null));
|
|
||||||
|
|
||||||
updateLoanSummaryDerivedFields();
|
|
||||||
doPostLoanTransactionChecks(chargesPayment.getTransactionDate(), loanLifecycleStateMachine);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LocalDate getLastRepaymentPeriodDueDate(final boolean includeRecalculatedInterestComponent) {
|
public LocalDate getLastRepaymentPeriodDueDate(final boolean includeRecalculatedInterestComponent) {
|
||||||
LocalDate lastRepaymentDate = getDisbursementDate();
|
LocalDate lastRepaymentDate = getDisbursementDate();
|
||||||
List<LoanRepaymentScheduleInstallment> installments = getRepaymentScheduleInstallments();
|
List<LoanRepaymentScheduleInstallment> installments = getRepaymentScheduleInstallments();
|
||||||
@@ -2245,10 +2207,8 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
return receivableInterest;
|
return receivableInterest;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHelpers(final LoanLifecycleStateMachine loanLifecycleStateMachine,
|
public void setHelpers(final LoanLifecycleStateMachine loanLifecycleStateMachine) {
|
||||||
final LoanRepaymentScheduleTransactionProcessorFactory transactionProcessorFactory) {
|
|
||||||
this.loanLifecycleStateMachine = loanLifecycleStateMachine;
|
this.loanLifecycleStateMachine = loanLifecycleStateMachine;
|
||||||
this.transactionProcessorFactory = transactionProcessorFactory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSyncDisbursementWithMeeting() {
|
public boolean isSyncDisbursementWithMeeting() {
|
||||||
@@ -2601,89 +2561,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
return (this.actualMaturityDate != null) ? (referenceDate.compareTo(this.actualMaturityDate) >= 0) : false;
|
return (this.actualMaturityDate != null) ? (referenceDate.compareTo(this.actualMaturityDate) >= 0) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChangedTransactionDetail processTransactions() {
|
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = getTransactionProcessor();
|
|
||||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
|
|
||||||
ChangedTransactionDetail changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(
|
|
||||||
getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(),
|
|
||||||
getActiveCharges());
|
|
||||||
for (TransactionChangeData change : changedTransactionDetail.getTransactionChanges()) {
|
|
||||||
change.getNewTransaction().updateLoan(this);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Commented since throwing exception if external id present for one of the transactions. for this need to save
|
|
||||||
* the reversed transactions first and then new transactions.
|
|
||||||
*/
|
|
||||||
final List<LoanTransaction> newTransactions = changedTransactionDetail.getTransactionChanges().stream()
|
|
||||||
.map(TransactionChangeData::getNewTransaction).toList();
|
|
||||||
this.loanTransactions.addAll(newTransactions);
|
|
||||||
updateLoanSummaryDerivedFields();
|
|
||||||
|
|
||||||
return changedTransactionDetail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Probably this is buggy when a chargeback transaction happens
|
|
||||||
*/
|
|
||||||
public Optional<ChangedTransactionDetail> processPostDisbursementTransactions() {
|
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = getTransactionProcessor();
|
|
||||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
|
|
||||||
final List<LoanTransaction> copyTransactions = new ArrayList<>();
|
|
||||||
|
|
||||||
if (allNonContraTransactionsPostDisbursement.isEmpty()) {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Probably this is not needed and can be eliminated, make sure to double check it
|
|
||||||
for (LoanTransaction loanTransaction : allNonContraTransactionsPostDisbursement) {
|
|
||||||
copyTransactions.add(LoanTransaction.copyTransactionProperties(loanTransaction));
|
|
||||||
}
|
|
||||||
final ChangedTransactionDetail changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(
|
|
||||||
getDisbursementDate(), copyTransactions, getCurrency(), getRepaymentScheduleInstallments(), getActiveCharges());
|
|
||||||
|
|
||||||
updateLoanSummaryDerivedFields();
|
|
||||||
|
|
||||||
return Optional.of(changedTransactionDetail);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LoanScheduleDTO getRecalculatedSchedule(final ScheduleGeneratorDTO generatorDTO) {
|
|
||||||
if (!isInterestBearingAndInterestRecalculationEnabled() || isNpa || isChargedOff()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
final InterestMethod interestMethod = this.loanRepaymentScheduleDetail.getInterestMethod();
|
|
||||||
final LoanScheduleGenerator loanScheduleGenerator = generatorDTO.getLoanScheduleFactory()
|
|
||||||
.create(this.loanRepaymentScheduleDetail.getLoanScheduleType(), interestMethod);
|
|
||||||
|
|
||||||
final MathContext mc = MoneyHelper.getMathContext();
|
|
||||||
|
|
||||||
final LoanApplicationTerms loanApplicationTerms = constructLoanApplicationTerms(generatorDTO);
|
|
||||||
|
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = getTransactionProcessor();
|
|
||||||
|
|
||||||
return loanScheduleGenerator.rescheduleNextInstallments(mc, loanApplicationTerms, this, generatorDTO.getHolidayDetailDTO(),
|
|
||||||
loanRepaymentScheduleTransactionProcessor, generatorDTO.getRecalculateFrom());
|
|
||||||
}
|
|
||||||
|
|
||||||
public OutstandingAmountsDTO fetchPrepaymentDetail(final ScheduleGeneratorDTO scheduleGeneratorDTO, final LocalDate onDate) {
|
|
||||||
OutstandingAmountsDTO outstandingAmounts;
|
|
||||||
|
|
||||||
if (isInterestBearingAndInterestRecalculationEnabled() && !isChargeOffOnDate(onDate)) {
|
|
||||||
final MathContext mc = MoneyHelper.getMathContext();
|
|
||||||
|
|
||||||
final InterestMethod interestMethod = this.loanRepaymentScheduleDetail.getInterestMethod();
|
|
||||||
final LoanApplicationTerms loanApplicationTerms = constructLoanApplicationTerms(scheduleGeneratorDTO);
|
|
||||||
|
|
||||||
final LoanScheduleGenerator loanScheduleGenerator = scheduleGeneratorDTO.getLoanScheduleFactory()
|
|
||||||
.create(loanApplicationTerms.getLoanScheduleType(), interestMethod);
|
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = getTransactionProcessor();
|
|
||||||
outstandingAmounts = loanScheduleGenerator.calculatePrepaymentAmount(getCurrency(), onDate, loanApplicationTerms, mc, this,
|
|
||||||
scheduleGeneratorDTO.getHolidayDetailDTO(), loanRepaymentScheduleTransactionProcessor);
|
|
||||||
} else {
|
|
||||||
outstandingAmounts = this.getTotalOutstandingOnLoan();
|
|
||||||
}
|
|
||||||
return outstandingAmounts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LoanApplicationTerms constructLoanApplicationTerms(final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
public LoanApplicationTerms constructLoanApplicationTerms(final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||||
final Integer loanTermFrequency = this.termFrequency;
|
final Integer loanTermFrequency = this.termFrequency;
|
||||||
NthDayType nthDayType = null;
|
NthDayType nthDayType = null;
|
||||||
@@ -2754,22 +2631,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
return annualNominalInterestRate;
|
return annualNominalInterestRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private OutstandingAmountsDTO getTotalOutstandingOnLoan() {
|
|
||||||
Money totalPrincipal = Money.zero(getCurrency());
|
|
||||||
Money totalInterest = Money.zero(getCurrency());
|
|
||||||
Money feeCharges = Money.zero(getCurrency());
|
|
||||||
Money penaltyCharges = Money.zero(getCurrency());
|
|
||||||
List<LoanRepaymentScheduleInstallment> repaymentSchedule = getRepaymentScheduleInstallments();
|
|
||||||
for (final LoanRepaymentScheduleInstallment scheduledRepayment : repaymentSchedule) {
|
|
||||||
totalPrincipal = totalPrincipal.plus(scheduledRepayment.getPrincipalOutstanding(getCurrency()));
|
|
||||||
totalInterest = totalInterest.plus(scheduledRepayment.getInterestOutstanding(getCurrency()));
|
|
||||||
feeCharges = feeCharges.plus(scheduledRepayment.getFeeChargesOutstanding(getCurrency()));
|
|
||||||
penaltyCharges = penaltyCharges.plus(scheduledRepayment.getPenaltyChargesOutstanding(getCurrency()));
|
|
||||||
}
|
|
||||||
return new OutstandingAmountsDTO(totalPrincipal.getCurrency()).principal(totalPrincipal).interest(totalInterest)
|
|
||||||
.feeCharges(feeCharges).penaltyCharges(penaltyCharges);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LocalDate fetchInterestRecalculateFromDate() {
|
public LocalDate fetchInterestRecalculateFromDate() {
|
||||||
LocalDate recalculatedOn;
|
LocalDate recalculatedOn;
|
||||||
if (this.interestRecalculatedOn == null) {
|
if (this.interestRecalculatedOn == null) {
|
||||||
@@ -3510,10 +3371,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
isTopup = topup;
|
isTopup = topup;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoanRepaymentScheduleTransactionProcessor getTransactionProcessor() {
|
|
||||||
return transactionProcessorFactory.determineProcessor(transactionProcessingStrategyCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isProgressiveSchedule() {
|
public boolean isProgressiveSchedule() {
|
||||||
return getLoanProductRelatedDetail().getLoanScheduleType() == PROGRESSIVE;
|
return getLoanProductRelatedDetail().getLoanScheduleType() == PROGRESSIVE;
|
||||||
}
|
}
|
||||||
|
|||||||
+41
-1
@@ -19,19 +19,28 @@
|
|||||||
package org.apache.fineract.portfolio.loanaccount.service;
|
package org.apache.fineract.portfolio.loanaccount.service;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanChargePaidBy;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanEvent;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleProcessingWrapper;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
||||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class LoanChargeService {
|
public class LoanChargeService {
|
||||||
|
|
||||||
private final LoanChargeValidator loanChargeValidator;
|
private final LoanChargeValidator loanChargeValidator;
|
||||||
|
private final LoanTransactionProcessingService loanTransactionProcessingService;
|
||||||
|
|
||||||
public void recalculateAllCharges(final Loan loan) {
|
public void recalculateAllCharges(final Loan loan) {
|
||||||
Set<LoanCharge> charges = loan.getActiveCharges();
|
Set<LoanCharge> charges = loan.getActiveCharges();
|
||||||
@@ -79,6 +88,37 @@ public class LoanChargeService {
|
|||||||
charge = loanCharge;
|
charge = loanCharge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loan.handleChargePaidTransaction(charge, paymentTransaction, loanLifecycleStateMachine, installmentNumber);
|
handleChargePaidTransaction(loan, charge, paymentTransaction, loanLifecycleStateMachine, installmentNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleChargePaidTransaction(final Loan loan, final LoanCharge charge, final LoanTransaction chargesPayment,
|
||||||
|
final LoanLifecycleStateMachine loanLifecycleStateMachine, final Integer installmentNumber) {
|
||||||
|
chargesPayment.updateLoan(loan);
|
||||||
|
final LoanChargePaidBy loanChargePaidBy = new LoanChargePaidBy(chargesPayment, charge,
|
||||||
|
chargesPayment.getAmount(loan.getCurrency()).getAmount(), installmentNumber);
|
||||||
|
chargesPayment.getLoanChargesPaid().add(loanChargePaidBy);
|
||||||
|
loan.addLoanTransaction(chargesPayment);
|
||||||
|
loanLifecycleStateMachine.transition(LoanEvent.LOAN_CHARGE_PAYMENT, loan);
|
||||||
|
|
||||||
|
final List<LoanRepaymentScheduleInstallment> chargePaymentInstallments = new ArrayList<>();
|
||||||
|
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
|
||||||
|
int firstNormalInstallmentNumber = LoanRepaymentScheduleProcessingWrapper
|
||||||
|
.fetchFirstNormalInstallmentNumber(loan.getRepaymentScheduleInstallments());
|
||||||
|
for (final LoanRepaymentScheduleInstallment installment : installments) {
|
||||||
|
boolean isFirstInstallment = installment.getInstallmentNumber().equals(firstNormalInstallmentNumber);
|
||||||
|
if (installment.getInstallmentNumber().equals(installmentNumber) || (installmentNumber == null
|
||||||
|
&& charge.isDueInPeriod(installment.getFromDate(), installment.getDueDate(), isFirstInstallment))) {
|
||||||
|
chargePaymentInstallments.add(installment);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final Set<LoanCharge> loanCharges = new HashSet<>(1);
|
||||||
|
loanCharges.add(charge);
|
||||||
|
loanTransactionProcessingService.processLatestTransaction(loan.getTransactionProcessingStrategyCode(), chargesPayment,
|
||||||
|
new TransactionCtx(loan.getCurrency(), chargePaymentInstallments, loanCharges,
|
||||||
|
new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
||||||
|
|
||||||
|
loan.updateLoanSummaryDerivedFields();
|
||||||
|
loan.doPostLoanTransactionChecks(chargesPayment.getTransactionDate(), loanLifecycleStateMachine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-4
@@ -42,7 +42,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachin
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
||||||
import org.apache.fineract.portfolio.loanaccount.exception.InvalidLoanStateTransitionException;
|
import org.apache.fineract.portfolio.loanaccount.exception.InvalidLoanStateTransitionException;
|
||||||
@@ -61,6 +60,7 @@ public class LoanDownPaymentHandlerServiceImpl implements LoanDownPaymentHandler
|
|||||||
private final LoanRefundService loanRefundService;
|
private final LoanRefundService loanRefundService;
|
||||||
private final LoanRefundValidator loanRefundValidator;
|
private final LoanRefundValidator loanRefundValidator;
|
||||||
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||||
|
private final LoanTransactionProcessingService loanTransactionProcessingService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LoanTransaction handleDownPayment(ScheduleGeneratorDTO scheduleGeneratorDTO, JsonCommand command,
|
public LoanTransaction handleDownPayment(ScheduleGeneratorDTO scheduleGeneratorDTO, JsonCommand command,
|
||||||
@@ -124,8 +124,6 @@ public class LoanDownPaymentHandlerServiceImpl implements LoanDownPaymentHandler
|
|||||||
|
|
||||||
loanRefundValidator.validateTransactionAmountThreshold(loan, adjustedTransaction);
|
loanRefundValidator.validateTransactionAmountThreshold(loan, adjustedTransaction);
|
||||||
|
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loan.getTransactionProcessor();
|
|
||||||
|
|
||||||
final LoanRepaymentScheduleInstallment currentInstallment = loan
|
final LoanRepaymentScheduleInstallment currentInstallment = loan
|
||||||
.fetchLoanRepaymentScheduleInstallmentByDueDate(loanTransaction.getTransactionDate());
|
.fetchLoanRepaymentScheduleInstallmentByDueDate(loanTransaction.getTransactionDate());
|
||||||
|
|
||||||
@@ -135,7 +133,7 @@ public class LoanDownPaymentHandlerServiceImpl implements LoanDownPaymentHandler
|
|||||||
|
|
||||||
if (isTransactionChronologicallyLatest && adjustedTransaction == null
|
if (isTransactionChronologicallyLatest && adjustedTransaction == null
|
||||||
&& (!reprocess || !loan.isInterestBearingAndInterestRecalculationEnabled()) && !loan.isForeclosure()) {
|
&& (!reprocess || !loan.isInterestBearingAndInterestRecalculationEnabled()) && !loan.isForeclosure()) {
|
||||||
loanRepaymentScheduleTransactionProcessor.processLatestTransaction(loanTransaction,
|
loanTransactionProcessingService.processLatestTransaction(loan.getTransactionProcessingStrategyCode(), loanTransaction,
|
||||||
new TransactionCtx(loan.getCurrency(), loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(),
|
new TransactionCtx(loan.getCurrency(), loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(),
|
||||||
new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
||||||
reprocess = false;
|
reprocess = false;
|
||||||
|
|||||||
+4
-5
@@ -26,7 +26,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanEvent;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanEvent;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
||||||
import org.apache.fineract.portfolio.loanaccount.serialization.LoanRefundValidator;
|
import org.apache.fineract.portfolio.loanaccount.serialization.LoanRefundValidator;
|
||||||
@@ -35,6 +34,7 @@ import org.apache.fineract.portfolio.loanaccount.serialization.LoanRefundValidat
|
|||||||
public class LoanRefundService {
|
public class LoanRefundService {
|
||||||
|
|
||||||
private final LoanRefundValidator loanRefundValidator;
|
private final LoanRefundValidator loanRefundValidator;
|
||||||
|
private final LoanTransactionProcessingService loadTransactionProcessingService;
|
||||||
|
|
||||||
public void makeRefund(final Loan loan, final LoanTransaction loanTransaction,
|
public void makeRefund(final Loan loan, final LoanTransaction loanTransaction,
|
||||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final List<Long> existingTransactionIds,
|
final LoanLifecycleStateMachine loanLifecycleStateMachine, final List<Long> existingTransactionIds,
|
||||||
@@ -106,10 +106,9 @@ public class LoanRefundService {
|
|||||||
loanRefundValidator.validateTransactionDateNotInFuture(loanTransactionDate);
|
loanRefundValidator.validateTransactionDateNotInFuture(loanTransactionDate);
|
||||||
loanRefundValidator.validateTransactionAmountThreshold(loan, null);
|
loanRefundValidator.validateTransactionAmountThreshold(loan, null);
|
||||||
|
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loan.getTransactionProcessor();
|
loadTransactionProcessingService.processLatestTransaction(loan.getTransactionProcessingStrategyCode(), loanTransaction,
|
||||||
|
new TransactionCtx(loan.getCurrency(), loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(),
|
||||||
loanRepaymentScheduleTransactionProcessor.processLatestTransaction(loanTransaction, new TransactionCtx(loan.getCurrency(),
|
new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
||||||
loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(), new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
|
||||||
|
|
||||||
loan.updateLoanSummaryDerivedFields();
|
loan.updateLoanSummaryDerivedFields();
|
||||||
loan.doPostLoanTransactionChecks(loanTransaction.getTransactionDate(), loanLifecycleStateMachine);
|
loan.doPostLoanTransactionChecks(loanTransaction.getTransactionDate(), loanLifecycleStateMachine);
|
||||||
|
|||||||
+3
-2
@@ -35,6 +35,7 @@ public class LoanScheduleService {
|
|||||||
|
|
||||||
private final LoanChargeService loanChargeService;
|
private final LoanChargeService loanChargeService;
|
||||||
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
private final ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||||
|
private final LoanTransactionProcessingService loadTransactionProcessingService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ability to regenerate the repayment schedule based on the loans current details/state.
|
* Ability to regenerate the repayment schedule based on the loans current details/state.
|
||||||
@@ -79,7 +80,7 @@ public class LoanScheduleService {
|
|||||||
|
|
||||||
public void regenerateRepaymentScheduleWithInterestRecalculation(final Loan loan, final ScheduleGeneratorDTO generatorDTO) {
|
public void regenerateRepaymentScheduleWithInterestRecalculation(final Loan loan, final ScheduleGeneratorDTO generatorDTO) {
|
||||||
final LocalDate lastTransactionDate = loan.getLastUserTransactionDate();
|
final LocalDate lastTransactionDate = loan.getLastUserTransactionDate();
|
||||||
final LoanScheduleDTO loanSchedule = loan.getRecalculatedSchedule(generatorDTO);
|
final LoanScheduleDTO loanSchedule = loadTransactionProcessingService.getRecalculatedSchedule(generatorDTO, loan);
|
||||||
if (loanSchedule == null) {
|
if (loanSchedule == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -107,7 +108,7 @@ public class LoanScheduleService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loan.processPostDisbursementTransactions();
|
loadTransactionProcessingService.processPostDisbursementTransactions(loan);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleRegenerateRepaymentScheduleWithInterestRecalculation(final Loan loan, final ScheduleGeneratorDTO generatorDTO) {
|
public void handleRegenerateRepaymentScheduleWithInterestRecalculation(final Loan loan, final ScheduleGeneratorDTO generatorDTO) {
|
||||||
|
|||||||
+151
@@ -0,0 +1,151 @@
|
|||||||
|
/**
|
||||||
|
* 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.service;
|
||||||
|
|
||||||
|
import java.math.MathContext;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||||
|
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||||
|
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.data.OutstandingAmountsDTO;
|
||||||
|
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.LoanRepaymentScheduleInstallment;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleDTO;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleGenerator;
|
||||||
|
import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class LoanTransactionProcessingService {
|
||||||
|
|
||||||
|
private final LoanRepaymentScheduleTransactionProcessorFactory transactionProcessorFactory;
|
||||||
|
|
||||||
|
public ChangedTransactionDetail processLatestTransaction(String transactionProcessingStrategyCode, LoanTransaction loanTransaction,
|
||||||
|
TransactionCtx ctx) {
|
||||||
|
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = getTransactionProcessor(
|
||||||
|
transactionProcessingStrategyCode);
|
||||||
|
return loanRepaymentScheduleTransactionProcessor.processLatestTransaction(loanTransaction, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChangedTransactionDetail reprocessLoanTransactions(String transactionProcessingStrategyCode, LocalDate disbursementDate,
|
||||||
|
List<LoanTransaction> repaymentsOrWaivers, MonetaryCurrency currency,
|
||||||
|
List<LoanRepaymentScheduleInstallment> repaymentScheduleInstallments, Set<LoanCharge> charges) {
|
||||||
|
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = getTransactionProcessor(
|
||||||
|
transactionProcessingStrategyCode);
|
||||||
|
return loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(disbursementDate, repaymentsOrWaivers, currency,
|
||||||
|
repaymentScheduleInstallments, charges);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoanRepaymentScheduleTransactionProcessor getTransactionProcessor(String transactionProcessingStrategyCode) {
|
||||||
|
return transactionProcessorFactory.determineProcessor(transactionProcessingStrategyCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<ChangedTransactionDetail> processPostDisbursementTransactions(Loan loan) {
|
||||||
|
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = getTransactionProcessor(
|
||||||
|
loan.getTransactionProcessingStrategyCode());
|
||||||
|
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = loan.retrieveListOfTransactionsForReprocessing();
|
||||||
|
final List<LoanTransaction> copyTransactions = new ArrayList<>();
|
||||||
|
|
||||||
|
if (allNonContraTransactionsPostDisbursement.isEmpty()) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Probably this is not needed and can be eliminated, make sure to double check it
|
||||||
|
for (LoanTransaction loanTransaction : allNonContraTransactionsPostDisbursement) {
|
||||||
|
copyTransactions.add(LoanTransaction.copyTransactionProperties(loanTransaction));
|
||||||
|
}
|
||||||
|
final ChangedTransactionDetail changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(
|
||||||
|
loan.getDisbursementDate(), copyTransactions, loan.getCurrency(), loan.getRepaymentScheduleInstallments(),
|
||||||
|
loan.getActiveCharges());
|
||||||
|
|
||||||
|
loan.updateLoanSummaryDerivedFields();
|
||||||
|
|
||||||
|
return Optional.of(changedTransactionDetail);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LoanScheduleDTO getRecalculatedSchedule(final ScheduleGeneratorDTO generatorDTO, Loan loan) {
|
||||||
|
if (!loan.isInterestBearingAndInterestRecalculationEnabled() || loan.isNpa() || loan.isChargedOff()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final InterestMethod interestMethod = loan.getLoanRepaymentScheduleDetail().getInterestMethod();
|
||||||
|
final LoanScheduleGenerator loanScheduleGenerator = generatorDTO.getLoanScheduleFactory()
|
||||||
|
.create(loan.getLoanRepaymentScheduleDetail().getLoanScheduleType(), interestMethod);
|
||||||
|
|
||||||
|
final MathContext mc = MoneyHelper.getMathContext();
|
||||||
|
|
||||||
|
final LoanApplicationTerms loanApplicationTerms = loan.constructLoanApplicationTerms(generatorDTO);
|
||||||
|
|
||||||
|
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = getTransactionProcessor(
|
||||||
|
loan.getTransactionProcessingStrategyCode());
|
||||||
|
|
||||||
|
return loanScheduleGenerator.rescheduleNextInstallments(mc, loanApplicationTerms, loan, generatorDTO.getHolidayDetailDTO(),
|
||||||
|
loanRepaymentScheduleTransactionProcessor, generatorDTO.getRecalculateFrom());
|
||||||
|
}
|
||||||
|
|
||||||
|
public OutstandingAmountsDTO fetchPrepaymentDetail(final ScheduleGeneratorDTO scheduleGeneratorDTO, final LocalDate onDate, Loan loan) {
|
||||||
|
OutstandingAmountsDTO outstandingAmounts;
|
||||||
|
|
||||||
|
if (loan.isInterestBearingAndInterestRecalculationEnabled() && !loan.isChargeOffOnDate(onDate)) {
|
||||||
|
final MathContext mc = MoneyHelper.getMathContext();
|
||||||
|
|
||||||
|
final InterestMethod interestMethod = loan.getLoanRepaymentScheduleDetail().getInterestMethod();
|
||||||
|
final LoanApplicationTerms loanApplicationTerms = loan.constructLoanApplicationTerms(scheduleGeneratorDTO);
|
||||||
|
|
||||||
|
final LoanScheduleGenerator loanScheduleGenerator = scheduleGeneratorDTO.getLoanScheduleFactory()
|
||||||
|
.create(loanApplicationTerms.getLoanScheduleType(), interestMethod);
|
||||||
|
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = getTransactionProcessor(
|
||||||
|
loan.getTransactionProcessingStrategyCode());
|
||||||
|
outstandingAmounts = loanScheduleGenerator.calculatePrepaymentAmount(loan.getCurrency(), onDate, loanApplicationTerms, mc, loan,
|
||||||
|
scheduleGeneratorDTO.getHolidayDetailDTO(), loanRepaymentScheduleTransactionProcessor);
|
||||||
|
} else {
|
||||||
|
outstandingAmounts = getTotalOutstandingOnLoan(loan);
|
||||||
|
}
|
||||||
|
return outstandingAmounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
private OutstandingAmountsDTO getTotalOutstandingOnLoan(Loan loan) {
|
||||||
|
Money totalPrincipal = Money.zero(loan.getCurrency());
|
||||||
|
Money totalInterest = Money.zero(loan.getCurrency());
|
||||||
|
Money feeCharges = Money.zero(loan.getCurrency());
|
||||||
|
Money penaltyCharges = Money.zero(loan.getCurrency());
|
||||||
|
List<LoanRepaymentScheduleInstallment> repaymentSchedule = loan.getRepaymentScheduleInstallments();
|
||||||
|
for (final LoanRepaymentScheduleInstallment scheduledRepayment : repaymentSchedule) {
|
||||||
|
totalPrincipal = totalPrincipal.plus(scheduledRepayment.getPrincipalOutstanding(loan.getCurrency()));
|
||||||
|
totalInterest = totalInterest.plus(scheduledRepayment.getInterestOutstanding(loan.getCurrency()));
|
||||||
|
feeCharges = feeCharges.plus(scheduledRepayment.getFeeChargesOutstanding(loan.getCurrency()));
|
||||||
|
penaltyCharges = penaltyCharges.plus(scheduledRepayment.getPenaltyChargesOutstanding(loan.getCurrency()));
|
||||||
|
}
|
||||||
|
return new OutstandingAmountsDTO(totalPrincipal.getCurrency()).principal(totalPrincipal).interest(totalInterest)
|
||||||
|
.feeCharges(feeCharges).penaltyCharges(penaltyCharges);
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
-7
@@ -29,7 +29,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountService;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleProcessingWrapper;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleProcessingWrapper;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -41,6 +40,7 @@ public class ReprocessLoanTransactionsServiceImpl implements ReprocessLoanTransa
|
|||||||
private final LoanAccountService loanAccountService;
|
private final LoanAccountService loanAccountService;
|
||||||
private final LoanAccountTransfersService loanAccountTransfersService;
|
private final LoanAccountTransfersService loanAccountTransfersService;
|
||||||
private final ReplayedTransactionBusinessEventService replayedTransactionBusinessEventService;
|
private final ReplayedTransactionBusinessEventService replayedTransactionBusinessEventService;
|
||||||
|
private final LoanTransactionProcessingService loadTransactionProcessingService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reprocessTransactions(final Loan loan) {
|
public void reprocessTransactions(final Loan loan) {
|
||||||
@@ -65,7 +65,7 @@ public class ReprocessLoanTransactionsServiceImpl implements ReprocessLoanTransa
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPostDisbursementTransactions(final Loan loan) {
|
public void processPostDisbursementTransactions(final Loan loan) {
|
||||||
loan.processPostDisbursementTransactions().ifPresent(this::handleChangedDetail);
|
loadTransactionProcessingService.processPostDisbursementTransactions(loan).ifPresent(this::handleChangedDetail);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -98,7 +98,8 @@ public class ReprocessLoanTransactionsServiceImpl implements ReprocessLoanTransa
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processLatestTransaction(final LoanTransaction loanTransaction, final Loan loan) {
|
public void processLatestTransaction(final LoanTransaction loanTransaction, final Loan loan) {
|
||||||
final ChangedTransactionDetail changedTransactionDetail = loan.getTransactionProcessor().processLatestTransaction(loanTransaction,
|
final ChangedTransactionDetail changedTransactionDetail = loadTransactionProcessingService.processLatestTransaction(
|
||||||
|
loan.getTransactionProcessingStrategyCode(), loanTransaction,
|
||||||
new TransactionCtx(loan.getCurrency(), loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(),
|
new TransactionCtx(loan.getCurrency(), loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(),
|
||||||
new MoneyHolder(loan.getTotalOverpaidAsMoney()), new ChangedTransactionDetail()));
|
new MoneyHolder(loan.getTotalOverpaidAsMoney()), new ChangedTransactionDetail()));
|
||||||
final List<LoanTransaction> newTransactions = changedTransactionDetail.getTransactionChanges().stream()
|
final List<LoanTransaction> newTransactions = changedTransactionDetail.getTransactionChanges().stream()
|
||||||
@@ -125,10 +126,9 @@ public class ReprocessLoanTransactionsServiceImpl implements ReprocessLoanTransa
|
|||||||
|
|
||||||
private ChangedTransactionDetail reprocessTransactionsAndFetchChangedTransactions(final Loan loan,
|
private ChangedTransactionDetail reprocessTransactionsAndFetchChangedTransactions(final Loan loan,
|
||||||
final List<LoanTransaction> loanTransactions) {
|
final List<LoanTransaction> loanTransactions) {
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loan.getTransactionProcessor();
|
final ChangedTransactionDetail changedTransactionDetail = loadTransactionProcessingService.reprocessLoanTransactions(
|
||||||
final ChangedTransactionDetail changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(
|
loan.getTransactionProcessingStrategyCode(), loan.getDisbursementDate(), loanTransactions, loan.getCurrency(),
|
||||||
loan.getDisbursementDate(), loanTransactions, loan.getCurrency(), loan.getRepaymentScheduleInstallments(),
|
loan.getRepaymentScheduleInstallments(), loan.getActiveCharges());
|
||||||
loan.getActiveCharges());
|
|
||||||
for (TransactionChangeData change : changedTransactionDetail.getTransactionChanges()) {
|
for (TransactionChangeData change : changedTransactionDetail.getTransactionChanges()) {
|
||||||
change.getNewTransaction().updateLoan(loan);
|
change.getNewTransaction().updateLoan(loan);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
@@ -32,7 +32,10 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleP
|
|||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePlanRepaymentPeriod;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePlanRepaymentPeriod;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
class EmbeddableProgressiveLoanScheduleGeneratorTest {
|
class EmbeddableProgressiveLoanScheduleGeneratorTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
+16
-3
@@ -30,7 +30,6 @@ import java.util.Comparator;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||||
@@ -49,19 +48,32 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleM
|
|||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleParams;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleParams;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePlan;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePlan;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.exception.MultiDisbursementOutstandingAmoutException;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.exception.MultiDisbursementOutstandingAmoutException;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.service.LoanTransactionProcessingService;
|
||||||
import org.apache.fineract.portfolio.loanproduct.calc.EMICalculator;
|
import org.apache.fineract.portfolio.loanproduct.calc.EMICalculator;
|
||||||
import org.apache.fineract.portfolio.loanproduct.calc.data.OutstandingDetails;
|
import org.apache.fineract.portfolio.loanproduct.calc.data.OutstandingDetails;
|
||||||
import org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
|
import org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
|
||||||
import org.apache.fineract.portfolio.loanproduct.domain.RepaymentStartDateType;
|
import org.apache.fineract.portfolio.loanproduct.domain.RepaymentStartDateType;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
|
public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
|
||||||
|
|
||||||
private final ScheduledDateGenerator scheduledDateGenerator;
|
private final ScheduledDateGenerator scheduledDateGenerator;
|
||||||
private final EMICalculator emiCalculator;
|
private final EMICalculator emiCalculator;
|
||||||
|
|
||||||
|
private LoanTransactionProcessingService loanTransactionProcessingService;
|
||||||
|
|
||||||
|
public ProgressiveLoanScheduleGenerator(ScheduledDateGenerator scheduledDateGenerator, EMICalculator emiCalculator) {
|
||||||
|
this.scheduledDateGenerator = scheduledDateGenerator;
|
||||||
|
this.emiCalculator = emiCalculator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
public void setLoanTransactionProcessingService(LoanTransactionProcessingService loanTransactionProcessingService) {
|
||||||
|
this.loanTransactionProcessingService = loanTransactionProcessingService;
|
||||||
|
}
|
||||||
|
|
||||||
public LoanSchedulePlan generate(final MathContext mc, final LoanRepaymentScheduleModelData modelData) {
|
public LoanSchedulePlan generate(final MathContext mc, final LoanRepaymentScheduleModelData modelData) {
|
||||||
LoanApplicationTerms loanApplicationTerms = LoanApplicationTerms.assembleFrom(modelData, mc);
|
LoanApplicationTerms loanApplicationTerms = LoanApplicationTerms.assembleFrom(modelData, mc);
|
||||||
return LoanSchedulePlan.from(generate(mc, loanApplicationTerms, null, null));
|
return LoanSchedulePlan.from(generate(mc, loanApplicationTerms, null, null));
|
||||||
@@ -208,7 +220,8 @@ public class ProgressiveLoanScheduleGenerator implements LoanScheduleGenerator {
|
|||||||
@Override
|
@Override
|
||||||
public Money getPeriodInterestTillDate(@NotNull LoanRepaymentScheduleInstallment installment, @NotNull LocalDate targetDate) {
|
public Money getPeriodInterestTillDate(@NotNull LoanRepaymentScheduleInstallment installment, @NotNull LocalDate targetDate) {
|
||||||
Loan loan = installment.getLoan();
|
Loan loan = installment.getLoan();
|
||||||
LoanRepaymentScheduleTransactionProcessor transactionProcessor = loan.getTransactionProcessor();
|
LoanRepaymentScheduleTransactionProcessor transactionProcessor = loanTransactionProcessingService
|
||||||
|
.getTransactionProcessor(loan.getTransactionProcessingStrategyCode());
|
||||||
if (!(transactionProcessor instanceof AdvancedPaymentScheduleTransactionProcessor processor)) {
|
if (!(transactionProcessor instanceof AdvancedPaymentScheduleTransactionProcessor processor)) {
|
||||||
throw new IllegalStateException("Expected an AdvancedPaymentScheduleTransactionProcessor");
|
throw new IllegalStateException("Expected an AdvancedPaymentScheduleTransactionProcessor");
|
||||||
}
|
}
|
||||||
|
|||||||
+8
@@ -19,6 +19,7 @@
|
|||||||
package org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
|
package org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.MathContext;
|
import java.math.MathContext;
|
||||||
@@ -32,9 +33,13 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleP
|
|||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePlanDisbursementPeriod;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePlanDisbursementPeriod;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePlanDownPaymentPeriod;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePlanDownPaymentPeriod;
|
||||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePlanRepaymentPeriod;
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePlanRepaymentPeriod;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.service.LoanTransactionProcessingService;
|
||||||
import org.apache.fineract.portfolio.loanproduct.calc.ProgressiveEMICalculator;
|
import org.apache.fineract.portfolio.loanproduct.calc.ProgressiveEMICalculator;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
class LoanScheduleGeneratorTest {
|
class LoanScheduleGeneratorTest {
|
||||||
|
|
||||||
private static final ProgressiveEMICalculator emiCalculator = new ProgressiveEMICalculator();
|
private static final ProgressiveEMICalculator emiCalculator = new ProgressiveEMICalculator();
|
||||||
@@ -49,6 +54,7 @@ class LoanScheduleGeneratorTest {
|
|||||||
private static final LocalDate DISBURSEMENT_DATE = LocalDate.of(2024, 1, 15);
|
private static final LocalDate DISBURSEMENT_DATE = LocalDate.of(2024, 1, 15);
|
||||||
private static final MathContext mc = new MathContext(12, RoundingMode.HALF_EVEN);
|
private static final MathContext mc = new MathContext(12, RoundingMode.HALF_EVEN);
|
||||||
private static final BigDecimal DOWN_PAYMENT_PORTION = BigDecimal.valueOf(25);
|
private static final BigDecimal DOWN_PAYMENT_PORTION = BigDecimal.valueOf(25);
|
||||||
|
private static final LoanTransactionProcessingService loanTransactionProcessingService = mock(LoanTransactionProcessingService.class);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGenerateLoanSchedule() {
|
void testGenerateLoanSchedule() {
|
||||||
@@ -58,6 +64,7 @@ class LoanScheduleGeneratorTest {
|
|||||||
|
|
||||||
ScheduledDateGenerator scheduledDateGenerator = new DefaultScheduledDateGenerator();
|
ScheduledDateGenerator scheduledDateGenerator = new DefaultScheduledDateGenerator();
|
||||||
ProgressiveLoanScheduleGenerator generator = new ProgressiveLoanScheduleGenerator(scheduledDateGenerator, emiCalculator);
|
ProgressiveLoanScheduleGenerator generator = new ProgressiveLoanScheduleGenerator(scheduledDateGenerator, emiCalculator);
|
||||||
|
generator.setLoanTransactionProcessingService(loanTransactionProcessingService);
|
||||||
|
|
||||||
LoanSchedulePlan loanSchedule = generator.generate(mc, modelData);
|
LoanSchedulePlan loanSchedule = generator.generate(mc, modelData);
|
||||||
|
|
||||||
@@ -94,6 +101,7 @@ class LoanScheduleGeneratorTest {
|
|||||||
|
|
||||||
ScheduledDateGenerator scheduledDateGenerator = new DefaultScheduledDateGenerator();
|
ScheduledDateGenerator scheduledDateGenerator = new DefaultScheduledDateGenerator();
|
||||||
ProgressiveLoanScheduleGenerator generator = new ProgressiveLoanScheduleGenerator(scheduledDateGenerator, emiCalculator);
|
ProgressiveLoanScheduleGenerator generator = new ProgressiveLoanScheduleGenerator(scheduledDateGenerator, emiCalculator);
|
||||||
|
generator.setLoanTransactionProcessingService(loanTransactionProcessingService);
|
||||||
|
|
||||||
LoanSchedulePlan loanSchedule = generator.generate(mc, modelData);
|
LoanSchedulePlan loanSchedule = generator.generate(mc, modelData);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -209,7 +209,7 @@ public class LoanScheduleCalculationPlatformServiceImpl implements LoanScheduleC
|
|||||||
|
|
||||||
private Loan fetchLoan(final Long accountId) {
|
private Loan fetchLoan(final Long accountId) {
|
||||||
final Loan loanAccount = this.loanRepository.findOneWithNotFoundDetection(accountId, true);
|
final Loan loanAccount = this.loanRepository.findOneWithNotFoundDetection(accountId, true);
|
||||||
loanAccount.setHelpers(defaultLoanLifecycleStateMachine, this.loanRepaymentScheduleTransactionProcessorFactory);
|
loanAccount.setHelpers(defaultLoanLifecycleStateMachine);
|
||||||
|
|
||||||
return loanAccount;
|
return loanAccount;
|
||||||
}
|
}
|
||||||
|
|||||||
-1
@@ -129,7 +129,6 @@ public class LoanReschedulePreviewPlatformServiceImpl implements LoanRescheduleP
|
|||||||
.determineProcessor(loan.transactionProcessingStrategy());
|
.determineProcessor(loan.transactionProcessingStrategy());
|
||||||
final LoanScheduleGenerator loanScheduleGenerator = this.loanScheduleFactory.create(loanApplicationTerms.getLoanScheduleType(),
|
final LoanScheduleGenerator loanScheduleGenerator = this.loanScheduleFactory.create(loanApplicationTerms.getLoanScheduleType(),
|
||||||
loanApplicationTerms.getInterestMethod());
|
loanApplicationTerms.getInterestMethod());
|
||||||
loan.setHelpers(null, this.loanRepaymentScheduleTransactionProcessorFactory);
|
|
||||||
final LoanScheduleDTO loanSchedule = loanScheduleGenerator.rescheduleNextInstallments(mathContext, loanApplicationTerms, loan,
|
final LoanScheduleDTO loanSchedule = loanScheduleGenerator.rescheduleNextInstallments(mathContext, loanApplicationTerms, loan,
|
||||||
loanApplicationTerms.getHolidayDetailDTO(), loanRepaymentScheduleTransactionProcessor, rescheduleFromDate);
|
loanApplicationTerms.getHolidayDetailDTO(), loanRepaymentScheduleTransactionProcessor, rescheduleFromDate);
|
||||||
final LoanScheduleModel loanScheduleModel = loanSchedule.getLoanScheduleModel();
|
final LoanScheduleModel loanScheduleModel = loanSchedule.getLoanScheduleModel();
|
||||||
|
|||||||
+1
-1
@@ -422,7 +422,7 @@ public class LoanRescheduleRequestWritePlatformServiceImpl implements LoanResche
|
|||||||
final LoanScheduleGenerator loanScheduleGenerator = this.loanScheduleFactory.create(loanApplicationTerms.getLoanScheduleType(),
|
final LoanScheduleGenerator loanScheduleGenerator = this.loanScheduleFactory.create(loanApplicationTerms.getLoanScheduleType(),
|
||||||
loanApplicationTerms.getInterestMethod());
|
loanApplicationTerms.getInterestMethod());
|
||||||
final LoanLifecycleStateMachine loanLifecycleStateMachine = null;
|
final LoanLifecycleStateMachine loanLifecycleStateMachine = null;
|
||||||
loan.setHelpers(loanLifecycleStateMachine, this.loanRepaymentScheduleTransactionProcessorFactory);
|
loan.setHelpers(loanLifecycleStateMachine);
|
||||||
final LoanScheduleDTO loanSchedule = loanScheduleGenerator.rescheduleNextInstallments(mathContext, loanApplicationTerms, loan,
|
final LoanScheduleDTO loanSchedule = loanScheduleGenerator.rescheduleNextInstallments(mathContext, loanApplicationTerms, loan,
|
||||||
loanApplicationTerms.getHolidayDetailDTO(), loanRepaymentScheduleTransactionProcessor, rescheduleFromDate);
|
loanApplicationTerms.getHolidayDetailDTO(), loanRepaymentScheduleTransactionProcessor, rescheduleFromDate);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -2022,7 +2022,7 @@ public final class LoanApplicationValidator {
|
|||||||
baseDataValidator.reset().parameter(LoanApiConstants.noteParameterName).value(note).notExceedingLengthOf(1000);
|
baseDataValidator.reset().parameter(LoanApiConstants.noteParameterName).value(note).notExceedingLengthOf(1000);
|
||||||
|
|
||||||
final Loan loan = this.loanRepositoryWrapper.findOneWithNotFoundDetection(loanId, true);
|
final Loan loan = this.loanRepositoryWrapper.findOneWithNotFoundDetection(loanId, true);
|
||||||
loan.setHelpers(defaultLoanLifecycleStateMachine, this.loanRepaymentScheduleTransactionProcessorFactory);
|
loan.setHelpers(defaultLoanLifecycleStateMachine);
|
||||||
|
|
||||||
final Client client = loan.client();
|
final Client client = loan.client();
|
||||||
if (client != null && client.isNotActive()) {
|
if (client != null && client.isNotActive()) {
|
||||||
|
|||||||
-8
@@ -71,7 +71,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanInstallmentCharge;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalcualtionAdditionalDetails;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalcualtionAdditionalDetails;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalculationDetails;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalculationDetails;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionComparator;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionComparator;
|
||||||
@@ -106,7 +105,6 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
|||||||
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
private final JournalEntryWritePlatformService journalEntryWritePlatformService;
|
||||||
private final LoanTransactionRepository loanTransactionRepository;
|
private final LoanTransactionRepository loanTransactionRepository;
|
||||||
private final LoanScheduleGeneratorFactory loanScheduleFactory;
|
private final LoanScheduleGeneratorFactory loanScheduleFactory;
|
||||||
private final LoanRepaymentScheduleTransactionProcessorFactory transactionProcessorFactory;
|
|
||||||
|
|
||||||
@Qualifier(TaskExecutorConstant.CONFIGURABLE_TASK_EXECUTOR_BEAN_NAME)
|
@Qualifier(TaskExecutorConstant.CONFIGURABLE_TASK_EXECUTOR_BEAN_NAME)
|
||||||
private final ThreadPoolTaskExecutor taskExecutor;
|
private final ThreadPoolTaskExecutor taskExecutor;
|
||||||
@@ -123,7 +121,6 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
|||||||
List<Throwable> errors = new ArrayList<>();
|
List<Throwable> errors = new ArrayList<>();
|
||||||
for (Loan loan : loans) {
|
for (Loan loan : loans) {
|
||||||
try {
|
try {
|
||||||
setSetHelpers(loan);
|
|
||||||
addPeriodicAccruals(tillDate, loan);
|
addPeriodicAccruals(tillDate, loan);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Failed to add accrual for loan {}", loan.getId(), e);
|
log.error("Failed to add accrual for loan {}", loan.getId(), e);
|
||||||
@@ -166,7 +163,6 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
|||||||
ThreadLocalContextUtil.init(context);
|
ThreadLocalContextUtil.init(context);
|
||||||
transactionTemplate.executeWithoutResult(status -> {
|
transactionTemplate.executeWithoutResult(status -> {
|
||||||
Loan loan = loanRepositoryWrapper.findOneWithNotFoundDetection(outerLoan.getId());
|
Loan loan = loanRepositoryWrapper.findOneWithNotFoundDetection(outerLoan.getId());
|
||||||
setSetHelpers(loan);
|
|
||||||
try {
|
try {
|
||||||
log.debug("Adding accruals for loan '{}'", loan.getId());
|
log.debug("Adding accruals for loan '{}'", loan.getId());
|
||||||
addAccruals(loan, tillDate, false, false, true);
|
addAccruals(loan, tillDate, false, false, true);
|
||||||
@@ -1293,8 +1289,4 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
|||||||
public boolean isProgressiveAccrual(@NotNull Loan loan) {
|
public boolean isProgressiveAccrual(@NotNull Loan loan) {
|
||||||
return loan.isProgressiveSchedule();
|
return loan.isProgressiveSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setSetHelpers(Loan loan) {
|
|
||||||
loan.setHelpers(null, transactionProcessorFactory);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -765,7 +765,7 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
|
|||||||
|
|
||||||
private Loan retrieveLoanBy(final Long loanId) {
|
private Loan retrieveLoanBy(final Long loanId) {
|
||||||
final Loan loan = this.loanRepositoryWrapper.findOneWithNotFoundDetection(loanId, true);
|
final Loan loan = this.loanRepositoryWrapper.findOneWithNotFoundDetection(loanId, true);
|
||||||
loan.setHelpers(defaultLoanLifecycleStateMachine, this.loanRepaymentScheduleTransactionProcessorFactory);
|
loan.setHelpers(defaultLoanLifecycleStateMachine);
|
||||||
return loan;
|
return loan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -169,7 +169,7 @@ public class LoanAssemblerImpl implements LoanAssembler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setHelpers(final Loan loanAccount) {
|
public void setHelpers(final Loan loanAccount) {
|
||||||
loanAccount.setHelpers(defaultLoanLifecycleStateMachine, loanRepaymentScheduleTransactionProcessorFactory);
|
loanAccount.setHelpers(defaultLoanLifecycleStateMachine);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -294,7 +294,7 @@ public class LoanAssemblerImpl implements LoanAssembler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
copyAdvancedPaymentRulesIfApplicable(transactionProcessingStrategyCode, loanProduct, loanApplication);
|
copyAdvancedPaymentRulesIfApplicable(transactionProcessingStrategyCode, loanProduct, loanApplication);
|
||||||
loanApplication.setHelpers(defaultLoanLifecycleStateMachine, this.loanRepaymentScheduleTransactionProcessorFactory);
|
loanApplication.setHelpers(defaultLoanLifecycleStateMachine);
|
||||||
// TODO: review
|
// TODO: review
|
||||||
loanChargeService.recalculateAllCharges(loanApplication);
|
loanChargeService.recalculateAllCharges(loanApplication);
|
||||||
topUpLoanConfiguration(element, loanApplication);
|
topUpLoanConfiguration(element, loanApplication);
|
||||||
|
|||||||
+3
-2
@@ -179,6 +179,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
|||||||
private final LoanTransactionRelationReadService loanTransactionRelationReadService;
|
private final LoanTransactionRelationReadService loanTransactionRelationReadService;
|
||||||
private final LoanForeclosureValidator loanForeclosureValidator;
|
private final LoanForeclosureValidator loanForeclosureValidator;
|
||||||
private final LoanTransactionMapper loanTransactionMapper;
|
private final LoanTransactionMapper loanTransactionMapper;
|
||||||
|
private final LoanTransactionProcessingService loadTransactionProcessingService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LoanAccountData retrieveOne(final Long loanId) {
|
public LoanAccountData retrieveOne(final Long loanId) {
|
||||||
@@ -466,7 +467,6 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
|||||||
this.loanUtilService.validateRepaymentTransactionType(repaymentTransactionType);
|
this.loanUtilService.validateRepaymentTransactionType(repaymentTransactionType);
|
||||||
|
|
||||||
final Loan loan = this.loanRepositoryWrapper.findOneWithNotFoundDetection(loanId, true);
|
final Loan loan = this.loanRepositoryWrapper.findOneWithNotFoundDetection(loanId, true);
|
||||||
loan.setHelpers(null, loanRepaymentScheduleTransactionProcessorFactory);
|
|
||||||
|
|
||||||
final MonetaryCurrency currency = loan.getCurrency();
|
final MonetaryCurrency currency = loan.getCurrency();
|
||||||
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency);
|
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency);
|
||||||
@@ -476,7 +476,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
|||||||
final LocalDate earliestUnpaidInstallmentDate = DateUtils.getBusinessLocalDate();
|
final LocalDate earliestUnpaidInstallmentDate = DateUtils.getBusinessLocalDate();
|
||||||
final LocalDate recalculateFrom = null;
|
final LocalDate recalculateFrom = null;
|
||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
final ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||||
final OutstandingAmountsDTO outstandingAmounts = loan.fetchPrepaymentDetail(scheduleGeneratorDTO, onDate);
|
final OutstandingAmountsDTO outstandingAmounts = loadTransactionProcessingService.fetchPrepaymentDetail(scheduleGeneratorDTO,
|
||||||
|
onDate, loan);
|
||||||
final LoanTransactionEnumData transactionType = LoanEnumerations.transactionType(repaymentTransactionType);
|
final LoanTransactionEnumData transactionType = LoanEnumerations.transactionType(repaymentTransactionType);
|
||||||
final Collection<PaymentTypeData> paymentOptions = this.paymentTypeReadPlatformService.retrieveAllPaymentTypes();
|
final Collection<PaymentTypeData> paymentOptions = this.paymentTypeReadPlatformService.retrieveAllPaymentTypes();
|
||||||
final BigDecimal outstandingLoanBalance = outstandingAmounts.principal().getAmount();
|
final BigDecimal outstandingLoanBalance = outstandingAmounts.principal().getAmount();
|
||||||
|
|||||||
+12
-17
@@ -176,7 +176,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelationR
|
|||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelationTypeEnum;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRelationTypeEnum;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor;
|
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
|
||||||
import org.apache.fineract.portfolio.loanaccount.exception.DateMismatchException;
|
import org.apache.fineract.portfolio.loanaccount.exception.DateMismatchException;
|
||||||
@@ -281,6 +280,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
private final LoanAccountService loanAccountService;
|
private final LoanAccountService loanAccountService;
|
||||||
private final LoanJournalEntryPoster journalEntryPoster;
|
private final LoanJournalEntryPoster journalEntryPoster;
|
||||||
private final LoanAdjustmentService loanAdjustmentService;
|
private final LoanAdjustmentService loanAdjustmentService;
|
||||||
|
private final LoanTransactionProcessingService loanTransactionProcessingService;
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
@@ -1068,8 +1068,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
loan.addLoanTransaction(newInterestPaymentWaiverTransaction);
|
loan.addLoanTransaction(newInterestPaymentWaiverTransaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loan.getTransactionProcessor();
|
|
||||||
|
|
||||||
final LoanRepaymentScheduleInstallment currentInstallment = loan.fetchLoanRepaymentScheduleInstallmentByDueDate(transactionDate);
|
final LoanRepaymentScheduleInstallment currentInstallment = loan.fetchLoanRepaymentScheduleInstallmentByDueDate(transactionDate);
|
||||||
|
|
||||||
boolean reprocess = true;
|
boolean reprocess = true;
|
||||||
@@ -1081,9 +1079,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
|
|
||||||
if (isTransactionChronologicallyLatest && (!reprocess || !loan.isInterestBearingAndInterestRecalculationEnabled())
|
if (isTransactionChronologicallyLatest && (!reprocess || !loan.isInterestBearingAndInterestRecalculationEnabled())
|
||||||
&& !loan.isForeclosure()) {
|
&& !loan.isForeclosure()) {
|
||||||
loanRepaymentScheduleTransactionProcessor.processLatestTransaction(newInterestPaymentWaiverTransaction,
|
loanTransactionProcessingService.processLatestTransaction(loan.getTransactionProcessingStrategyCode(),
|
||||||
new TransactionCtx(loan.getCurrency(), loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(),
|
newInterestPaymentWaiverTransaction, new TransactionCtx(loan.getCurrency(), loan.getRepaymentScheduleInstallments(),
|
||||||
new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
loan.getActiveCharges(), new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
||||||
reprocess = false;
|
reprocess = false;
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
if (currentInstallment == null || currentInstallment.isNotFullyPaidOff()) {
|
if (currentInstallment == null || currentInstallment.isNotFullyPaidOff()) {
|
||||||
@@ -2105,7 +2103,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan.getDisbursementDate());
|
holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), loan.getDisbursementDate());
|
||||||
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
if (loan.isInterestBearingAndInterestRecalculationEnabled()) {
|
||||||
ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
ScheduleGeneratorDTO scheduleGeneratorDTO = loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
|
||||||
loan.setHelpers(null, this.transactionProcessingStrategy);
|
|
||||||
loanScheduleService.recalculateScheduleFromLastTransaction(loan, scheduleGeneratorDTO, existingTransactionIds,
|
loanScheduleService.recalculateScheduleFromLastTransaction(loan, scheduleGeneratorDTO, existingTransactionIds,
|
||||||
existingReversedTransactionIds);
|
existingReversedTransactionIds);
|
||||||
createAndSaveLoanScheduleArchive(loan, scheduleGeneratorDTO);
|
createAndSaveLoanScheduleArchive(loan, scheduleGeneratorDTO);
|
||||||
@@ -3106,15 +3103,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
public void handleChargebackTransaction(final Loan loan, LoanTransaction chargebackTransaction,
|
public void handleChargebackTransaction(final Loan loan, LoanTransaction chargebackTransaction,
|
||||||
final LoanLifecycleStateMachine loanLifecycleStateMachine) {
|
final LoanLifecycleStateMachine loanLifecycleStateMachine) {
|
||||||
loanTransactionValidator.validateIfTransactionIsChargeback(chargebackTransaction);
|
loanTransactionValidator.validateIfTransactionIsChargeback(chargebackTransaction);
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loan.getTransactionProcessor();
|
|
||||||
|
|
||||||
loan.addLoanTransaction(chargebackTransaction);
|
loan.addLoanTransaction(chargebackTransaction);
|
||||||
if (loan.isInterestBearing() && loan.isInterestRecalculationEnabled()) {
|
if (loan.isInterestBearing() && loan.isInterestRecalculationEnabled()) {
|
||||||
loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(loan.getDisbursementDate(),
|
loanTransactionProcessingService.reprocessLoanTransactions(loan.getTransactionProcessingStrategyCode(),
|
||||||
loan.retrieveListOfTransactionsForReprocessing(), loan.getCurrency(), loan.getRepaymentScheduleInstallments(),
|
loan.getDisbursementDate(), loan.retrieveListOfTransactionsForReprocessing(), loan.getCurrency(),
|
||||||
loan.getActiveCharges());
|
loan.getRepaymentScheduleInstallments(), loan.getActiveCharges());
|
||||||
} else {
|
} else {
|
||||||
loanRepaymentScheduleTransactionProcessor.processLatestTransaction(chargebackTransaction,
|
loanTransactionProcessingService.processLatestTransaction(loan.getTransactionProcessingStrategyCode(), chargebackTransaction,
|
||||||
new TransactionCtx(loan.getCurrency(), loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(),
|
new TransactionCtx(loan.getCurrency(), loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(),
|
||||||
new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
||||||
}
|
}
|
||||||
@@ -3261,7 +3257,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
final LoanLifecycleStateMachine loanLifecycleStateMachine, final Map<String, Object> changes,
|
final LoanLifecycleStateMachine loanLifecycleStateMachine, final Map<String, Object> changes,
|
||||||
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds, final AppUser currentUser,
|
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds, final AppUser currentUser,
|
||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
final ScheduleGeneratorDTO scheduleGeneratorDTO) {
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loan.getTransactionProcessor();
|
|
||||||
closeDisbursements(loan, scheduleGeneratorDTO);
|
closeDisbursements(loan, scheduleGeneratorDTO);
|
||||||
|
|
||||||
final LocalDate writtenOffOnLocalDate = command.localDateValueOfParameterNamed(TRANSACTION_DATE);
|
final LocalDate writtenOffOnLocalDate = command.localDateValueOfParameterNamed(TRANSACTION_DATE);
|
||||||
@@ -3313,8 +3308,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
}
|
}
|
||||||
|
|
||||||
loan.addLoanTransaction(loanTransaction);
|
loan.addLoanTransaction(loanTransaction);
|
||||||
loanRepaymentScheduleTransactionProcessor.processLatestTransaction(loanTransaction, new TransactionCtx(loan.getCurrency(),
|
loanTransactionProcessingService.processLatestTransaction(loan.getTransactionProcessingStrategyCode(), loanTransaction,
|
||||||
loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(), new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
new TransactionCtx(loan.getCurrency(), loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(),
|
||||||
|
new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
||||||
|
|
||||||
loan.updateLoanSummaryDerivedFields();
|
loan.updateLoanSummaryDerivedFields();
|
||||||
|
|
||||||
@@ -3366,7 +3362,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
final String errorMessage = "The date on which a loan is closed cannot be in the future.";
|
final String errorMessage = "The date on which a loan is closed cannot be in the future.";
|
||||||
throw new InvalidLoanStateTransitionException("close", "cannot.be.a.future.date", errorMessage, closureDate);
|
throw new InvalidLoanStateTransitionException("close", "cannot.be.a.future.date", errorMessage, closureDate);
|
||||||
}
|
}
|
||||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loan.getTransactionProcessor();
|
|
||||||
closeDisbursements(loan, scheduleGeneratorDTO);
|
closeDisbursements(loan, scheduleGeneratorDTO);
|
||||||
|
|
||||||
LoanTransaction loanTransaction = null;
|
LoanTransaction loanTransaction = null;
|
||||||
@@ -3390,7 +3385,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
}
|
}
|
||||||
|
|
||||||
loan.addLoanTransaction(loanTransaction);
|
loan.addLoanTransaction(loanTransaction);
|
||||||
loanRepaymentScheduleTransactionProcessor.processLatestTransaction(loanTransaction,
|
loanTransactionProcessingService.processLatestTransaction(loan.getTransactionProcessingStrategyCode(), loanTransaction,
|
||||||
new TransactionCtx(loan.getCurrency(), loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(),
|
new TransactionCtx(loan.getCurrency(), loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(),
|
||||||
new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
new MoneyHolder(loan.getTotalOverpaidAsMoney()), null));
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -60,6 +60,7 @@ public class ProgressiveLoanInterestRefundServiceImpl implements InterestRefundS
|
|||||||
private final LoanAssembler loanAssembler;
|
private final LoanAssembler loanAssembler;
|
||||||
private final LoanScheduleService loanScheduleService;
|
private final LoanScheduleService loanScheduleService;
|
||||||
private final LoanUtilService loanUtilService;
|
private final LoanUtilService loanUtilService;
|
||||||
|
private final LoanTransactionProcessingService loanTransactionProcessingService;
|
||||||
|
|
||||||
private static void simulateRepaymentForDisbursements(LoanTransaction lt, final AtomicReference<BigDecimal> refundFinal,
|
private static void simulateRepaymentForDisbursements(LoanTransaction lt, final AtomicReference<BigDecimal> refundFinal,
|
||||||
List<LoanTransaction> collect) {
|
List<LoanTransaction> collect) {
|
||||||
@@ -116,7 +117,7 @@ public class ProgressiveLoanInterestRefundServiceImpl implements InterestRefundS
|
|||||||
LocalDate relatedRefundTransactionDate, List<LoanTransaction> newTransactions, List<Long> oldTransactionIds) {
|
LocalDate relatedRefundTransactionDate, List<LoanTransaction> newTransactions, List<Long> oldTransactionIds) {
|
||||||
Loan loan = loanAssembler.assembleFrom(loanId);
|
Loan loan = loanAssembler.assembleFrom(loanId);
|
||||||
if (processor == null) {
|
if (processor == null) {
|
||||||
processor = loan.getTransactionProcessor();
|
processor = loanTransactionProcessingService.getTransactionProcessor(loan.getTransactionProcessingStrategyCode());
|
||||||
}
|
}
|
||||||
if (!(processor instanceof AdvancedPaymentScheduleTransactionProcessor)) {
|
if (!(processor instanceof AdvancedPaymentScheduleTransactionProcessor)) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
|
|||||||
+20
-12
@@ -137,6 +137,7 @@ import org.apache.fineract.portfolio.loanaccount.service.LoanScheduleService;
|
|||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanStatusChangePlatformService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanStatusChangePlatformService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanStatusChangePlatformServiceImpl;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanStatusChangePlatformServiceImpl;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanTransactionAssembler;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanTransactionAssembler;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.service.LoanTransactionProcessingService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanTransactionRelationReadService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanTransactionRelationReadService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanUtilService;
|
||||||
import org.apache.fineract.portfolio.loanaccount.service.LoanWritePlatformService;
|
import org.apache.fineract.portfolio.loanaccount.service.LoanWritePlatformService;
|
||||||
@@ -326,7 +327,8 @@ public class LoanAccountConfiguration {
|
|||||||
ColumnValidator columnValidator, DatabaseSpecificSQLGenerator sqlGenerator,
|
ColumnValidator columnValidator, DatabaseSpecificSQLGenerator sqlGenerator,
|
||||||
DelinquencyReadPlatformService delinquencyReadPlatformService, LoanTransactionRepository loanTransactionRepository,
|
DelinquencyReadPlatformService delinquencyReadPlatformService, LoanTransactionRepository loanTransactionRepository,
|
||||||
LoanChargePaidByReadService loanChargePaidByReadService, LoanTransactionRelationReadService loanTransactionRelationReadService,
|
LoanChargePaidByReadService loanChargePaidByReadService, LoanTransactionRelationReadService loanTransactionRelationReadService,
|
||||||
LoanForeclosureValidator loanForeclosureValidator, LoanTransactionMapper loanTransactionMapper) {
|
LoanForeclosureValidator loanForeclosureValidator, LoanTransactionMapper loanTransactionMapper,
|
||||||
|
LoanTransactionProcessingService loanTransactionProcessingService) {
|
||||||
return new LoanReadPlatformServiceImpl(jdbcTemplate, context, loanRepositoryWrapper, applicationCurrencyRepository,
|
return new LoanReadPlatformServiceImpl(jdbcTemplate, context, loanRepositoryWrapper, applicationCurrencyRepository,
|
||||||
loanProductReadPlatformService, clientReadPlatformService, groupReadPlatformService, loanDropdownReadPlatformService,
|
loanProductReadPlatformService, clientReadPlatformService, groupReadPlatformService, loanDropdownReadPlatformService,
|
||||||
fundReadPlatformService, chargeReadPlatformService, codeValueReadPlatformService, calendarReadPlatformService,
|
fundReadPlatformService, chargeReadPlatformService, codeValueReadPlatformService, calendarReadPlatformService,
|
||||||
@@ -334,7 +336,7 @@ public class LoanAccountConfiguration {
|
|||||||
loanRepaymentScheduleTransactionProcessorFactory, floatingRatesReadPlatformService, loanUtilService,
|
loanRepaymentScheduleTransactionProcessorFactory, floatingRatesReadPlatformService, loanUtilService,
|
||||||
configurationDomainService, accountDetailsReadPlatformService, columnValidator, sqlGenerator,
|
configurationDomainService, accountDetailsReadPlatformService, columnValidator, sqlGenerator,
|
||||||
delinquencyReadPlatformService, loanTransactionRepository, loanChargePaidByReadService, loanTransactionRelationReadService,
|
delinquencyReadPlatformService, loanTransactionRepository, loanChargePaidByReadService, loanTransactionRelationReadService,
|
||||||
loanForeclosureValidator, loanTransactionMapper);
|
loanForeclosureValidator, loanTransactionMapper, loanTransactionProcessingService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@@ -396,7 +398,8 @@ public class LoanAccountConfiguration {
|
|||||||
LoanDisbursementService loanDisbursementService, LoanScheduleService loanScheduleService,
|
LoanDisbursementService loanDisbursementService, LoanScheduleService loanScheduleService,
|
||||||
LoanChargeValidator loanChargeValidator, LoanOfficerService loanOfficerService,
|
LoanChargeValidator loanChargeValidator, LoanOfficerService loanOfficerService,
|
||||||
ReprocessLoanTransactionsService reprocessLoanTransactionsService, LoanAccountService loanAccountService,
|
ReprocessLoanTransactionsService reprocessLoanTransactionsService, LoanAccountService loanAccountService,
|
||||||
LoanJournalEntryPoster journalEntryPoster, LoanAdjustmentService loanAdjustmentService) {
|
LoanJournalEntryPoster journalEntryPoster, LoanAdjustmentService loanAdjustmentService,
|
||||||
|
LoanTransactionProcessingService loanTransactionProcessingService) {
|
||||||
return new LoanWritePlatformServiceJpaRepositoryImpl(context, loanTransactionValidator, loanUpdateCommandFromApiJsonDeserializer,
|
return new LoanWritePlatformServiceJpaRepositoryImpl(context, loanTransactionValidator, loanUpdateCommandFromApiJsonDeserializer,
|
||||||
loanRepositoryWrapper, loanAccountDomainService, noteRepository, loanTransactionRepository,
|
loanRepositoryWrapper, loanAccountDomainService, noteRepository, loanTransactionRepository,
|
||||||
loanTransactionRelationRepository, loanAssembler, journalEntryWritePlatformService, calendarInstanceRepository,
|
loanTransactionRelationRepository, loanAssembler, journalEntryWritePlatformService, calendarInstanceRepository,
|
||||||
@@ -410,7 +413,8 @@ public class LoanAccountConfiguration {
|
|||||||
loanAccountLockService, externalIdFactory, loanAccrualTransactionBusinessEventService, errorHandler,
|
loanAccountLockService, externalIdFactory, loanAccrualTransactionBusinessEventService, errorHandler,
|
||||||
loanDownPaymentHandlerService, loanTransactionAssembler, loanAccrualsProcessingService, loanOfficerValidator,
|
loanDownPaymentHandlerService, loanTransactionAssembler, loanAccrualsProcessingService, loanOfficerValidator,
|
||||||
loanDownPaymentTransactionValidator, loanDisbursementService, loanScheduleService, loanChargeValidator, loanOfficerService,
|
loanDownPaymentTransactionValidator, loanDisbursementService, loanScheduleService, loanChargeValidator, loanOfficerService,
|
||||||
reprocessLoanTransactionsService, loanAccountService, journalEntryPoster, loanAdjustmentService);
|
reprocessLoanTransactionsService, loanAccountService, journalEntryPoster, loanAdjustmentService,
|
||||||
|
loanTransactionProcessingService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@@ -426,10 +430,11 @@ public class LoanAccountConfiguration {
|
|||||||
BusinessEventNotifierService businessEventNotifierService,
|
BusinessEventNotifierService businessEventNotifierService,
|
||||||
LoanDownPaymentTransactionValidator loanDownPaymentTransactionValidator, LoanScheduleService loanScheduleService,
|
LoanDownPaymentTransactionValidator loanDownPaymentTransactionValidator, LoanScheduleService loanScheduleService,
|
||||||
LoanRefundService loanRefundService, LoanRefundValidator loanRefundValidator,
|
LoanRefundService loanRefundService, LoanRefundValidator loanRefundValidator,
|
||||||
ReprocessLoanTransactionsService reprocessLoanTransactionsService) {
|
ReprocessLoanTransactionsService reprocessLoanTransactionsService,
|
||||||
|
LoanTransactionProcessingService loanTransactionProcessingService) {
|
||||||
return new LoanDownPaymentHandlerServiceImpl(loanTransactionRepository, businessEventNotifierService,
|
return new LoanDownPaymentHandlerServiceImpl(loanTransactionRepository, businessEventNotifierService,
|
||||||
loanDownPaymentTransactionValidator, loanScheduleService, loanRefundService, loanRefundValidator,
|
loanDownPaymentTransactionValidator, loanScheduleService, loanRefundService, loanRefundValidator,
|
||||||
reprocessLoanTransactionsService);
|
reprocessLoanTransactionsService, loanTransactionProcessingService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@@ -447,15 +452,17 @@ public class LoanAccountConfiguration {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean(LoanChargeService.class)
|
@ConditionalOnMissingBean(LoanChargeService.class)
|
||||||
public LoanChargeService loanChargeService(LoanChargeValidator loanChargeValidator) {
|
public LoanChargeService loanChargeService(LoanChargeValidator loanChargeValidator,
|
||||||
return new LoanChargeService(loanChargeValidator);
|
LoanTransactionProcessingService loanTransactionProcessingService) {
|
||||||
|
return new LoanChargeService(loanChargeValidator, loanTransactionProcessingService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean(LoanScheduleService.class)
|
@ConditionalOnMissingBean(LoanScheduleService.class)
|
||||||
public LoanScheduleService loanScheduleService(LoanChargeService loanChargeService,
|
public LoanScheduleService loanScheduleService(LoanChargeService loanChargeService,
|
||||||
ReprocessLoanTransactionsService reprocessLoanTransactionsService) {
|
ReprocessLoanTransactionsService reprocessLoanTransactionsService,
|
||||||
return new LoanScheduleService(loanChargeService, reprocessLoanTransactionsService);
|
LoanTransactionProcessingService loanTransactionProcessingService) {
|
||||||
|
return new LoanScheduleService(loanChargeService, reprocessLoanTransactionsService, loanTransactionProcessingService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@@ -466,8 +473,9 @@ public class LoanAccountConfiguration {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean(LoanRefundService.class)
|
@ConditionalOnMissingBean(LoanRefundService.class)
|
||||||
public LoanRefundService loanRefundService(LoanRefundValidator loanRefundValidator) {
|
public LoanRefundService loanRefundService(LoanRefundValidator loanRefundValidator,
|
||||||
return new LoanRefundService(loanRefundValidator);
|
LoanTransactionProcessingService loanTransactionProcessingService) {
|
||||||
|
return new LoanRefundService(loanRefundValidator, loanTransactionProcessingService);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
|||||||
+5
-3
@@ -104,13 +104,16 @@ public class LoanDownPaymentHandlerServiceImplTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
private ReprocessLoanTransactionsService reprocessLoanTransactionsService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private LoanTransactionProcessingService loanTransactionProcessingService;
|
||||||
|
|
||||||
private LoanDownPaymentHandlerServiceImpl underTest;
|
private LoanDownPaymentHandlerServiceImpl underTest;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
underTest = new LoanDownPaymentHandlerServiceImpl(loanTransactionRepository, businessEventNotifierService,
|
underTest = new LoanDownPaymentHandlerServiceImpl(loanTransactionRepository, businessEventNotifierService,
|
||||||
loanDownPaymentTransactionValidator, loanScheduleService, loanRefundService, loanRefundValidator,
|
loanDownPaymentTransactionValidator, loanScheduleService, loanRefundService, loanRefundValidator,
|
||||||
reprocessLoanTransactionsService);
|
reprocessLoanTransactionsService, loanTransactionProcessingService);
|
||||||
moneyHelper.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.UP));
|
moneyHelper.when(MoneyHelper::getMathContext).thenReturn(new MathContext(12, RoundingMode.UP));
|
||||||
moneyHelper.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.UP);
|
moneyHelper.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.UP);
|
||||||
tempConfigServiceMock.when(TemporaryConfigurationServiceContainer::isExternalIdAutoGenerationEnabled).thenReturn(true);
|
tempConfigServiceMock.when(TemporaryConfigurationServiceContainer::isExternalIdAutoGenerationEnabled).thenReturn(true);
|
||||||
@@ -156,8 +159,7 @@ public class LoanDownPaymentHandlerServiceImplTest {
|
|||||||
when(loanForProcessing.getLoanProduct()).thenReturn(loanProduct);
|
when(loanForProcessing.getLoanProduct()).thenReturn(loanProduct);
|
||||||
when(loanProduct.getInstallmentAmountInMultiplesOf()).thenReturn(10);
|
when(loanProduct.getInstallmentAmountInMultiplesOf()).thenReturn(10);
|
||||||
when(loanForProcessing.getLoanProductRelatedDetail()).thenReturn(loanProductRelatedDetail);
|
when(loanForProcessing.getLoanProductRelatedDetail()).thenReturn(loanProductRelatedDetail);
|
||||||
when(loanForProcessing.getTransactionProcessor()).thenReturn(loanRepaymentScheduleTransactionProcessor);
|
when(loanTransactionProcessingService.reprocessLoanTransactions(any(), any(), any(), any(), any(), any()))
|
||||||
when(loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(any(), any(), any(), any(), any()))
|
|
||||||
.thenReturn(changedTransactionDetail);
|
.thenReturn(changedTransactionDetail);
|
||||||
when(loanProductRelatedDetail.getLoanScheduleType()).thenReturn(LoanScheduleType.PROGRESSIVE);
|
when(loanProductRelatedDetail.getLoanScheduleType()).thenReturn(LoanScheduleType.PROGRESSIVE);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user