FINERACT-2070: E2E test synchronization 2024-11-22

This commit is contained in:
Peter Kovacs
2024-11-22 14:59:41 +01:00
committed by Adam Saghy
parent ebfc11c041
commit e95b3ff25c
10 changed files with 923 additions and 56 deletions
@@ -52,6 +52,7 @@ public enum DefaultLoanProduct implements LoanProduct {
LP2_DOWNPAYMENT_ADV_PMT_ALLOC_FIXED_LENGTH, //
LP2_DOWNPAYMENT_AUTO_ADVANCED_PAYMENT_ALLOCATION_REPAYMENT_START_SUBMITTED, //
LP2_DOWNPAYMENT_INTEREST_FLAT_ADV_PMT_ALLOC, //
LP2_ADV_PYMNT_INTEREST_RECALCULATION_DAILY_EMI_360_30_MULTIDISBURSE_DOWNPAYMENT, //
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL, //
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_ACCRUAL_ACTIVITY, //
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30, //
@@ -1012,6 +1012,39 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
TestContext.INSTANCE.set(
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION,
responseLoanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefundInterestRecalculation);
// LP2 with progressive loan schedule + horizontal + interest EMI + 360/30 + multidisbursement + downpayment +
// interest recalculation
// 25%, auto disabled
// (LP2_ADV_PYMNT_INTEREST_RECALCULATION_DAILY_EMI_360_30_MULTIDISBURSE_DOWNPAYMENT)
String name49 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_RECALCULATION_DAILY_EMI_360_30_MULTIDISBURSE_DOWNPAYMENT.getName();
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterestRecalculationEmi36030MultiDisburseDownPayment = loanProductsRequestFactory
.defaultLoanProductsRequestLP2Emi()//
.name(name49)//
.enableDownPayment(true)//
.disbursedAmountPercentageForDownPayment(new BigDecimal(25))//
.daysInYearType(DaysInYearType.DAYS360.value)//
.daysInMonthType(DaysInMonthType.DAYS30.value)//
.isInterestRecalculationEnabled(true)//
.preClosureInterestCalculationStrategy(1)//
.rescheduleStrategyMethod(4)//
.interestRecalculationCompoundingMethod(0)//
.recalculationRestFrequencyType(2)//
.recalculationRestFrequencyInterval(1)//
.paymentAllocation(List.of(//
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT"), //
createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT"), //
createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION"), //
createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT")))//
.multiDisburseLoan(true)//
.disallowExpectedDisbursements(true)//
.maxTrancheCount(10)//
.outstandingLoanBalance(10000.0);//
Response<PostLoanProductsResponse> responseLoanProductsRequestLP2AdvancedpaymentInterestRecalculation36030MultiDisburseDownPayment = loanProductsApi
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterestRecalculationEmi36030MultiDisburseDownPayment).execute();
TestContext.INSTANCE.set(
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_RECALCULATION_DAILY_EMI_360_30_MULTIDISBURSE_DOWNPAYMENT,
responseLoanProductsRequestLP2AdvancedpaymentInterestRecalculation36030MultiDisburseDownPayment);
}
public static AdvancedPaymentData createPaymentAllocation(String transactionType, String futureInstallmentAllocationRule,
@@ -18,6 +18,7 @@
*/
package org.apache.fineract.test.messaging.event;
import static org.apache.fineract.test.stepdef.loan.LoanRepaymentStepDef.DATE_FORMAT;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.IOException;
@@ -33,6 +34,7 @@ import org.apache.fineract.avro.loan.v1.LoanAccountDataV1;
import org.apache.fineract.avro.loan.v1.LoanAmountDataV1;
import org.apache.fineract.avro.loan.v1.LoanInstallmentDelinquencyBucketDataV1;
import org.apache.fineract.avro.loan.v1.LoanOwnershipTransferDataV1;
import org.apache.fineract.avro.loan.v1.LoanTransactionAdjustmentDataV1;
import org.apache.fineract.avro.loan.v1.LoanTransactionDataV1;
import org.apache.fineract.client.models.ExternalTransferData;
import org.apache.fineract.client.models.GetClientsClientIdResponse;
@@ -67,6 +69,7 @@ import org.apache.fineract.test.messaging.event.loan.LoanUndoApprovalEvent;
import org.apache.fineract.test.messaging.event.loan.delinquency.LoanDelinquencyPauseChangedEvent;
import org.apache.fineract.test.messaging.event.loan.delinquency.LoanDelinquencyRangeChangeEvent;
import org.apache.fineract.test.messaging.event.loan.transaction.AbstractLoanTransactionEvent;
import org.apache.fineract.test.messaging.event.loan.transaction.LoanAdjustTransactionBusinessEvent;
import org.apache.fineract.test.messaging.event.loan.transaction.LoanDisbursalTransactionEvent;
import org.apache.fineract.test.messaging.event.loan.transaction.LoanRefundPostBusinessEvent;
import org.apache.fineract.test.messaging.event.loan.transaction.LoanTransactionGoodwillCreditPostEvent;
@@ -236,6 +239,31 @@ public class EventCheckHelper {
});
}
public GetLoansLoanIdTransactions getNthTransactionType(String nthItemStr, String transactionType, String transactionDate,
List<GetLoansLoanIdTransactions> transactions) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
int nthItem = Integer.parseInt(nthItemStr) - 1;
GetLoansLoanIdTransactions targetTransaction = transactions//
.stream()//
.filter(t -> transactionDate.equals(formatter.format(t.getDate())) && transactionType.equals(t.getType().getValue()))//
.toList()//
.get(nthItem);//
return targetTransaction;
}
public void checkTransactionWithLoanTransactionAdjustmentBizEvent(GetLoansLoanIdTransactions transaction) {
EventAssertion.EventAssertionBuilder<LoanTransactionAdjustmentDataV1> eventAssertionBuilder = eventAssertion
.assertEvent(LoanAdjustTransactionBusinessEvent.class, transaction.getId());
eventAssertionBuilder
.extractingData(loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getId())
.isEqualTo(transaction.getId());
eventAssertionBuilder
.extractingData(
loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getManuallyReversed())
.isEqualTo(Boolean.TRUE);
eventAssertionBuilder.extractingData(LoanTransactionAdjustmentDataV1::getNewTransactionDetail).isEqualTo(null);
}
private boolean areBigDecimalValuesEqual(BigDecimal actual, BigDecimal expected) {
log.debug("--- Checking BigDecimal values.... ---");
log.debug("Actual: {}", actual);
@@ -390,16 +390,7 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
.adjustLoanTransaction(loanId, targetTransaction.getId(), repaymentUndoRequest, "").execute();
ErrorHelper.checkSuccessfulApiCall(repaymentUndoResponse);
testContext().set(TestContextKey.LOAN_REPAYMENT_UNDO_RESPONSE, repaymentUndoResponse);
EventAssertion.EventAssertionBuilder<LoanTransactionAdjustmentDataV1> eventAssertionBuilder = eventAssertion
.assertEvent(LoanAdjustTransactionBusinessEvent.class, targetTransaction.getId());
eventAssertionBuilder
.extractingData(loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getId())
.isEqualTo(targetTransaction.getId());
eventAssertionBuilder
.extractingData(
loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getManuallyReversed())
.isEqualTo(Boolean.TRUE);
eventAssertionBuilder.extractingData(LoanTransactionAdjustmentDataV1::getNewTransactionDetail).isEqualTo(null);
eventCheckHelper.checkTransactionWithLoanTransactionAdjustmentBizEvent(targetTransaction);
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
}
@@ -423,16 +414,8 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
.adjustLoanTransaction(loanId, targetTransaction.getId(), transactionUndoRequest, "").execute();
ErrorHelper.checkSuccessfulApiCall(transactionUndoResponse);
testContext().set(TestContextKey.LOAN_TRANSACTION_UNDO_RESPONSE, transactionUndoResponse);
EventAssertion.EventAssertionBuilder<LoanTransactionAdjustmentDataV1> eventAssertionBuilder = eventAssertion
.assertEvent(LoanAdjustTransactionBusinessEvent.class, targetTransaction.getId());
eventAssertionBuilder
.extractingData(loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getId())
.isEqualTo(targetTransaction.getId());
eventAssertionBuilder
.extractingData(
loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getManuallyReversed())
.isEqualTo(Boolean.TRUE);
eventAssertionBuilder.extractingData(LoanTransactionAdjustmentDataV1::getNewTransactionDetail).isEqualTo(null);
eventCheckHelper.checkTransactionWithLoanTransactionAdjustmentBizEvent(targetTransaction);
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
}
@@ -459,16 +442,36 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
.adjustLoanTransaction(loanId, targetTransaction.getId(), transactionUndoRequest, "").execute();
ErrorHelper.checkSuccessfulApiCall(transactionUndoResponse);
testContext().set(TestContextKey.LOAN_TRANSACTION_UNDO_RESPONSE, transactionUndoResponse);
EventAssertion.EventAssertionBuilder<LoanTransactionAdjustmentDataV1> eventAssertionBuilder = eventAssertion
.assertEvent(LoanAdjustTransactionBusinessEvent.class, targetTransaction.getId());
eventAssertionBuilder
.extractingData(loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getId())
.isEqualTo(targetTransaction.getId());
eventAssertionBuilder
.extractingData(
loanTransactionAdjustmentDataV1 -> loanTransactionAdjustmentDataV1.getTransactionToAdjust().getManuallyReversed())
.isEqualTo(Boolean.TRUE);
eventAssertionBuilder.extractingData(LoanTransactionAdjustmentDataV1::getNewTransactionDetail).isEqualTo(null);
eventCheckHelper.checkTransactionWithLoanTransactionAdjustmentBizEvent(targetTransaction);
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
}
@When("Customer undo {string}th {string} transaction made on {string} with linked {string} transaction")
public void checkNthTransactionType(String nthItemStr, String transactionType, String transactionDate, String linkedTransactionType)
throws IOException {
eventStore.reset();
Response<PostLoansResponse> loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
long loanId = loanResponse.body().getLoanId();
List<GetLoansLoanIdTransactions> transactions = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute().body()
.getTransactions();
// check that here are 2 transactions - target and linked
assertThat(transactions.size()).isGreaterThanOrEqualTo(2);
GetLoansLoanIdTransactions targetTransaction = eventCheckHelper.getNthTransactionType(nthItemStr, transactionType, transactionDate,
transactions);
PostLoansLoanIdTransactionsTransactionIdRequest transactionUndoRequest = LoanRequestFactory.defaultTransactionUndoRequest()
.transactionDate(transactionDate);
Response<PostLoansLoanIdTransactionsResponse> transactionUndoResponse = loanTransactionsApi
.adjustLoanTransaction(loanId, targetTransaction.getId(), transactionUndoRequest, "").execute();
ErrorHelper.checkSuccessfulApiCall(transactionUndoResponse);
testContext().set(TestContextKey.LOAN_TRANSACTION_UNDO_RESPONSE, transactionUndoResponse);
eventCheckHelper.checkTransactionWithLoanTransactionAdjustmentBizEvent(targetTransaction);
// linked transaction
GetLoansLoanIdTransactions linkedTargetTransaction = eventCheckHelper.getNthTransactionType(nthItemStr, linkedTransactionType,
transactionDate, transactions);
eventCheckHelper.checkTransactionWithLoanTransactionAdjustmentBizEvent(linkedTargetTransaction);
eventCheckHelper.loanBalanceChangedEventCheck(loanId);
}
@@ -482,7 +485,6 @@ public class LoanRepaymentStepDef extends AbstractStepDef {
ErrorHelper.checkSuccessfulApiCall(transactionResponse);
assertThat(transactionResponse.body().getAmount()).isEqualTo(repaymentAmount);
assertThat(transactionResponse.body().getPaymentDetailData().getPaymentType().getName()).isEqualTo(paymentType);
}
@Then("Repayment failed because the repayment date is after the business date")
@@ -408,7 +408,7 @@ public class LoanStepDef extends AbstractStepDef {
}
@When("Admin creates a fully customized loan with interestRateFrequencyType and following data:")
public void createFullyCustomizedLoanWithinterestRateFrequencyType(final DataTable table) throws IOException {
public void createFullyCustomizedLoanWithInterestRateFrequencyType(final DataTable table) throws IOException {
final List<List<String>> data = table.asLists();
createFullyCustomizedLoanWithInterestRateFrequency(data.get(1));
}
@@ -2725,15 +2725,26 @@ public class LoanStepDef extends AbstractStepDef {
InterestRateFrequencyType interestRateFrequencyType = InterestRateFrequencyType.valueOf(interestRateFrequencyTypeStr);
Integer interestRateFrequencyTypeValue = interestRateFrequencyType.value;
final PostLoansRequest loansRequest = loanRequestFactory.defaultLoansRequest(clientId).productId(loanProductId)
.principal(new BigDecimal(principal)).interestRatePerPeriod(interestRate).interestType(interestTypeValue)
.interestCalculationPeriodType(interestCalculationPeriodValue).amortizationType(amortizationTypeValue)
.loanTermFrequency(loanTermFrequency).loanTermFrequencyType(loanTermFrequencyTypeValue)
.numberOfRepayments(numberOfRepayments).repaymentEvery(repaymentFrequency)
.repaymentFrequencyType(repaymentFrequencyTypeValue).submittedOnDate(submitDate).expectedDisbursementDate(submitDate)
.graceOnPrincipalPayment(graceOnPrincipalPayment).graceOnInterestPayment(graceOnInterestPayment)
.graceOnInterestPayment(graceOnInterestCharged).transactionProcessingStrategyCode(transactionProcessingStrategyCodeValue)
.interestRateFrequencyType(interestRateFrequencyTypeValue);
final PostLoansRequest loansRequest = loanRequestFactory//
.defaultLoansRequest(clientId)//
.productId(loanProductId)//
.principal(new BigDecimal(principal))//
.interestRatePerPeriod(interestRate)//
.interestType(interestTypeValue)//
.interestCalculationPeriodType(interestCalculationPeriodValue)//
.amortizationType(amortizationTypeValue)//
.loanTermFrequency(loanTermFrequency)//
.loanTermFrequencyType(loanTermFrequencyTypeValue)//
.numberOfRepayments(numberOfRepayments)//
.repaymentEvery(repaymentFrequency)//
.repaymentFrequencyType(repaymentFrequencyTypeValue)//
.submittedOnDate(submitDate)//
.expectedDisbursementDate(submitDate)//
.graceOnPrincipalPayment(graceOnPrincipalPayment)//
.graceOnInterestPayment(graceOnInterestPayment)//
.graceOnInterestPayment(graceOnInterestCharged)//
.transactionProcessingStrategyCode(transactionProcessingStrategyCodeValue)//
.interestRateFrequencyType(interestRateFrequencyTypeValue);//
final Response<PostLoansResponse> response = loansApi.calculateLoanScheduleOrSubmitLoanApplication(loansRequest, "").execute();
testContext().set(TestContextKey.LOAN_CREATE_RESPONSE, response);
@@ -85,6 +85,7 @@ public abstract class TestContextKey {
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_DOWNPAYMENT_ADV_PMT_ALLOC_PROG_SCHEDULE_HOR_INST_LVL_DELINQUENCY_CREDIT_ALLOCATION = "loanProductCreateResponseLP2DownPaymentProgressiveLoanScheduleHorizontalInstallmentLevelDelinquencyCreditAllocation";
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_DOWNPAYMENT_ADV_PMT_ALLOC_FIXED_LENGTH = "loanProductCreateResponseLP2DownPaymentProgressiveLoanScheduleFixedLength";
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_DOWNPAYMENT_INTEREST_FLAT_ADV_PMT_ALLOC = "loanProductCreateResponseLP2DownPaymentInterestFlatAdvancedPaymentAllocation";
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_RECALCULATION_DAILY_EMI_360_30_MULTIDISBURSE_DOWNPAYMENT = "loanProductCreateResponseLP2AdvancedPaymentInterestRecalculationDailyEmi36030MultiDisburseDownPayment";
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmiActualActual";
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_ACCRUAL_ACTIVITY = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmiActualActualAccrualActivity";
public static final String DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30 = "loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030";