Skip to content

Commit a58db39

Browse files
MarianaDmytrivBinariksgalovics
authored andcommitted
FINERACT-2326: added e2e auto tests for accrual reversal logic issue
1 parent 469489d commit a58db39

File tree

6 files changed

+961
-74
lines changed

6 files changed

+961
-74
lines changed

fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/GlobalConfigurationStepDef.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,6 @@ public void updateCurrencyEmptyValueFailure() throws IOException {
7878
assertThat(errorDetails.getSingleError().getDeveloperMessage()).isEqualTo(ErrorMessageHelper.setCurrencyEmptyValueFailure());
7979
}
8080

81-
@When("Update currency with incorrect null value outcomes with an error")
82-
public void updateCurrencyIncorrectNullValueFailure() throws IOException {
83-
var request = new CurrencyUpdateRequest();
84-
var currencyResponse = currencyApi.updateCurrencies(request.currencies(Collections.singletonList(null))).execute();
85-
final ErrorResponse errorDetails = ErrorResponse.from(currencyResponse);
86-
assertThat(errorDetails.getHttpStatusCode()).as(ErrorMessageHelper.setCurrencyIncorrectValueFailure("null")).isEqualTo(404);
87-
assertThat(errorDetails.getSingleError().getDeveloperMessage())
88-
.isEqualTo(ErrorMessageHelper.setCurrencyIncorrectValueFailure("null"));
89-
}
90-
9181
@When("Update currency as NULL value outcomes with an error")
9282
public void updateCurrencyNullValueFailure() throws IOException {
9383
var request = new CurrencyUpdateRequest();

fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java

Lines changed: 86 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import org.apache.fineract.avro.loan.v1.LoanAccountDataV1;
6161
import org.apache.fineract.avro.loan.v1.LoanChargePaidByDataV1;
6262
import org.apache.fineract.avro.loan.v1.LoanStatusEnumDataV1;
63+
import org.apache.fineract.avro.loan.v1.LoanTransactionAdjustmentDataV1;
6364
import org.apache.fineract.avro.loan.v1.LoanTransactionDataV1;
6465
import org.apache.fineract.client.models.AdvancedPaymentData;
6566
import org.apache.fineract.client.models.AmortizationMappingData;
@@ -2424,12 +2425,17 @@ public void loanTransactionsHaveNonNullExternalId() throws IOException {
24242425
.as(ErrorMessageHelper.transactionHasNullResourceValue("", "external-id")).isTrue();
24252426
}
24262427

2427-
@Then("Check required transaction for non-null eternal-id")
2428-
public void loanTransactionHasNonNullExternalId() throws IOException {
2428+
@Then("Check required {string}th transaction for non-null eternal-id")
2429+
public void loanTransactionHasNonNullExternalId(String nThNumber) throws IOException {
24292430
Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
24302431
long loanId = loanCreateResponse.body().getLoanId();
24312432

2432-
GetLoansLoanIdTransactions targetTransaction = testContext().get(TestContextKey.LOAN_TRANSACTION_RESPONSE);
2433+
GetLoansLoanIdTransactions targetTransaction;
2434+
if (nThNumber.equals("1")) {
2435+
targetTransaction = testContext().get(TestContextKey.LOAN_TRANSACTION_RESPONSE);
2436+
} else {
2437+
targetTransaction = testContext().get(TestContextKey.LOAN_SECOND_TRANSACTION_RESPONSE);
2438+
}
24332439
Long targetTransactionId = targetTransaction.getId();
24342440

24352441
Response<GetLoansLoanIdTransactionsTransactionIdResponse> transactionResponse = loanTransactionsApi
@@ -2890,11 +2896,11 @@ public void checkLoanChargeAdjustmentPostBusinessEvent(String date) throws IOExc
28902896

28912897
List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
28922898

2893-
GetLoansLoanIdTransactions loadTransaction = transactions.stream()
2899+
GetLoansLoanIdTransactions loanTransaction = transactions.stream()
28942900
.filter(t -> date.equals(FORMATTER.format(t.getDate())) && "Charge Adjustment".equals(t.getType().getValue())).findFirst()
28952901
.orElseThrow(() -> new IllegalStateException(String.format("No Charge Adjustment transaction found on %s", date)));
28962902

2897-
eventAssertion.assertEventRaised(LoanChargeAdjustmentPostBusinessEvent.class, loadTransaction.getId());
2903+
eventAssertion.assertEventRaised(LoanChargeAdjustmentPostBusinessEvent.class, loanTransaction.getId());
28982904
}
28992905

29002906
@Then("BulkBusinessEvent is not raised on {string}")
@@ -2919,9 +2925,7 @@ public void checkLoanAccrualTransactionNotCreatedBusinessEvent(String date) thro
29192925
em -> FORMATTER.format(em.getBusinessDate()).equals(date));
29202926
}
29212927

2922-
@Then("{string} transaction on {string} got reverse-replayed on {string}")
2923-
public void checkLoanAdjustTransactionBusinessEvent(String transactionType, String transactionDate, String submittedOnDate)
2924-
throws IOException {
2928+
public GetLoansLoanIdTransactions getLoanTransactionIdByDate(String transactionType, String transactionDate) throws IOException {
29252929
Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
29262930
long loanId = loanCreateResponse.body().getLoanId();
29272931

@@ -2930,41 +2934,96 @@ public void checkLoanAdjustTransactionBusinessEvent(String transactionType, Stri
29302934

29312935
List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
29322936

2933-
GetLoansLoanIdTransactions loadTransaction = transactions.stream()
2937+
GetLoansLoanIdTransactions loanTransaction = transactions.stream()
29342938
.filter(t -> transactionDate.equals(FORMATTER.format(t.getDate())) && transactionType.equals(t.getType().getValue()))
29352939
.findFirst().orElseThrow(
29362940
() -> new IllegalStateException(String.format("No %s transaction found on %s", transactionType, transactionDate)));
2941+
return loanTransaction;
2942+
}
2943+
2944+
public GetLoansLoanIdTransactionsTransactionIdResponse getLoanTransactionIdById(Long transactionId) throws IOException {
2945+
Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
2946+
long loanId = loanCreateResponse.body().getLoanId();
2947+
2948+
Response<GetLoansLoanIdTransactionsTransactionIdResponse> loanTransactionResponse = loanTransactionsApi
2949+
.retrieveTransaction(loanId, transactionId, "").execute();
2950+
GetLoansLoanIdTransactionsTransactionIdResponse loanTransaction = loanTransactionResponse.body();
2951+
return loanTransaction;
2952+
}
29372953

2938-
Set<GetLoansLoanIdLoanTransactionRelation> transactionRelations = loadTransaction.getTransactionRelations();
2954+
@Then("{string} transaction on {string} got reverse-replayed on {string}")
2955+
public void checkLoanAdjustTransactionBusinessEvent(String transactionType, String transactionDate, String submittedOnDate)
2956+
throws IOException {
2957+
GetLoansLoanIdTransactions loanTransaction = getLoanTransactionIdByDate(transactionType, transactionDate);
2958+
2959+
Set<GetLoansLoanIdLoanTransactionRelation> transactionRelations = loanTransaction.getTransactionRelations();
29392960
Long originalTransactionId = transactionRelations.stream().map(GetLoansLoanIdLoanTransactionRelation::getToLoanTransaction)
29402961
.filter(Objects::nonNull).findFirst()
29412962
.orElseThrow(() -> new IllegalStateException("Transaction was reversed, but not replayed!"));
29422963

29432964
// Check whether reverse-replay event got occurred
2944-
eventAssertion.assertEvent(LoanAdjustTransactionBusinessEvent.class, originalTransactionId).extractingData(
2945-
e -> e.getNewTransactionDetail() != null && e.getNewTransactionDetail().getId().equals(loadTransaction.getId()));
2965+
eventAssertion.assertEvent(LoanAdjustTransactionBusinessEvent.class, originalTransactionId)
2966+
.extractingData(LoanTransactionAdjustmentDataV1::getNewTransactionDetail).isNotEqualTo(null)
2967+
.extractingData(e -> e.getNewTransactionDetail().getId()).isEqualTo(loanTransaction.getId());
29462968
// Check whether there was just ONE event related to this transaction
29472969
eventAssertion.assertEventNotRaised(LoanAdjustTransactionBusinessEvent.class, originalTransactionId);
2948-
assertThat(FORMATTER.format(loadTransaction.getSubmittedOnDate()))
2949-
.as("Loan got replayed on %s", loadTransaction.getSubmittedOnDate()).isEqualTo(submittedOnDate);
2970+
assertThat(FORMATTER.format(loanTransaction.getSubmittedOnDate()))
2971+
.as("Loan got replayed on %s", loanTransaction.getSubmittedOnDate()).isEqualTo(submittedOnDate);
29502972
}
29512973

2952-
@When("Save external ID of {string} transaction made on {string} as {string}")
2953-
public void saveExternalIdForTransaction(String transactionName, String transactionDate, String externalIdKey) throws IOException {
2954-
Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
2955-
long loanId = loanCreateResponse.body().getLoanId();
2974+
@Then("Store {string} transaction created on {string} date as {string}th transaction")
2975+
public void storeLoanTransactionId(String transactionType, String transactionDate, String nthTrnOrderNumber) throws IOException {
2976+
GetLoansLoanIdTransactions loanTransaction = getLoanTransactionIdByDate(transactionType, transactionDate);
2977+
if (nthTrnOrderNumber.equals("1")) {
2978+
testContext().set(TestContextKey.LOAN_TRANSACTION_RESPONSE, loanTransaction);
2979+
} else {
2980+
testContext().set(TestContextKey.LOAN_SECOND_TRANSACTION_RESPONSE, loanTransaction);
2981+
}
2982+
}
29562983

2957-
Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
2958-
ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
2984+
@Then("LoanAdjustTransactionBusinessEvent is raised with transaction got reversed on {string}")
2985+
public void checkLoanAdjustTransactionBusinessEventWithReversedTrn(String submittedOnDate) throws IOException {
2986+
GetLoansLoanIdTransactions originalTransaction = testContext().get(TestContextKey.LOAN_TRANSACTION_RESPONSE);
2987+
Long originalTransactionId = originalTransaction.getId();
2988+
GetLoansLoanIdTransactionsTransactionIdResponse loanTransaction = getLoanTransactionIdById(originalTransactionId);
29592989

2960-
List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
2990+
// Check whether reversed event got occurred
2991+
eventAssertion.assertEvent(LoanAdjustTransactionBusinessEvent.class, originalTransactionId)
2992+
.extractingData(LoanTransactionAdjustmentDataV1::getNewTransactionDetail).isEqualTo(null)
2993+
.extractingData(e -> e.getTransactionToAdjust().getId()).isEqualTo(originalTransactionId);
2994+
// Check whether there was just ONE event related to this transaction
2995+
eventAssertion.assertEventNotRaised(LoanAdjustTransactionBusinessEvent.class, originalTransactionId);
2996+
assertThat(FORMATTER.format(loanTransaction.getReversedOnDate())).as("Loan got replayed on %s", loanTransaction.getReversedOnDate())
2997+
.isEqualTo(submittedOnDate);
2998+
}
29612999

2962-
GetLoansLoanIdTransactions loadTransaction = transactions.stream()
2963-
.filter(t -> transactionDate.equals(FORMATTER.format(t.getDate())) && transactionName.equals(t.getType().getValue()))
2964-
.findFirst().orElseThrow(
2965-
() -> new IllegalStateException(String.format("No %s transaction found on %s", transactionName, transactionDate)));
3000+
@Then("LoanAdjustTransactionBusinessEvent is raised with transaction on {string} got reversed on {string}")
3001+
public void checkLoanAdjustTransactionBusinessEventWithReversedTrn(String transactionDate, String submittedOnDate) throws IOException {
3002+
Long originalTransactionId;
3003+
GetLoansLoanIdTransactions loanTransaction1 = testContext().get(TestContextKey.LOAN_TRANSACTION_RESPONSE);
3004+
GetLoansLoanIdTransactions loanTransaction2 = testContext().get(TestContextKey.LOAN_SECOND_TRANSACTION_RESPONSE);
3005+
if (FORMATTER.format(loanTransaction1.getDate()).equals(transactionDate)) {
3006+
originalTransactionId = loanTransaction1.getId();
3007+
} else {
3008+
originalTransactionId = loanTransaction2.getId();
3009+
}
3010+
GetLoansLoanIdTransactionsTransactionIdResponse loanTransaction = getLoanTransactionIdById(originalTransactionId);
3011+
3012+
// Check whether reversedevent got occurred
3013+
eventAssertion.assertEvent(LoanAdjustTransactionBusinessEvent.class, originalTransactionId)
3014+
.extractingData(e -> e.getTransactionToAdjust().getId()).isEqualTo(originalTransactionId)
3015+
.extractingData(LoanTransactionAdjustmentDataV1::getNewTransactionDetail).isEqualTo(null);
3016+
// Check whether there was just ONE event related to this transaction
3017+
eventAssertion.assertEventNotRaised(LoanAdjustTransactionBusinessEvent.class, originalTransactionId);
3018+
assertThat(FORMATTER.format(loanTransaction.getReversedOnDate())).as("Loan got replayed on %s", loanTransaction.getReversedOnDate())
3019+
.isEqualTo(submittedOnDate);
3020+
}
29663021

2967-
String externalId = loadTransaction.getExternalId();
3022+
@When("Save external ID of {string} transaction made on {string} as {string}")
3023+
public void saveExternalIdForTransaction(String transactionName, String transactionDate, String externalIdKey) throws IOException {
3024+
GetLoansLoanIdTransactions loanTransaction = getLoanTransactionIdByDate(transactionName, transactionDate);
3025+
3026+
String externalId = loanTransaction.getExternalId();
29683027
testContext().set(externalIdKey, externalId);
29693028
log.debug("Transaction external ID: {} saved to testContext", externalId);
29703029
}
@@ -2975,15 +3034,7 @@ public void checkExternalIdForReplayedAccrualActivity(String transactionType, St
29753034
Response<PostLoansResponse> loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
29763035
long loanId = loanCreateResponse.body().getLoanId();
29773036

2978-
Response<GetLoansLoanIdResponse> loanDetailsResponse = loansApi.retrieveLoan(loanId, false, "transactions", "", "").execute();
2979-
ErrorHelper.checkSuccessfulApiCall(loanDetailsResponse);
2980-
2981-
List<GetLoansLoanIdTransactions> transactions = loanDetailsResponse.body().getTransactions();
2982-
2983-
GetLoansLoanIdTransactions transactionDetails = transactions.stream()
2984-
.filter(t -> transactionDate.equals(FORMATTER.format(t.getDate())) && transactionType.equals(t.getType().getValue()))
2985-
.findFirst().orElseThrow(
2986-
() -> new IllegalStateException(String.format("No %s transaction found on %s", transactionType, transactionDate)));
3037+
GetLoansLoanIdTransactions transactionDetails = getLoanTransactionIdByDate(transactionType, transactionDate);
29873038

29883039
Set<GetLoansLoanIdLoanTransactionRelation> transactionRelations = transactionDetails.getTransactionRelations();
29893040
Long originalTransactionId = transactionRelations.stream().map(GetLoansLoanIdLoanTransactionRelation::getToLoanTransaction)

fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ public abstract class TestContextKey {
245245
public static final String LOAN_WRITE_OFF_RESPONSE = "loanWriteOffResponse";
246246
public static final String LOAN_DELINQUENCY_ACTION_RESPONSE = "loanDelinquencyActionResponse";
247247
public static final String LOAN_TRANSACTION_RESPONSE = "loanTransactionResponse";
248+
public static final String LOAN_SECOND_TRANSACTION_RESPONSE = "loanSecondTransactionResponse";
248249
public static final String LOAN_CAPITALIZED_INCOME_RESPONSE = "loanCapitalizedIncomeResponse";
249250
public static final String LOAN_DISBURSEMENT_DETAIL_RESPONSE = "loanDisbursementDetailResponse";
250251
public static final String LOAN_CAPITALIZED_INCOME_AMORTIZATION_ID = "loanCapitalizedIncomeAmortizationId";

fineract-e2e-tests-runner/src/test/resources/features/BusinessDate.feature

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,27 +27,23 @@ Feature: BusinessDate
2727
When Admin runs the Increase Business Date by 1 day job
2828
Then Admin checks that the business date is correctly set to "11 July 2022"
2929

30-
@TestRailId:C3953
31-
Scenario: Verify set incorrect business date with empty value handled correct with accordance error message - UC1
32-
When Set incorrect business date with empty value "null" outcomes with an error
33-
3430
@TestRailId:C3954
35-
Scenario: Verify set incorrect business date with null value handled correct with accordance error message - UC2
36-
When Set incorrect business date with empty value "" outcomes with an error
37-
38-
@TestRailId:C3955
39-
Scenario: Verify set incorrect business date value handled correct with accordance error message - UC3
40-
When Set incorrect business date value "15" outcomes with an error
41-
42-
@TestRailId:C3956
43-
Scenario: Verify set incorrect business date value handled correct with accordance error message - UC4
44-
When Set incorrect business date value "11 15 2025" outcomes with an error
31+
Scenario Outline: Verify set incorrect business date with null or empty value handled correct with accordance error message - UC1
32+
When Set incorrect business date with empty value <empty_biz_date_value> outcomes with an error
4533

46-
@TestRailId:C_3957
47-
Scenario: Verify set incorrect business date value handled correct with accordance error message - UC5
48-
When Set incorrect business date value "August 12 2025" outcomes with an error
34+
Examples:
35+
| empty_biz_date_value |
36+
| "" |
37+
| "null" |
4938

5039
@TestRailId:C3958
51-
Scenario: Verify set incorrect business date value handled correct with accordance error message - UC6
52-
When Set incorrect business date value "33 August 2025" outcomes with an error
40+
Scenario Outline: Verify set incorrect business date value handled correct with accordance error message - UC2
41+
When Set incorrect business date value "<incorrect_biz_date_value>" outcomes with an error
42+
43+
Examples:
44+
| incorrect_biz_date_value |
45+
| 33 August 2025 |
46+
| August 12 2025 |
47+
| 11 15 2025 |
48+
| 15 |
5349

fineract-e2e-tests-runner/src/test/resources/features/Configuration.feature

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ Feature: Configuration
55
Scenario: Verify update currency with empty value handled correct with accordance error message - UC1
66
When Update currency with incorrect empty value outcomes with an error
77

8-
@TestRailId:C3960
9-
Scenario: Verify update currency with null value handled correct with accordance error message - UC2
10-
When Update currency with incorrect null value outcomes with an error
11-
128
@TestRailId:C3961
13-
Scenario: Verify update currency as NULL value handled correct with accordance error message - UC3
9+
Scenario: Verify update currency as NULL value handled correct with accordance error message - UC2
1410
When Update currency as NULL value outcomes with an error
1511

1612
@TestRailId:C3962
17-
Scenario: Verify update currency with incorrect value handled correct with accordance error message - UC4
18-
When Update currency as "string" value outcomes with an error
13+
Scenario Outline: Verify update currency with incorrect/null value handled correct with accordance error message - UC3
14+
When Update currency as <incorrect_config_value> value outcomes with an error
15+
16+
Examples:
17+
| incorrect_config_value |
18+
| "string" |
19+
| "null" |

0 commit comments

Comments
 (0)