Skip to content

Commit a278d28

Browse files
authored
Merge pull request #5670
FINERACT-2454: Migrate ClientLoanAccountLockIntegrationTest from RestAssured to feign client
2 parents f1cb567 + e2d4a22 commit a278d28

4 files changed

Lines changed: 60 additions & 122 deletions

File tree

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

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@
4848
import org.apache.fineract.test.data.LoanStatus;
4949
import org.apache.fineract.test.helper.BusinessDateHelper;
5050
import org.apache.fineract.test.helper.WorkingCapitalLoanTestHelper;
51-
import org.apache.fineract.test.messaging.config.JobPollingProperties;
5251
import org.apache.fineract.test.stepdef.AbstractStepDef;
5352
import org.apache.fineract.test.support.TestContextKey;
5453
import org.junit.jupiter.api.Assertions;
@@ -63,8 +62,6 @@ public class WorkingCapitalLoanCobStepDef extends AbstractStepDef {
6362
private WorkingCapitalLoanTestHelper wcLoanHelper;
6463
@Autowired
6564
private FineractFeignClient fineractClient;
66-
@Autowired
67-
private JobPollingProperties jobPollingProperties;
6865

6966
@Before(value = "@WCCOBFeature")
7067
public void beforeWcCobScenario() {
@@ -243,29 +240,42 @@ public void runWorkingCapitalLoanCOBCatchUp() {
243240

244241
@When("Admin checks that WC Loan COB is running until the current business date")
245242
public void checkWCLoanCOBCatchUpRunningUntilCOBBusinessDate() {
246-
await().atMost(Duration.ofMillis(jobPollingProperties.getTimeoutInMillis())) //
247-
.pollInterval(Duration.ofMillis(jobPollingProperties.getIntervalInMillis())) //
243+
// Resolve the expected completion date upfront, before the async job potentially finishes.
244+
// COB catch-up processes every day from the oldest lastClosedBusinessDate up to cobBusinessDate.
245+
// When complete, cobProcessedDate (the oldest loan's lastClosedBusinessDate) will equal cobBusinessDate.
246+
BusinessDateResponse businessDateResponse = ok(
247+
() -> fineractClient.businessDateManagement().getBusinessDate(BusinessDateHelper.COB, Map.of()));
248+
LocalDate expectedCompletionDate = businessDateResponse.getDate();
249+
250+
// Single-phase polling: handles both the case where the job is still running AND where it
251+
// already finished before this polling loop started (race condition with async execution).
252+
// Bug fix #1: removed Phase 1 "wait until running" which timed out when the job completed
253+
// too quickly for the poll to catch isCatchUpRunning = true.
254+
// Bug fix #2: use cobProcessedDate (oldest loan's lastClosedBusinessDate) instead of
255+
// cobBusinessDate (which is always == current COB date, making the check vacuous).
256+
await() //
257+
.atMost(Duration.ofMinutes(4)) //
258+
.pollInterval(Duration.ofSeconds(5)) //
259+
.pollDelay(Duration.ofSeconds(2)) //
248260
.until(() -> {
249-
IsCatchUpRunningDTO isCatchUpRunningResponse = ok(
250-
() -> fineractClient.workingCapitalLoanCobCatchUpApi().isCatchUpRunning1());
251-
return isCatchUpRunningResponse.getCatchUpRunning();
252-
});
253-
// Then wait for catch-up to complete
254-
await().atMost(Duration.ofMinutes(4)).pollInterval(Duration.ofSeconds(5)).pollDelay(Duration.ofSeconds(5)).until(() -> {
255-
IsCatchUpRunningDTO statusResponse = ok(() -> fineractClient.workingCapitalLoanCobCatchUpApi().isCatchUpRunning1());
256-
if (!statusResponse.getCatchUpRunning()) {
257-
BusinessDateResponse businessDateResponse = ok(
258-
() -> fineractClient.businessDateManagement().getBusinessDate(BusinessDateHelper.COB, Map.of()));
259-
LocalDate currentBusinessDate = businessDateResponse.getDate();
261+
IsCatchUpRunningDTO statusResponse = ok(() -> fineractClient.workingCapitalLoanCobCatchUpApi().isCatchUpRunning1());
260262

261-
OldestCOBProcessedLoanDTO catchUpResponse = ok(
262-
() -> fineractClient.workingCapitalLoanCobCatchUpApi().getOldestCOBProcessedLoan1());
263-
LocalDate lastClosedDate = catchUpResponse.getCobBusinessDate();
263+
if (statusResponse.getCatchUpRunning()) {
264+
log.debug("WC COB catch-up still running, waiting...");
265+
return false;
266+
}
264267

265-
return !lastClosedDate.isBefore(currentBusinessDate);
266-
}
267-
return false;
268-
});
268+
// Catch-up not running — check whether it processed all days up to the expected date.
269+
// cobProcessedDate = the oldest loan's lastClosedBusinessDate after the last COB run.
270+
OldestCOBProcessedLoanDTO catchUpStatus = ok(
271+
() -> fineractClient.workingCapitalLoanCobCatchUpApi().getOldestCOBProcessedLoan1());
272+
LocalDate cobProcessedDate = catchUpStatus.getCobProcessedDate();
273+
274+
boolean catchUpComplete = !cobProcessedDate.isBefore(expectedCompletionDate);
275+
log.debug("WC COB catch-up complete check: cobProcessedDate={}, expectedCompletionDate={}, complete={}",
276+
cobProcessedDate, expectedCompletionDate, catchUpComplete);
277+
return catchUpComplete;
278+
});
269279
}
270280

271281
@SuppressWarnings("unchecked")

integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientExternalIdTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,6 @@ public void testDeleteClientUsingExternalId() {
232232
ClientHelper.closeClient(clientExternalId, closureReasonId);
233233
ClientHelper.reactivateClient(clientExternalId);
234234

235-
// then
236235
final DeleteClientsClientIdResponse clientDeleteResponse = ClientHelper.deleteClientByExternalId(clientExternalId);
237236
assertNotNull(clientDeleteResponse);
238237
assertNotNull(clientDeleteResponse.getResourceExternalId());

integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanAccountLockIntegrationTest.java

Lines changed: 26 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -18,117 +18,46 @@
1818
*/
1919
package org.apache.fineract.integrationtests;
2020

21-
import io.restassured.builder.RequestSpecBuilder;
22-
import io.restassured.builder.ResponseSpecBuilder;
23-
import io.restassured.http.ContentType;
24-
import io.restassured.specification.RequestSpecification;
25-
import io.restassured.specification.ResponseSpecification;
26-
import java.util.ArrayList;
27-
import java.util.HashMap;
28-
import java.util.List;
2921
import org.apache.fineract.client.models.LoanAccountLockResponseDTO;
22+
import org.apache.fineract.client.models.LockRequest;
23+
import org.apache.fineract.client.models.PostLoansLoanIdRequest;
24+
import org.apache.fineract.client.models.PostLoansResponse;
25+
import org.apache.fineract.client.util.Calls;
3026
import org.apache.fineract.integrationtests.common.ClientHelper;
27+
import org.apache.fineract.integrationtests.common.FineractClientHelper;
3128
import org.apache.fineract.integrationtests.common.Utils;
32-
import org.apache.fineract.integrationtests.common.accounting.Account;
33-
import org.apache.fineract.integrationtests.common.loans.LoanAccountLockHelper;
34-
import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
35-
import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
36-
import org.apache.fineract.integrationtests.common.loans.LoanStatusChecker;
37-
import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension;
38-
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
29+
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
3930
import org.junit.jupiter.api.Assertions;
40-
import org.junit.jupiter.api.BeforeEach;
4131
import org.junit.jupiter.api.Test;
42-
import org.junit.jupiter.api.extension.ExtendWith;
43-
import org.slf4j.Logger;
44-
import org.slf4j.LoggerFactory;
4532

46-
@SuppressWarnings({ "rawtypes", "unchecked" })
47-
@ExtendWith(LoanTestLifecycleExtension.class)
48-
public class ClientLoanAccountLockIntegrationTest {
49-
50-
private static final Logger LOG = LoggerFactory.getLogger(ClientLoanAccountLockIntegrationTest.class);
51-
52-
public static final String MINIMUM_OPENING_BALANCE = "1000.0";
53-
public static final String ACCOUNT_TYPE_INDIVIDUAL = "INDIVIDUAL";
54-
private static final String NONE = "1";
55-
56-
private ResponseSpecification responseSpec;
57-
private RequestSpecification requestSpec;
58-
private ClientHelper clientHelper;
59-
private LoanTransactionHelper loanTransactionHelper;
60-
private LoanAccountLockHelper loanAccountLockHelper;
61-
62-
@BeforeEach
63-
public void setup() {
64-
Utils.initializeRESTAssured();
65-
this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
66-
this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
67-
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
68-
this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
69-
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
70-
loanAccountLockHelper = new LoanAccountLockHelper(requestSpec, new ResponseSpecBuilder().expectStatusCode(202).build());
71-
}
33+
public class ClientLoanAccountLockIntegrationTest extends BaseLoanIntegrationTest {
7234

7335
@Test
7436
public void checkRetrieveLockedLoanAccountsList() {
75-
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
76-
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
37+
final Long clientId = ClientHelper.addClientAsPerson(null, ClientHelper.LEGALFORM_ID_PERSON, null).getResourceId();
7738

78-
final Integer loanProductID = createLoanProduct(false, NONE);
39+
final Long loanProductId = loanTransactionHelper.createLoanProduct(createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct()) //
40+
.getResourceId();
7941

80-
List<HashMap> collaterals = new ArrayList<>();
81-
final Integer loanID = applyForLoanApplication(clientID, loanProductID, null, null, "12,000.00", collaterals);
82-
HashMap loanStatusHashMap = this.loanTransactionHelper.approveLoan("20 September 2011", loanID);
83-
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
84-
loanStatusHashMap = this.loanTransactionHelper.disburseLoanWithNetDisbursalAmount("20 September 2011", loanID, "12,000.00");
85-
LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
42+
final PostLoansResponse loanResponse = loanTransactionHelper
43+
.applyLoan(applyLoanRequest(clientId, loanProductId, "20 September 2011", 12000.0, 4));
44+
final Long loanId = loanResponse.getLoanId();
8645

87-
loanAccountLockHelper.placeSoftLockOnLoanAccount(loanID, "LOAN_INLINE_COB_PROCESSING", "Sample error");
46+
loanTransactionHelper.approveLoan(loanId, new PostLoansLoanIdRequest() //
47+
.approvedOnDate("20 September 2011") //
48+
.dateFormat(Utils.DATE_FORMAT) //
49+
.locale("en"));
50+
verifyLoanStatus(loanId, LoanStatus.APPROVED);
8851

89-
LoanAccountLockResponseDTO getLoanAccountLockResponse = clientHelper.retrieveLockedAccounts(0, 1000);
90-
Assertions.assertTrue(getLoanAccountLockResponse.getContent().size() > 0);
91-
Assertions.assertTrue(getLoanAccountLockResponse.getContent().stream()
92-
.anyMatch(loanAccountLock -> loanAccountLock.getLoanId().equals(Long.valueOf(loanID))));
93-
}
52+
loanTransactionHelper.disburseLoan(loanId, "20 September 2011", 12000.0);
53+
verifyLoanStatus(loanId, LoanStatus.ACTIVE);
9454

95-
private Integer createLoanProduct(final boolean multiDisburseLoan, final String accountingRule, final Account... accounts) {
96-
LOG.info("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------");
97-
LoanProductTestBuilder builder = new LoanProductTestBuilder() //
98-
.withPrincipal("12,000.00") //
99-
.withNumberOfRepayments("4") //
100-
.withRepaymentAfterEvery("1") //
101-
.withRepaymentTypeAsMonth() //
102-
.withinterestRatePerPeriod("1") //
103-
.withInterestRateFrequencyTypeAsMonths() //
104-
.withAmortizationTypeAsEqualInstallments() //
105-
.withInterestTypeAsDecliningBalance() //
106-
.withTranches(multiDisburseLoan) //
107-
.withAccounting(accountingRule, accounts);
108-
if (multiDisburseLoan) {
109-
builder = builder.withInterestCalculationPeriodTypeAsRepaymentPeriod(true);
110-
}
111-
final String loanProductJSON = builder.build(null);
112-
return this.loanTransactionHelper.getLoanProductId(loanProductJSON);
113-
}
55+
Calls.ok(FineractClientHelper.getFineractClient().legacy //
56+
.placeLockOnLoanAccount(loanId, "LOAN_INLINE_COB_PROCESSING", new LockRequest().error("Sample error")));
11457

115-
private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, List<HashMap> charges,
116-
final String savingsId, String principal, List<HashMap> collaterals) {
117-
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
118-
final String loanApplicationJSON = new LoanApplicationTestBuilder() //
119-
.withPrincipal(principal) //
120-
.withLoanTermFrequency("4") //
121-
.withLoanTermFrequencyAsMonths() //
122-
.withNumberOfRepayments("4") //
123-
.withRepaymentEveryAfter("1") //
124-
.withRepaymentFrequencyTypeAsMonths() //
125-
.withInterestRatePerPeriod("2") //
126-
.withAmortizationTypeAsEqualInstallments() //
127-
.withInterestTypeAsDecliningBalance() //
128-
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod() //
129-
.withExpectedDisbursementDate("20 September 2011") //
130-
.withSubmittedOnDate("20 September 2011") //
131-
.withCollaterals(collaterals).withCharges(charges).build(clientID.toString(), loanProductID.toString(), savingsId);
132-
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
58+
LoanAccountLockResponseDTO lockResponse = Calls
59+
.ok(FineractClientHelper.getFineractClient().loanAccountLockApi.retrieveLockedAccounts(0, 1000));
60+
Assertions.assertTrue(lockResponse.getContent().size() > 0);
61+
Assertions.assertTrue(lockResponse.getContent().stream().anyMatch(lock -> lock.getLoanId().equals(loanId)));
13362
}
13463
}

integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanWithdrawnByApplicantIntegrationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public class LoanWithdrawnByApplicantIntegrationTest extends BaseLoanIntegration
3232
public void loanWithdrawnByApplicant() {
3333
final Long clientId = ClientHelper.createClient(new PostClientsRequest() //
3434
.officeId(1L) //
35-
.legalFormId(1L) //
35+
.legalFormId(ClientHelper.LEGALFORM_ID_PERSON) //
3636
.firstname(Utils.randomFirstNameGenerator()) //
3737
.lastname(Utils.randomLastNameGenerator()) //
3838
.active(true) //

0 commit comments

Comments
 (0)