FINERACT-1971: Internal server error fix for handling batch API hard locked loan
This commit is contained in:
committed by
Arnold Gálovics
parent
d112ee4b26
commit
1d2fc73715
+10
-1
@@ -29,6 +29,7 @@ import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
@@ -173,6 +174,10 @@ public class LoanCOBFilterHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isLoanHardLocked(Long... loanIds) {
|
||||
return isLoanHardLocked(Arrays.asList(loanIds));
|
||||
}
|
||||
|
||||
private boolean isLoanHardLocked(List<Long> loanIds) {
|
||||
return loanIds.stream().anyMatch(loanAccountLockService::isLoanHardLocked);
|
||||
}
|
||||
@@ -208,7 +213,11 @@ public class LoanCOBFilterHelper {
|
||||
// check the body for Loan ID
|
||||
Long loanId = getTopLevelLoanIdFromBatchRequest(batchRequest);
|
||||
if (loanId != null) {
|
||||
loanIds.add(loanId);
|
||||
if (isLoanHardLocked(loanId)) {
|
||||
throw new LoanIdsHardLockedException(loanId);
|
||||
} else {
|
||||
loanIds.add(loanId);
|
||||
}
|
||||
}
|
||||
}
|
||||
return loanIds;
|
||||
|
||||
+14
@@ -75,6 +75,8 @@ import org.apache.fineract.integrationtests.common.accounting.Account;
|
||||
import org.apache.fineract.integrationtests.common.accounting.AccountHelper;
|
||||
import org.apache.fineract.integrationtests.common.accounting.JournalEntryHelper;
|
||||
import org.apache.fineract.integrationtests.common.charges.ChargesHelper;
|
||||
import org.apache.fineract.integrationtests.common.error.ErrorResponse;
|
||||
import org.apache.fineract.integrationtests.common.loans.LoanAccountLockHelper;
|
||||
import org.apache.fineract.integrationtests.common.loans.LoanProductHelper;
|
||||
import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
|
||||
import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension;
|
||||
@@ -113,6 +115,9 @@ public abstract class BaseLoanIntegrationTest {
|
||||
protected final InlineLoanCOBHelper inlineLoanCOBHelper = new InlineLoanCOBHelper(requestSpec, responseSpec);
|
||||
|
||||
protected BusinessDateHelper businessDateHelper = new BusinessDateHelper();
|
||||
|
||||
protected final LoanAccountLockHelper loanAccountLockHelper = new LoanAccountLockHelper(requestSpec,
|
||||
createResponseSpecification(Matchers.is(202)));
|
||||
protected DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DATETIME_PATTERN);
|
||||
|
||||
// asset
|
||||
@@ -342,6 +347,10 @@ public abstract class BaseLoanIntegrationTest {
|
||||
}
|
||||
}
|
||||
|
||||
protected void placeHardLockOnLoan(Long loanId) {
|
||||
loanAccountLockHelper.placeSoftLockOnLoanAccount(loanId.intValue(), "LOAN_COB_CHUNK_PROCESSING");
|
||||
}
|
||||
|
||||
protected void executeInlineCOB(Long loanId) {
|
||||
inlineLoanCOBHelper.executeInlineCOB(List.of(loanId));
|
||||
}
|
||||
@@ -634,6 +643,11 @@ public abstract class BaseLoanIntegrationTest {
|
||||
public List<BatchResponse> executeEnclosingTransaction() {
|
||||
return BatchHelper.postBatchRequestsWithEnclosingTransaction(requestSpec, responseSpec, BatchHelper.toJsonString(requests));
|
||||
}
|
||||
|
||||
public ErrorResponse executeEnclosingTransactionError(ResponseSpecification responseSpec) {
|
||||
return BatchHelper.postBatchRequestsWithoutEnclosingTransactionError(requestSpec, responseSpec,
|
||||
BatchHelper.toJsonString(requests));
|
||||
}
|
||||
}
|
||||
|
||||
@ToString
|
||||
|
||||
+63
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.apache.fineract.integrationtests;
|
||||
|
||||
import io.restassured.builder.ResponseSpecBuilder;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
@@ -28,6 +29,7 @@ import org.apache.fineract.client.models.PostLoansLoanIdResponse;
|
||||
import org.apache.fineract.client.models.PostLoansRequest;
|
||||
import org.apache.fineract.client.models.PostLoansResponse;
|
||||
import org.apache.fineract.integrationtests.common.ClientHelper;
|
||||
import org.apache.fineract.integrationtests.common.error.ErrorResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -98,4 +100,65 @@ public class BatchLoanIntegrationTest extends BaseLoanIntegrationTest {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_InlineLoanCOB_ShouldExecute_WhenLoanIsHardLocked_And_RescheduleIsRequestedViaBatchApi() {
|
||||
AtomicLong createdLoanId = new AtomicLong();
|
||||
|
||||
runAt("01 January 2023", () -> {
|
||||
// Create Client
|
||||
Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
|
||||
|
||||
int numberOfRepayments = 24;
|
||||
int repaymentEvery = 1;
|
||||
|
||||
// Create Loan Product
|
||||
PostLoanProductsRequest product = createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct() //
|
||||
.numberOfRepayments(numberOfRepayments) //
|
||||
.repaymentEvery(repaymentEvery) //
|
||||
.repaymentFrequencyType(RepaymentFrequencyType.MONTHS.longValue()); //
|
||||
|
||||
PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(product);
|
||||
Long loanProductId = loanProductResponse.getResourceId();
|
||||
|
||||
// Apply and Approve Loan
|
||||
double amount = 1250.0;
|
||||
|
||||
PostLoansRequest applicationRequest = applyLoanRequest(clientId, loanProductId, "01 January 2023", amount, numberOfRepayments)//
|
||||
.repaymentEvery(repaymentEvery)//
|
||||
.loanTermFrequency(numberOfRepayments)//
|
||||
.repaymentFrequencyType(RepaymentFrequencyType.MONTHS)//
|
||||
.loanTermFrequencyType(RepaymentFrequencyType.MONTHS);
|
||||
|
||||
PostLoansResponse postLoansResponse = loanTransactionHelper.applyLoan(applicationRequest);
|
||||
|
||||
PostLoansLoanIdResponse approvedLoanResult = loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
|
||||
approveLoanRequest(amount, "01 January 2023"));
|
||||
|
||||
Long loanId = approvedLoanResult.getLoanId();
|
||||
|
||||
// disburse Loan
|
||||
disburseLoan(loanId, BigDecimal.valueOf(1250.0), "01 January 2023");
|
||||
|
||||
createdLoanId.set(loanId);
|
||||
});
|
||||
|
||||
runAt("02 January 2023", () -> {
|
||||
executeInlineCOB(createdLoanId.get());
|
||||
});
|
||||
|
||||
runAt("05 January 2023", () -> {
|
||||
long loanId = createdLoanId.get();
|
||||
placeHardLockOnLoan(loanId);
|
||||
runAsNonByPass(() -> {
|
||||
|
||||
ErrorResponse response = batchRequest() //
|
||||
.rescheduleLoan(1L, loanId, "01 January 2023", "01 February 2023", "01 March 2023") //
|
||||
.approveRescheduleLoan(2L, 1L, "01 January 2023") //
|
||||
.executeEnclosingTransactionError(new ResponseSpecBuilder().expectStatusCode(409).build()); //
|
||||
|
||||
Assertions.assertEquals(HttpStatus.SC_CONFLICT, Integer.parseInt(response.getHttpStatusCode()));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+5
-2
@@ -251,8 +251,11 @@ public final class Utils {
|
||||
public static <T> T performServerPost(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
|
||||
final String postURL, final String jsonBodyToSend, final String jsonAttributeToGetBack) {
|
||||
LOG.info("JSON {}", jsonBodyToSend);
|
||||
final String json = given().spec(requestSpec).body(jsonBodyToSend).expect().spec(responseSpec).log().ifError().when().post(postURL)
|
||||
.andReturn().asString();
|
||||
RequestSpecification spec = given().spec(requestSpec);
|
||||
if (StringUtils.isNotBlank(jsonBodyToSend)) {
|
||||
spec = spec.body(jsonBodyToSend);
|
||||
}
|
||||
final String json = spec.expect().spec(responseSpec).log().ifError().when().post(postURL).andReturn().asString();
|
||||
if (jsonAttributeToGetBack == null) {
|
||||
return (T) json;
|
||||
}
|
||||
|
||||
+1
-2
@@ -43,8 +43,7 @@ public class LoanAccountLockHelper extends IntegrationTest {
|
||||
|
||||
public String placeSoftLockOnLoanAccount(Integer loanId, String lockOwner, String error) {
|
||||
return Utils.performServerPost(requestSpec, responseSpec,
|
||||
INTERNAL_PLACE_LOCK_ON_LOAN_ACCOUNT_URL + loanId + "/place-lock/" + lockOwner + "?" + Utils.TENANT_IDENTIFIER,
|
||||
error == null ? GSON.toJson(null) : error);
|
||||
INTERNAL_PLACE_LOCK_ON_LOAN_ACCOUNT_URL + loanId + "/place-lock/" + lockOwner + "?" + Utils.TENANT_IDENTIFIER, error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user