FINERACT-2354: Reversal of re-aging transaction - remove restriction of reversal if there was payment after or on that day

This commit is contained in:
Peter Kovacs
2025-11-07 10:23:26 +01:00
committed by Adam Saghy
parent 9320dd1bd7
commit 1b2801447b
4 changed files with 663 additions and 54 deletions
@@ -41,7 +41,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepositor
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
import org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeInterestHandlingType;
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.AdvancedPaymentScheduleTransactionProcessor;
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.ChangeOperation;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
import org.springframework.stereotype.Component;
@@ -158,14 +157,6 @@ public class LoanReAgingValidator {
throw new GeneralPlatformDomainRuleException("error.msg.loan.reage.reaging.transaction.missing",
"Undoing a reaging can only be done if there was a reaging already", loan.getId());
}
// validate if there's no payment between the reaging and today
boolean repaymentExistsAfterReAging = loan.getLoanTransactions().stream()
.anyMatch(tx -> tx.getTypeOf().isRepaymentType() && transactionHappenedAfterOther(tx, optionalReAgingTx.get()));
if (repaymentExistsAfterReAging) {
throw new GeneralPlatformDomainRuleException("error.msg.loan.reage.repayment.exists.after.reaging",
"Undoing a reaging can only be done if there hasn't been any repayment afterwards", loan.getId());
}
}
private void throwExceptionIfValidationErrorsExist(List<ApiParameterError> dataValidationErrors) {
@@ -175,10 +166,6 @@ public class LoanReAgingValidator {
}
}
private boolean transactionHappenedAfterOther(LoanTransaction transaction, LoanTransaction otherTransaction) {
return new ChangeOperation(transaction).compareTo(new ChangeOperation(otherTransaction)) > 0;
}
private void validateReAgeOutstandingBalance(final Loan loan, final JsonCommand command) {
final LocalDate businessDate = getBusinessLocalDate();
final LocalDate startDate = command.dateValueOfParameterNamed(LoanReAgingApiConstants.startDate);
@@ -380,42 +380,6 @@ class LoanReAgingValidatorTest {
assertThat(result.getGlobalisationMessageCode()).isEqualTo("error.msg.loan.reage.reaging.transaction.missing");
}
@Test
public void testValidateUndoReAge_ShouldThrowException_WhenLoanAlreadyHasRepaymentAfterReAge() {
// given
List<LoanTransaction> transactions = List.of(loanTransaction(LoanTransactionType.DISBURSEMENT, actualDate.minusDays(3)),
loanTransaction(LoanTransactionType.REAGE, actualDate.minusDays(2)),
loanTransaction(LoanTransactionType.REPAYMENT, actualDate.minusDays(1)));
Loan loan = loan();
given(loan.getLoanTransactions()).willReturn(transactions);
JsonCommand command = jsonCommand();
// when
GeneralPlatformDomainRuleException result = assertThrows(GeneralPlatformDomainRuleException.class,
() -> underTest.validateUndoReAge(loan, command));
// then
assertThat(result).isNotNull();
assertThat(result.getGlobalisationMessageCode()).isEqualTo("error.msg.loan.reage.repayment.exists.after.reaging");
}
@Test
public void testValidateUndoReAge_ShouldThrowException_WhenLoanAlreadyHasRepaymentAfterReAge_SameDay() {
// given
List<LoanTransaction> transactions = List.of(loanTransaction(LoanTransactionType.DISBURSEMENT, actualDate.minusDays(2)),
loanTransaction(LoanTransactionType.REAGE, actualDate.minusDays(1),
OffsetDateTime.of(actualDate, LocalTime.of(10, 0), ZoneOffset.UTC)),
loanTransaction(LoanTransactionType.REPAYMENT, actualDate.minusDays(1),
OffsetDateTime.of(actualDate, LocalTime.of(11, 0), ZoneOffset.UTC)));
Loan loan = loan();
given(loan.getLoanTransactions()).willReturn(transactions);
JsonCommand command = jsonCommand();
// when
GeneralPlatformDomainRuleException result = assertThrows(GeneralPlatformDomainRuleException.class,
() -> underTest.validateUndoReAge(loan, command));
// then
assertThat(result).isNotNull();
assertThat(result.getGlobalisationMessageCode()).isEqualTo("error.msg.loan.reage.repayment.exists.after.reaging");
}
@Test
public void testValidateUndoReAge_ShouldNotThrowException_WhenLoanAlreadyHasRepaymentAfterReAge_SameDay_RepaymentBeforeReAge() {
// given