FINERACT-2042: Fix chargeback on overpaid loan
This commit is contained in:
+22
-16
@@ -134,6 +134,7 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanSchedul
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModel;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModelPeriod;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.AmortizationMethod;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.CreditAllocationTransactionType;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.InterestRecalculationCompoundingMethod;
|
||||
@@ -712,7 +713,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
ChangedTransactionDetail changedTransactionDetail = null;
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
|
||||
changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(getDisbursementDate(),
|
||||
allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(), getActiveCharges());
|
||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
||||
@@ -875,7 +876,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
* Consider removing this block of code or logically completing it for the future by getting the list of
|
||||
* affected Transactions
|
||||
***/
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
|
||||
loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(getDisbursementDate(),
|
||||
allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(), getActiveCharges());
|
||||
}
|
||||
@@ -943,7 +944,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
* Consider removing this block of code or logically completing it for the future by getting the list of
|
||||
* affected Transactions
|
||||
***/
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
|
||||
loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(getDisbursementDate(),
|
||||
allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(), getActiveCharges());
|
||||
} else {
|
||||
@@ -1137,7 +1138,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
* Consider removing this block of code or logically completing it for the future by getting the list of
|
||||
* affected Transactions
|
||||
*/
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
|
||||
loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(getDisbursementDate(),
|
||||
allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(), getActiveCharges());
|
||||
} else {
|
||||
@@ -2696,7 +2697,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
private ChangedTransactionDetail reprocessTransactionForDisbursement() {
|
||||
ChangedTransactionDetail changedTransactionDetail = null;
|
||||
if (this.loanProduct.isMultiDisburseLoan()) {
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
|
||||
if (!allNonContraTransactionsPostDisbursement.isEmpty()) {
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
@@ -3369,7 +3370,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
|
||||
}
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
|
||||
changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(getDisbursementDate(),
|
||||
allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(), getActiveCharges());
|
||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
||||
@@ -3429,12 +3430,12 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
return incomePostTransactions;
|
||||
}
|
||||
|
||||
private List<LoanTransaction> retrieveListOfTransactionsPostDisbursement() {
|
||||
public List<LoanTransaction> retrieveListOfTransactionsForReprocessing() {
|
||||
final List<LoanTransaction> repaymentsOrWaivers = new ArrayList<>();
|
||||
List<LoanTransaction> trans = getLoanTransactions();
|
||||
for (final LoanTransaction transaction : trans) {
|
||||
if (transaction.isNotReversed() && (transaction.isChargeOff() || transaction.isReAge() || transaction.isReAmortize()
|
||||
|| !transaction.isNonMonetaryTransaction())) {
|
||||
if (transaction.isNotReversed() && !transaction.isAccrual() && (transaction.isChargeOff() || transaction.isReAge()
|
||||
|| transaction.isReAmortize() || !transaction.isNonMonetaryTransaction())) {
|
||||
repaymentsOrWaivers.add(transaction);
|
||||
}
|
||||
}
|
||||
@@ -3818,7 +3819,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
loanLifecycleStateMachine.transition(LoanEvent.WRITE_OFF_OUTSTANDING_UNDO, this);
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
|
||||
if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
|
||||
}
|
||||
@@ -3868,10 +3869,15 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
}
|
||||
if (loanTransaction.isRefund() || loanTransaction.isRefundForActiveLoan()) {
|
||||
totalPaidInRepayments = totalPaidInRepayments.minus(loanTransaction.getAmount(currency));
|
||||
} else if (loanTransaction.isCreditBalanceRefund() || loanTransaction.isChargeback()) {
|
||||
} else if (loanTransaction.isCreditBalanceRefund()) {
|
||||
if (loanTransaction.getPrincipalPortion(currency).isZero()) {
|
||||
totalPaidInRepayments = totalPaidInRepayments.minus(loanTransaction.getOverPaymentPortion(currency));
|
||||
}
|
||||
} else if (loanTransaction.isChargeback()) {
|
||||
if (loanTransaction.getPrincipalPortion(currency).isZero() && getCreditAllocationRules().stream()
|
||||
.filter(car -> car.getTransactionType().equals(CreditAllocationTransactionType.CHARGEBACK)).findAny().isEmpty()) {
|
||||
totalPaidInRepayments = totalPaidInRepayments.minus(loanTransaction.getOverPaymentPortion(currency));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3972,7 +3978,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
if (this.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
|
||||
regenerateRepaymentScheduleWithInterestRecalculation(scheduleGeneratorDTO);
|
||||
}
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
|
||||
changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(getDisbursementDate(),
|
||||
allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(), getActiveCharges());
|
||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
||||
@@ -5420,7 +5426,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
|
||||
ChangedTransactionDetail changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(
|
||||
getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(),
|
||||
getActiveCharges());
|
||||
@@ -5574,7 +5580,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
public ChangedTransactionDetail processTransactions() {
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
|
||||
ChangedTransactionDetail changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(
|
||||
getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(),
|
||||
getActiveCharges());
|
||||
@@ -5818,7 +5824,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
public void processPostDisbursementTransactions() {
|
||||
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
|
||||
.determineProcessor(this.transactionProcessingStrategyCode);
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
|
||||
final List<LoanTransaction> copyTransactions = new ArrayList<>();
|
||||
if (!allNonContraTransactionsPostDisbursement.isEmpty()) {
|
||||
for (LoanTransaction loanTransaction : allNonContraTransactionsPostDisbursement) {
|
||||
@@ -6428,7 +6434,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
loanRepaymentScheduleTransactionProcessor.processLatestTransaction(loanTransaction, new TransactionCtx(getCurrency(),
|
||||
getRepaymentScheduleInstallments(), getActiveCharges(), new MoneyHolder(getTotalOverpaidAsMoney())));
|
||||
} else {
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsPostDisbursement();
|
||||
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing();
|
||||
changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(getDisbursementDate(),
|
||||
allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(), getActiveCharges());
|
||||
for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail.getNewTransactionMappings().entrySet()) {
|
||||
|
||||
+1
@@ -356,6 +356,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
||||
(ctx.getInstallments().size() + 1), pastDueDate, transactionDate, zeroMoney.getAmount(),
|
||||
zeroMoney.getAmount(), zeroMoney.getAmount(), zeroMoney.getAmount(), false, null);
|
||||
recognizeAmountsAfterChargeback(ctx.getCurrency(), transactionDate, installment, chargebackAllocation);
|
||||
installment.markAsAdditional();
|
||||
loan.addLoanRepaymentScheduleInstallment(installment);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user