FINERACT-2413: Improve re-amortization undo validation
This commit is contained in:
committed by
Arnold Gálovics
parent
b457b2aa93
commit
2858316c71
+1
-13
@@ -115,16 +115,12 @@ public class LoanReAmortizationService {
|
||||
|
||||
public CommandProcessingResult undoReAmortize(Long loanId, JsonCommand command) {
|
||||
Loan loan = loanAssembler.assembleFrom(loanId);
|
||||
reAmortizationValidator.validateUndoReAmortize(loan, command);
|
||||
final LoanTransaction reAmortizeTransaction = reAmortizationValidator.findAndValidateReAmortizeTransactionForUndo(loan);
|
||||
|
||||
Map<String, Object> changes = new LinkedHashMap<>();
|
||||
changes.put(LoanReAmortizationApiConstants.localeParameterName, command.locale());
|
||||
changes.put(LoanReAmortizationApiConstants.dateFormatParameterName, command.dateFormat());
|
||||
|
||||
LoanTransaction reAmortizeTransaction = findLatestNonReversedReAmortizeTransaction(loan);
|
||||
if (reAmortizeTransaction == null) {
|
||||
// TODO: when validations implemented; throw exception if there isn't a reamortize transaction available
|
||||
}
|
||||
if (loan.isProgressiveSchedule()) {
|
||||
loanScheduleService.regenerateRepaymentSchedule(loan);
|
||||
}
|
||||
@@ -185,14 +181,6 @@ public class LoanReAmortizationService {
|
||||
reprocessLoanTransactionsService.reprocessTransactions(loan);
|
||||
}
|
||||
|
||||
private LoanTransaction findLatestNonReversedReAmortizeTransaction(Loan loan) {
|
||||
return loan.getLoanTransactions().stream() //
|
||||
.filter(LoanTransaction::isNotReversed) //
|
||||
.filter(LoanTransaction::isReAmortize) //
|
||||
.max(Comparator.comparing(LoanTransaction::getTransactionDate)) //
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private LoanTransaction createReAmortizeTransaction(Loan loan, JsonCommand command) {
|
||||
ExternalId txExternalId = externalIdFactory.createFromCommand(command, LoanReAmortizationApiConstants.externalIdParameterName);
|
||||
|
||||
|
||||
+8
-21
@@ -21,7 +21,6 @@ package org.apache.fineract.portfolio.loanaccount.service.reamortization;
|
||||
import static org.apache.fineract.infrastructure.core.service.DateUtils.getBusinessLocalDate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -39,7 +38,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.reamortization.LoanReAmortizationInterestHandlingType;
|
||||
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;
|
||||
|
||||
@@ -123,26 +121,18 @@ public class LoanReAmortizationValidator {
|
||||
}
|
||||
}
|
||||
|
||||
public void validateUndoReAmortize(Loan loan, JsonCommand command) {
|
||||
validateUndoReAmortizeBusinessRules(loan);
|
||||
}
|
||||
|
||||
private void validateUndoReAmortizeBusinessRules(Loan loan) {
|
||||
// validate if there's a reamortization transaction already
|
||||
Optional<LoanTransaction> optionalReAmortizationTx = loan.getLoanTransactions().stream().filter(tx -> tx.getTypeOf().isReAmortize())
|
||||
.min(Comparator.comparing(LoanTransaction::getTransactionDate));
|
||||
public LoanTransaction findAndValidateReAmortizeTransactionForUndo(Loan loan) {
|
||||
// validate if there's a non-reversed reamortization transaction already
|
||||
final Optional<LoanTransaction> optionalReAmortizationTx = loan.getLoanTransactions().stream() //
|
||||
.filter(LoanTransaction::isNotReversed) //
|
||||
.filter(tx -> tx.getTypeOf().isReAmortize()) //
|
||||
.findAny();
|
||||
if (optionalReAmortizationTx.isEmpty()) {
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.loan.reamortize.reamortization.transaction.missing",
|
||||
"Undoing a reamortization can only be done if there was a reamortization already", loan.getId());
|
||||
"Undoing a reamortization can only be done if there was a non-reversed reamortization already", loan.getId());
|
||||
}
|
||||
|
||||
// validate if there's no payment between the reamortization and today
|
||||
boolean repaymentExistsAfterReAmortization = loan.getLoanTransactions().stream().anyMatch(tx -> tx.getTypeOf().isRepaymentType()
|
||||
&& !tx.isReversed() && transactionHappenedAfterOther(tx, optionalReAmortizationTx.get()));
|
||||
if (repaymentExistsAfterReAmortization) {
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.loan.reamortize.repayment.exists.after.reamortization",
|
||||
"Undoing a reamortization can only be done if there hasn't been any repayment afterwards", loan.getId());
|
||||
}
|
||||
return optionalReAmortizationTx.get();
|
||||
}
|
||||
|
||||
private void throwExceptionIfValidationErrorsExist(List<ApiParameterError> dataValidationErrors) {
|
||||
@@ -152,7 +142,4 @@ public class LoanReAmortizationValidator {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean transactionHappenedAfterOther(LoanTransaction transaction, LoanTransaction otherTransaction) {
|
||||
return new ChangeOperation(transaction).compareTo(new ChangeOperation(otherTransaction)) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-41
@@ -185,53 +185,16 @@ class LoanReAmortizationValidatorTest {
|
||||
List<LoanTransaction> transactions = List.of(loanTransaction(LoanTransactionType.DISBURSEMENT, actualDate.minusDays(3)));
|
||||
Loan loan = loan();
|
||||
given(loan.getLoanTransactions()).willReturn(transactions);
|
||||
JsonCommand command = jsonCommand();
|
||||
// when
|
||||
GeneralPlatformDomainRuleException result = assertThrows(GeneralPlatformDomainRuleException.class,
|
||||
() -> underTest.validateUndoReAmortize(loan, command));
|
||||
() -> underTest.findAndValidateReAmortizeTransactionForUndo(loan));
|
||||
// then
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getGlobalisationMessageCode()).isEqualTo("error.msg.loan.reamortize.reamortization.transaction.missing");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateUndoReAmortize_ShouldThrowException_WhenLoanAlreadyHasRepaymentAfterReAmortization() {
|
||||
// given
|
||||
List<LoanTransaction> transactions = List.of(loanTransaction(LoanTransactionType.DISBURSEMENT, actualDate.minusDays(3)),
|
||||
loanTransaction(LoanTransactionType.REAMORTIZE, 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.validateUndoReAmortize(loan, command));
|
||||
// then
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getGlobalisationMessageCode()).isEqualTo("error.msg.loan.reamortize.repayment.exists.after.reamortization");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateUndoReAmortize_ShouldThrowException_WhenLoanAlreadyHasRepaymentAfterReAmortization_SameDay() {
|
||||
// given
|
||||
List<LoanTransaction> transactions = List.of(loanTransaction(LoanTransactionType.DISBURSEMENT, actualDate.minusDays(2)),
|
||||
loanTransaction(LoanTransactionType.REAMORTIZE, 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.validateUndoReAmortize(loan, command));
|
||||
// then
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result.getGlobalisationMessageCode()).isEqualTo("error.msg.loan.reamortize.repayment.exists.after.reamortization");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateUndoReAmortize_ShouldNotThrowException_WhenLoanAlreadyHasRepaymentAfterReAmortization_SameDay_RepaymentBeforeReAmortization() {
|
||||
public void testValidateUndoReAmortize_ShouldNotThrowException() {
|
||||
// given
|
||||
List<LoanTransaction> transactions = List.of(loanTransaction(LoanTransactionType.DISBURSEMENT, actualDate.minusDays(2)),
|
||||
loanTransaction(LoanTransactionType.REAMORTIZE, actualDate.minusDays(1),
|
||||
@@ -240,9 +203,8 @@ class LoanReAmortizationValidatorTest {
|
||||
OffsetDateTime.of(actualDate, LocalTime.of(9, 0), ZoneOffset.UTC)));
|
||||
Loan loan = loan();
|
||||
given(loan.getLoanTransactions()).willReturn(transactions);
|
||||
JsonCommand command = jsonCommand();
|
||||
// when
|
||||
underTest.validateUndoReAmortize(loan, command);
|
||||
underTest.findAndValidateReAmortizeTransactionForUndo(loan);
|
||||
// then no exception thrown
|
||||
}
|
||||
|
||||
@@ -271,6 +233,7 @@ class LoanReAmortizationValidatorTest {
|
||||
given(loanTransaction.getTypeOf()).willReturn(type);
|
||||
given(loanTransaction.getTransactionDate()).willReturn(txDate);
|
||||
given(loanTransaction.getSubmittedOnDate()).willReturn(txDate);
|
||||
given(loanTransaction.isNotReversed()).willReturn(true);
|
||||
return loanTransaction;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user