Skip to content

Commit 8f0870d

Browse files
FINERACT-2418: Extend disbursal and reage events with changed terms flag
1 parent 6269cbb commit 8f0870d

File tree

16 files changed

+277
-8
lines changed

16 files changed

+277
-8
lines changed

fineract-avro-schemas/src/main/avro/loan/v1/LoanTransactionDataV1.avsc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,15 @@
283283
"items": "org.apache.fineract.avro.loan.v1.OriginatorDetailsV1"
284284
}
285285
]
286+
},
287+
{
288+
"default": null,
289+
"name": "flags",
290+
"doc": "Optional flags associated with this transaction event",
291+
"type": [
292+
"null",
293+
"org.apache.fineract.avro.loan.v1.LoanTransactionFlagsDataV1"
294+
]
286295
}
287296
]
288297
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "LoanTransactionFlagsDataV1",
3+
"namespace": "org.apache.fineract.avro.loan.v1",
4+
"doc": "Optional flags associated with a loan transaction event",
5+
"type": "record",
6+
"fields": [{
7+
"default": null,
8+
"name": "changedTerms",
9+
"doc": "True if the transaction changed the number of loan repayment terms (installments excluding downpayment and additional)",
10+
"type": [
11+
"null",
12+
"boolean"
13+
]
14+
}]
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.test.messaging.event.loan.transaction;
20+
21+
public class LoanReAgeTransactionEvent extends AbstractLoanTransactionEvent {
22+
23+
@Override
24+
public String getEventName() {
25+
return "LoanReAgeTransactionBusinessEvent";
26+
}
27+
28+
}

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import java.util.stream.Collectors;
3838
import lombok.RequiredArgsConstructor;
3939
import lombok.extern.slf4j.Slf4j;
40+
import org.apache.fineract.avro.loan.v1.LoanTransactionFlagsDataV1;
4041
import org.apache.fineract.client.feign.FineractFeignClient;
4142
import org.apache.fineract.client.feign.util.CallFailedRuntimeException;
4243
import org.apache.fineract.client.models.LoanScheduleData;
@@ -49,6 +50,7 @@
4950
import org.apache.fineract.test.helper.Utils;
5051
import org.apache.fineract.test.messaging.EventAssertion;
5152
import org.apache.fineract.test.messaging.event.loan.LoanReAgeEvent;
53+
import org.apache.fineract.test.messaging.event.loan.transaction.LoanReAgeTransactionEvent;
5254
import org.apache.fineract.test.stepdef.AbstractStepDef;
5355
import org.apache.fineract.test.support.TestContextKey;
5456
import org.junit.jupiter.api.Assertions;
@@ -414,4 +416,20 @@ public void checkCreateLoanReAgeFailure(DataTable table, String errorMessage) {
414416
assertThat(exception.getDeveloperMessage()).contains(errorMessage);
415417
}
416418

419+
@Then("LoanReAgeTransactionBusinessEvent has changedTerms {string}")
420+
public void checkReAgeTransactionEventChangedTerms(final String expectedChangedTerms) {
421+
final PostLoansLoanIdTransactionsResponse reAgingResponse = testContext().get(TestContextKey.LOAN_REAGING_RESPONSE);
422+
Assertions.assertNotNull(reAgingResponse);
423+
final Long transactionId = reAgingResponse.getResourceId();
424+
Assertions.assertNotNull(transactionId);
425+
426+
final Boolean expectedValue = "null".equalsIgnoreCase(expectedChangedTerms) ? null : Boolean.valueOf(expectedChangedTerms);
427+
428+
eventAssertion.assertEvent(LoanReAgeTransactionEvent.class, transactionId).extractingData(loanTransactionDataV1 -> {
429+
final LoanTransactionFlagsDataV1 flags = loanTransactionDataV1.getFlags();
430+
final Boolean actualChangedTerms = flags == null ? null : flags.getChangedTerms();
431+
assertThat(actualChangedTerms).as("changedTerms in LoanReAgeTransactionBusinessEvent").isEqualTo(expectedValue);
432+
return null;
433+
});
434+
}
417435
}

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
import org.apache.fineract.avro.loan.v1.LoanStatusEnumDataV1;
6868
import org.apache.fineract.avro.loan.v1.LoanTransactionAdjustmentDataV1;
6969
import org.apache.fineract.avro.loan.v1.LoanTransactionDataV1;
70+
import org.apache.fineract.avro.loan.v1.LoanTransactionFlagsDataV1;
7071
import org.apache.fineract.client.feign.FineractFeignClient;
7172
import org.apache.fineract.client.feign.util.CallFailedRuntimeException;
7273
import org.apache.fineract.client.models.AdvancedPaymentData;
@@ -162,6 +163,7 @@
162163
import org.apache.fineract.test.messaging.event.loan.transaction.LoanChargeAdjustmentPostBusinessEvent;
163164
import org.apache.fineract.test.messaging.event.loan.transaction.LoanChargeOffEvent;
164165
import org.apache.fineract.test.messaging.event.loan.transaction.LoanChargeOffUndoEvent;
166+
import org.apache.fineract.test.messaging.event.loan.transaction.LoanDisbursalTransactionEvent;
165167
import org.apache.fineract.test.messaging.event.loan.transaction.LoanTransactionAccrualActivityPostEvent;
166168
import org.apache.fineract.test.messaging.event.loan.transaction.LoanTransactionContractTerminationPostBusinessEvent;
167169
import org.apache.fineract.test.messaging.store.EventStore;
@@ -5942,4 +5944,35 @@ public static AdvancedPaymentData editPaymentAllocationFutureInstallment(String
59425944

59435945
return advancedPaymentData;
59445946
}
5947+
5948+
@When("Admin disburses the loan on {string} with {string} EUR transaction amount")
5949+
public void disburseLoanForEventVerification(String actualDisbursementDate, String transactionAmount) {
5950+
PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
5951+
assertNotNull(loanResponse);
5952+
long loanId = loanResponse.getLoanId();
5953+
5954+
PostLoansLoanIdRequest disburseRequest = LoanRequestFactory.defaultLoanDisburseRequest()
5955+
.actualDisbursementDate(actualDisbursementDate).transactionAmount(new BigDecimal(transactionAmount));
5956+
5957+
PostLoansLoanIdResponse loanDisburseResponse = ok(
5958+
() -> fineractClient.loans().stateTransitions(loanId, disburseRequest, Map.of("command", "disburse")));
5959+
testContext().set(TestContextKey.LOAN_DISBURSE_RESPONSE, loanDisburseResponse);
5960+
}
5961+
5962+
@Then("LoanDisbursalTransactionBusinessEvent has changedTerms {string}")
5963+
public void checkDisbursalTransactionEventChangedTerms(final String expectedChangedTerms) {
5964+
final PostLoansLoanIdResponse disburseResponse = testContext().get(TestContextKey.LOAN_DISBURSE_RESPONSE);
5965+
assertNotNull(disburseResponse);
5966+
final Long transactionId = disburseResponse.getSubResourceId();
5967+
assertNotNull(transactionId);
5968+
5969+
final Boolean expectedValue = "null".equalsIgnoreCase(expectedChangedTerms) ? null : Boolean.valueOf(expectedChangedTerms);
5970+
5971+
eventAssertion.assertEvent(LoanDisbursalTransactionEvent.class, transactionId).extractingData(loanTransactionDataV1 -> {
5972+
final LoanTransactionFlagsDataV1 flags = loanTransactionDataV1.getFlags();
5973+
final Boolean actualChangedTerms = flags == null ? null : flags.getChangedTerms();
5974+
assertThat(actualChangedTerms).as("changedTerms in LoanDisbursalTransactionBusinessEvent").isEqualTo(expectedValue);
5975+
return null;
5976+
});
5977+
}
59455978
}

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

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9021,4 +9021,41 @@ Feature: Loan
90219021
| 01 January 2025 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 | false | false |
90229022
| 01 February 2025 | Disbursement | 500.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1500.0 | false | false |
90239023
| 01 February 2025 | Repayment | 1525.89 | 1500.0 | 25.89 | 0.0 | 0.0 | 0.0 | false | false |
9024-
| 01 February 2025 | Accrual | 25.89 | 0.0 | 25.89 | 0.0 | 0.0 | 0.0 | false | false |
9024+
| 01 February 2025 | Accrual | 25.89 | 0.0 | 25.89 | 0.0 | 0.0 | 0.0 | false | false |
9025+
9026+
Scenario: Verify that changedTerms is false in LoanDisbursalTransactionBusinessEvent for initial disbursement
9027+
When Admin sets the business date to "01 January 2024"
9028+
When Admin creates a client with random data
9029+
When Admin creates a fully customized loan with the following data:
9030+
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
9031+
| LP2_ADV_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 01 January 2024 | 1000 | 7 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 45 | DAYS | 15 | DAYS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
9032+
And Admin successfully approves the loan on "01 January 2024" with "1000" amount and expected disbursement date on "01 January 2024"
9033+
When Admin disburses the loan on "01 January 2024" with "1000" EUR transaction amount
9034+
Then LoanDisbursalTransactionBusinessEvent has changedTerms "false"
9035+
9036+
Scenario: Verify that changedTerms is true in LoanDisbursalTransactionBusinessEvent when additional disbursement adds new terms
9037+
When Admin sets the business date to "01 January 2024"
9038+
When Admin creates a client with random data
9039+
When Admin creates a fully customized loan with the following data:
9040+
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
9041+
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALC_DAILY_MULTIDISBURSE_FULL_TERM_TRANCHE | 01 January 2024 | 200 | 9.4822 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
9042+
And Admin successfully approves the loan on "01 January 2024" with "200" amount and expected disbursement date on "01 January 2024"
9043+
When Admin disburses the loan on "01 January 2024" with "100" EUR transaction amount
9044+
Then LoanDisbursalTransactionBusinessEvent has changedTerms "false"
9045+
When Admin sets the business date to "01 February 2024"
9046+
When Admin disburses the loan on "01 February 2024" with "100" EUR transaction amount
9047+
Then LoanDisbursalTransactionBusinessEvent has changedTerms "true"
9048+
9049+
Scenario: Verify that changedTerms is false in LoanDisbursalTransactionBusinessEvent when additional disbursement does not change terms
9050+
When Admin sets the business date to "01 January 2024"
9051+
When Admin creates a client with random data
9052+
When Admin set "LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_MULTIDISBURSE" loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future installment allocation rule
9053+
When Admin creates a fully customized loan with the following data:
9054+
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
9055+
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_MULTIDISBURSE | 01 January 2024 | 300 | 9.4822 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 6 | MONTHS | 1 | MONTHS | 6 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
9056+
And Admin successfully approves the loan on "01 January 2024" with "300" amount and expected disbursement date on "01 January 2024"
9057+
When Admin disburses the loan on "01 January 2024" with "100" EUR transaction amount
9058+
Then LoanDisbursalTransactionBusinessEvent has changedTerms "false"
9059+
When Admin sets the business date to "08 January 2024"
9060+
When Admin disburses the loan on "08 January 2024" with "200" EUR transaction amount
9061+
Then LoanDisbursalTransactionBusinessEvent has changedTerms "false"

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Feature: LoanReAging
4646
| 01 January 2024 | Down Payment | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 750.0 | false |
4747
| 20 February 2024 | Re-age | 750.0 | 750.0 | 0.0 | 0.0 | 0.0 | 0.0 | false |
4848
Then Admin checks that delinquency range is: "NO_DELINQUENCY" and has delinquentDate ""
49-
49+
Then LoanReAgeTransactionBusinessEvent has changedTerms "true"
5050
When Loan Pay-off is made on "20 February 2024"
5151
Then Loan is closed with zero outstanding balance and it's all installments have obligations met
5252

fineract-loan/src/main/java/org/apache/fineract/infrastructure/event/business/domain/loan/transaction/LoanDisbursalTransactionBusinessEvent.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ public LoanDisbursalTransactionBusinessEvent(LoanTransaction value) {
2828
super(value);
2929
}
3030

31+
public LoanDisbursalTransactionBusinessEvent(LoanTransaction value, LoanTransactionFlagsData flags) {
32+
super(value, flags);
33+
}
34+
3135
@Override
3236
public String getType() {
3337
return TYPE;

fineract-loan/src/main/java/org/apache/fineract/infrastructure/event/business/domain/loan/transaction/LoanTransactionBusinessEvent.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,24 @@
1818
*/
1919
package org.apache.fineract.infrastructure.event.business.domain.loan.transaction;
2020

21+
import lombok.Getter;
2122
import org.apache.fineract.infrastructure.event.business.domain.AbstractBusinessEvent;
2223
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
2324

25+
@Getter
2426
public abstract class LoanTransactionBusinessEvent extends AbstractBusinessEvent<LoanTransaction> {
2527

2628
private static final String CATEGORY = "Loan";
2729

30+
private final LoanTransactionFlagsData flags;
31+
2832
public LoanTransactionBusinessEvent(LoanTransaction value) {
33+
this(value, null);
34+
}
35+
36+
public LoanTransactionBusinessEvent(LoanTransaction value, LoanTransactionFlagsData flags) {
2937
super(value);
38+
this.flags = flags;
3039
}
3140

3241
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.infrastructure.event.business.domain.loan.transaction;
20+
21+
public record LoanTransactionFlagsData(boolean changedTerms) {
22+
23+
}

0 commit comments

Comments
 (0)