FINERACT-2104: Accrual Activity Reverse Replay Transaction
This commit is contained in:
+14
-12
@@ -2481,24 +2481,19 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
}
|
||||
|
||||
public List<LoanTransaction> retrieveListOfTransactionsForReprocessing() {
|
||||
return getLoanTransactions().stream()
|
||||
.filter(transaction -> transaction.isNotReversed() && !transaction.isAccrual()
|
||||
&& (transaction.isChargeOff() || transaction.isReAge() || transaction.isReAmortize()
|
||||
|| !transaction.isNonMonetaryTransaction()))
|
||||
.sorted(LoanTransactionComparator.INSTANCE).collect(Collectors.toList());
|
||||
return getLoanTransactions().stream().filter(loanTransactionForReprocessingPredicate()).sorted(LoanTransactionComparator.INSTANCE)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<LoanTransaction> retrieveListOfTransactionsPostDisbursementExcludeAccruals() {
|
||||
return this.loanTransactions.stream()
|
||||
.filter(transaction -> transaction.isNotReversed() && !(transaction.isAccrual() || transaction.isRepaymentAtDisbursement()
|
||||
|| transaction.isNonMonetaryTransaction() || transaction.isIncomePosting()))
|
||||
.sorted(LoanTransactionComparator.INSTANCE).collect(Collectors.toList());
|
||||
private static Predicate<LoanTransaction> loanTransactionForReprocessingPredicate() {
|
||||
return transaction -> transaction.isNotReversed() && (transaction.isChargeOff() || transaction.isReAge()
|
||||
|| transaction.isAccrualActivity() || transaction.isReAmortize() || !transaction.isNonMonetaryTransaction());
|
||||
}
|
||||
|
||||
private List<LoanTransaction> retrieveListOfTransactionsExcludeAccruals() {
|
||||
final List<LoanTransaction> repaymentsOrWaivers = new ArrayList<>();
|
||||
for (final LoanTransaction transaction : this.loanTransactions) {
|
||||
if (transaction.isNotReversed() && !(transaction.isAccrual() || transaction.isNonMonetaryTransaction())) {
|
||||
if (transaction.isNotReversed() && !transaction.isNonMonetaryTransaction()) {
|
||||
repaymentsOrWaivers.add(transaction);
|
||||
}
|
||||
}
|
||||
@@ -3901,6 +3896,13 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
return currentTransactionDate;
|
||||
}
|
||||
|
||||
public LoanTransaction getLastTransactionForReprocessing() {
|
||||
return loanTransactions.stream() //
|
||||
.filter(Loan.loanTransactionForReprocessingPredicate()) //
|
||||
.reduce((first, second) -> second) //
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
public LoanTransaction getLastPaymentTransaction() {
|
||||
return loanTransactions.stream() //
|
||||
.filter(loanTransaction -> !loanTransaction.isReversed()) //
|
||||
@@ -4526,7 +4528,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
}
|
||||
outstanding = outstanding.plus(transactionOutstanding);
|
||||
loanTransaction.updateOutstandingLoanBalance(MathUtil.negativeToZero(outstanding.getAmount()));
|
||||
} else {
|
||||
} else if (!loanTransaction.isAccrualActivity()) {
|
||||
if (this.loanInterestRecalculationDetails != null
|
||||
&& this.loanInterestRecalculationDetails.isCompoundingToBePostedAsTransaction()
|
||||
&& !loanTransaction.isRepaymentAtDisbursement()) {
|
||||
|
||||
+8
-8
@@ -879,11 +879,11 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
|
||||
|
||||
public boolean isNonMonetaryTransaction() {
|
||||
return isNotReversed() && (LoanTransactionType.CONTRA.equals(getTypeOf())
|
||||
|| LoanTransactionType.MARKED_FOR_RESCHEDULING.equals(getTypeOf())
|
||||
|| LoanTransactionType.APPROVE_TRANSFER.equals(getTypeOf()) || LoanTransactionType.INITIATE_TRANSFER.equals(getTypeOf())
|
||||
|| LoanTransactionType.REJECT_TRANSFER.equals(getTypeOf()) || LoanTransactionType.WITHDRAW_TRANSFER.equals(getTypeOf())
|
||||
|| LoanTransactionType.CHARGE_OFF.equals(getTypeOf()) || LoanTransactionType.REAMORTIZE.equals(getTypeOf())
|
||||
|| LoanTransactionType.REAGE.equals(getTypeOf()));
|
||||
|| LoanTransactionType.MARKED_FOR_RESCHEDULING.equals(getTypeOf()) || LoanTransactionType.ACCRUAL.equals(getTypeOf())
|
||||
|| LoanTransactionType.ACCRUAL_ACTIVITY.equals(getTypeOf()) || LoanTransactionType.APPROVE_TRANSFER.equals(getTypeOf())
|
||||
|| LoanTransactionType.INITIATE_TRANSFER.equals(getTypeOf()) || LoanTransactionType.REJECT_TRANSFER.equals(getTypeOf())
|
||||
|| LoanTransactionType.WITHDRAW_TRANSFER.equals(getTypeOf()) || LoanTransactionType.CHARGE_OFF.equals(getTypeOf())
|
||||
|| LoanTransactionType.REAMORTIZE.equals(getTypeOf()) || LoanTransactionType.REAGE.equals(getTypeOf()));
|
||||
}
|
||||
|
||||
public void updateOutstandingLoanBalance(BigDecimal outstandingLoanBalance) {
|
||||
@@ -949,7 +949,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
|
||||
}
|
||||
|
||||
public Boolean isAllowTypeTransactionAtTheTimeOfLastUndo() {
|
||||
return isDisbursement() || isAccrual() || isRepaymentAtDisbursement() || isRepayment();
|
||||
return isDisbursement() || isAccrual() || isRepaymentAtDisbursement() || isRepayment() || isAccrualActivity();
|
||||
}
|
||||
|
||||
public boolean isAccrualTransaction() {
|
||||
@@ -969,8 +969,8 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
|
||||
}
|
||||
|
||||
public boolean isPaymentTransaction() {
|
||||
return this.isNotReversed() && !(this.isDisbursement() || this.isAccrual() || this.isRepaymentAtDisbursement()
|
||||
|| this.isNonMonetaryTransaction() || this.isIncomePosting());
|
||||
return this.isNotReversed() && !(this.isDisbursement() || this.isRepaymentAtDisbursement() || this.isNonMonetaryTransaction()
|
||||
|| this.isIncomePosting());
|
||||
}
|
||||
|
||||
public Set<LoanCollateralManagement> getLoanCollateralManagementSet() {
|
||||
|
||||
+31
@@ -204,12 +204,43 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
||||
reprocessChargebackTransactionRelation(changedTransactionDetail, transactionsToBeProcessed);
|
||||
} else if (loanTransaction.isChargeOff()) {
|
||||
recalculateChargeOffTransaction(changedTransactionDetail, loanTransaction, currency, installments);
|
||||
} else if (loanTransaction.isAccrualActivity()) {
|
||||
recalculateAccrualActivityTransaction(changedTransactionDetail, loanTransaction, currency, installments);
|
||||
}
|
||||
}
|
||||
reprocessInstallments(disbursementDate, transactionsToBeProcessed, installments, currency);
|
||||
return changedTransactionDetail;
|
||||
}
|
||||
|
||||
protected void calculateAccrualActivity(LoanTransaction loanTransaction, MonetaryCurrency currency,
|
||||
List<LoanRepaymentScheduleInstallment> installments) {
|
||||
loanTransaction.resetDerivedComponents();
|
||||
// determine how much is outstanding total and breakdown for principal, interest and charges
|
||||
final Money principalPortion = Money.zero(currency);
|
||||
Money interestPortion = Money.zero(currency);
|
||||
Money feeChargesPortion = Money.zero(currency);
|
||||
Money penaltychargesPortion = Money.zero(currency);
|
||||
for (final LoanRepaymentScheduleInstallment currentInstallment : installments) {
|
||||
if (loanTransaction.getDateOf().isEqual(currentInstallment.getDueDate())) {
|
||||
interestPortion = interestPortion.plus(currentInstallment.getInterestCharged(currency));
|
||||
feeChargesPortion = feeChargesPortion.plus(currentInstallment.getFeeChargesCharged(currency));
|
||||
penaltychargesPortion = penaltychargesPortion.plus(currentInstallment.getPenaltyChargesCharged(currency));
|
||||
}
|
||||
}
|
||||
loanTransaction.updateComponentsAndTotal(principalPortion, interestPortion, feeChargesPortion, penaltychargesPortion);
|
||||
}
|
||||
|
||||
private void recalculateAccrualActivityTransaction(ChangedTransactionDetail changedTransactionDetail, LoanTransaction loanTransaction,
|
||||
MonetaryCurrency currency, List<LoanRepaymentScheduleInstallment> installments) {
|
||||
final LoanTransaction newLoanTransaction = LoanTransaction.copyTransactionProperties(loanTransaction);
|
||||
|
||||
calculateAccrualActivity(newLoanTransaction, currency, installments);
|
||||
|
||||
if (!LoanTransaction.transactionAmountsMatch(currency, loanTransaction, newLoanTransaction)) {
|
||||
createNewTransaction(loanTransaction, newLoanTransaction, changedTransactionDetail);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processLatestTransaction(final LoanTransaction loanTransaction, final TransactionCtx ctx) {
|
||||
switch (loanTransaction.getTypeOf()) {
|
||||
|
||||
+1
-1
@@ -2785,7 +2785,7 @@ public abstract class AbstractCumulativeLoanScheduleGenerator implements LoanSch
|
||||
|
||||
LoanScheduleDTO loanScheduleDTO = rescheduleNextInstallments(mc, loanApplicationTerms, loan, holidayDetailDTO,
|
||||
loanRepaymentScheduleTransactionProcessor, onDate, calculateTill);
|
||||
List<LoanTransaction> loanTransactions = loan.retrieveListOfTransactionsPostDisbursementExcludeAccruals();
|
||||
List<LoanTransaction> loanTransactions = loan.retrieveListOfTransactionsForReprocessing();
|
||||
|
||||
loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions(loanApplicationTerms.getExpectedDisbursementDate(),
|
||||
loanTransactions, currency, loanScheduleDTO.getInstallments(), loan.getActiveCharges());
|
||||
|
||||
Reference in New Issue
Block a user