From 49b3c014efc2937eaad5ff5c9899cf493356cdd0 Mon Sep 17 00:00:00 2001 From: taskain7 Date: Thu, 29 Feb 2024 02:35:14 +0100 Subject: [PATCH] FINERACT-2058: loan can be marked as fraud in any status --- ...WritePlatformServiceJpaRepositoryImpl.java | 5 - .../BaseLoanIntegrationTest.java | 4 + .../LoanAccountFraudTest.java | 154 +++++++++--------- 3 files changed, 82 insertions(+), 81 deletions(-) diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 5c9759407..479370353 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -2550,11 +2550,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf Loan loan = this.loanAssembler.assembleFrom(loanId); final Map changes = new LinkedHashMap<>(); - - if (loan.isApproved() || loan.isSubmittedAndPendingApproval()) { - throw new GeneralPlatformDomainRuleException("error.msg.loan.mark.as.fraud.not.allowed", - "Loan Id: " + loanId + " mark as fraud is not allowed as loan status is not active", loan.getStatus().getCode()); - } final boolean fraud = command.booleanPrimitiveValueOfParameterNamed(LoanApiConstants.FRAUD_ATTRIBUTE_NAME); if (loan.isFraud() != fraud) { loan.markAsFraud(fraud); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java index f0056b250..0d74fc161 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java @@ -401,6 +401,10 @@ public abstract class BaseLoanIntegrationTest { .transactionAmount(amount).locale("en")); } + protected void undoDisbursement(Integer loanId) { + loanTransactionHelper.undoDisbursal(loanId); + } + protected void verifyJournalEntries(Long loanId, Journal... entries) { GetJournalEntriesTransactionIdResponse journalEntriesForLoan = journalEntryHelper.getJournalEntriesForLoan(loanId); Assertions.assertEquals(entries.length, journalEntriesForLoan.getPageItems().size()); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountFraudTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountFraudTest.java index 771dafe2d..1cca12cca 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountFraudTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountFraudTest.java @@ -21,63 +21,50 @@ package org.apache.fineract.integrationtests; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import io.restassured.builder.RequestSpecBuilder; -import io.restassured.builder.ResponseSpecBuilder; -import io.restassured.http.ContentType; -import io.restassured.specification.RequestSpecification; -import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; import java.time.LocalDate; -import java.util.HashMap; import lombok.extern.slf4j.Slf4j; -import org.apache.fineract.client.models.GetLoanProductsProductIdResponse; import org.apache.fineract.client.models.GetLoansLoanIdResponse; +import org.apache.fineract.client.models.PostLoanProductsRequest; +import org.apache.fineract.client.models.PostLoanProductsResponse; +import org.apache.fineract.client.models.PostLoansLoanIdResponse; +import org.apache.fineract.client.models.PostLoansResponse; import org.apache.fineract.client.models.PutLoansLoanIdResponse; -import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; -import org.apache.fineract.integrationtests.common.BusinessDateHelper; import org.apache.fineract.integrationtests.common.ClientHelper; -import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper; import org.apache.fineract.integrationtests.common.Utils; -import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; -import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension; -import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @Slf4j @ExtendWith(LoanTestLifecycleExtension.class) -public class LoanAccountFraudTest { +public class LoanAccountFraudTest extends BaseLoanIntegrationTest { - private ResponseSpecification responseSpec; - private ResponseSpecification responseSpecError; - private RequestSpecification requestSpec; - private LoanTransactionHelper loanTransactionHelper; - private final String amountVal = "1000"; + private static final double AMOUNT = 100.0; + private static final String COMMAND = "markAsFraud"; private LocalDate todaysDate; private String operationDate; @BeforeEach public void setup() { Utils.initializeRESTAssured(); - this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); - this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); - this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); - this.responseSpecError = new ResponseSpecBuilder().expectStatusCode(403).build(); - this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - this.todaysDate = Utils.getLocalDateOfTenant(); this.operationDate = Utils.dateFormatter.format(this.todaysDate); } @Test public void testMarkLoanAsFraud() { - try { - GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE); - BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, todaysDate); - final String command = "markAsFraud"; - // Client and Loan account creation - final Integer loanId = createAccounts(15, 1); + runAt(operationDate, () -> { + + final Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId(); + + PostLoanProductsRequest loanProductsRequest = createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct(); + PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(loanProductsRequest); + + PostLoansResponse postLoansResponse = loanTransactionHelper + .applyLoan(applyLoanRequest(clientId, loanProductResponse.getResourceId(), operationDate, AMOUNT, 1)); + Integer loanId = postLoansResponse.getLoanId().intValue(); GetLoansLoanIdResponse getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId); assertNotNull(getLoansLoanIdResponse); @@ -87,16 +74,46 @@ public class LoanAccountFraudTest { assertEquals(Boolean.FALSE, getLoansLoanIdResponse.getFraud()); String payload = loanTransactionHelper.getLoanFraudPayloadAsJSON("fraud", "true"); - // Send the request, not expecting any errors (because only open loan restriction removed) - PutLoansLoanIdResponse putLoansLoanIdResponse = loanTransactionHelper.modifyLoanCommand(loanId, command, payload, - this.responseSpecError); + PutLoansLoanIdResponse putLoansLoanIdResponse = loanTransactionHelper.modifyLoanCommand(loanId, COMMAND, payload, responseSpec); + assertNotNull(putLoansLoanIdResponse); + getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId); + assertNotNull(getLoansLoanIdResponse); + assertNotNull(getLoansLoanIdResponse.getFraud()); + assertEquals(Boolean.TRUE, getLoansLoanIdResponse.getFraud()); String statusCode = getLoansLoanIdResponse.getStatus().getCode(); log.info("Loan with Id {} is with Status {}", getLoansLoanIdResponse.getId(), statusCode); + payload = loanTransactionHelper.getLoanFraudPayloadAsJSON("fraud", "false"); + putLoansLoanIdResponse = loanTransactionHelper.modifyLoanCommand(loanId, COMMAND, payload, responseSpec); + assertNotNull(putLoansLoanIdResponse); + + getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId); + assertNotNull(getLoansLoanIdResponse); + assertNotNull(getLoansLoanIdResponse.getFraud()); + assertEquals(Boolean.FALSE, getLoansLoanIdResponse.getFraud()); + statusCode = getLoansLoanIdResponse.getStatus().getCode(); + log.info("Loan with Id {} is with Status {}", getLoansLoanIdResponse.getId(), statusCode); + // Approve the Loan active - loanTransactionHelper.approveLoan(operationDate, this.amountVal, loanId, null); - putLoansLoanIdResponse = loanTransactionHelper.modifyLoanCommand(loanId, command, payload, this.responseSpecError); + PostLoansLoanIdResponse approvedLoanResult = loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(), + approveLoanRequest(AMOUNT, operationDate)); + assertNotNull(approvedLoanResult); + + payload = loanTransactionHelper.getLoanFraudPayloadAsJSON("fraud", "true"); + putLoansLoanIdResponse = loanTransactionHelper.modifyLoanCommand(loanId, COMMAND, payload, responseSpec); + assertNotNull(putLoansLoanIdResponse); + + getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId); + assertNotNull(getLoansLoanIdResponse); + assertNotNull(getLoansLoanIdResponse.getFraud()); + assertEquals(Boolean.TRUE, getLoansLoanIdResponse.getFraud()); + statusCode = getLoansLoanIdResponse.getStatus().getCode(); + log.info("Loan with Id {} is with Status {}", getLoansLoanIdResponse.getId(), statusCode); + + payload = loanTransactionHelper.getLoanFraudPayloadAsJSON("fraud", "false"); + putLoansLoanIdResponse = loanTransactionHelper.modifyLoanCommand(loanId, COMMAND, payload, responseSpec); + assertNotNull(putLoansLoanIdResponse); // Default values Not Null and False getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId); @@ -106,10 +123,11 @@ public class LoanAccountFraudTest { statusCode = getLoansLoanIdResponse.getStatus().getCode(); log.info("Loan with Id {} is with Status {}", getLoansLoanIdResponse.getId(), statusCode); - loanTransactionHelper.disburseLoanWithNetDisbursalAmount(operationDate, loanId, this.amountVal); + disburseLoan(loanId.longValue(), BigDecimal.valueOf(AMOUNT), operationDate); // Mark On the Fraud - putLoansLoanIdResponse = loanTransactionHelper.modifyLoanCommand(loanId, command, payload, this.responseSpec); + payload = loanTransactionHelper.getLoanFraudPayloadAsJSON("fraud", "true"); + putLoansLoanIdResponse = loanTransactionHelper.modifyLoanCommand(loanId, COMMAND, payload, responseSpec); assertNotNull(putLoansLoanIdResponse); getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId); @@ -119,49 +137,33 @@ public class LoanAccountFraudTest { // Mark Off the Fraud payload = loanTransactionHelper.getLoanFraudPayloadAsJSON("fraud", "false"); - putLoansLoanIdResponse = loanTransactionHelper.modifyLoanCommand(loanId, command, payload, this.responseSpec); + putLoansLoanIdResponse = loanTransactionHelper.modifyLoanCommand(loanId, COMMAND, payload, this.responseSpec); assertNotNull(putLoansLoanIdResponse); getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId); assertNotNull(getLoansLoanIdResponse); assertNotNull(getLoansLoanIdResponse.getFraud()); assertEquals(Boolean.FALSE, getLoansLoanIdResponse.getFraud()); - } finally { - GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.FALSE); - } + + payload = loanTransactionHelper.getLoanFraudPayloadAsJSON("fraud", "true"); + putLoansLoanIdResponse = loanTransactionHelper.modifyLoanCommand(loanId, COMMAND, payload, responseSpec); + assertNotNull(putLoansLoanIdResponse); + + getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId); + assertNotNull(getLoansLoanIdResponse); + assertNotNull(getLoansLoanIdResponse.getFraud()); + assertEquals(Boolean.TRUE, getLoansLoanIdResponse.getFraud()); + statusCode = getLoansLoanIdResponse.getStatus().getCode(); + log.info("Loan with Id {} is with Status {}", getLoansLoanIdResponse.getId(), statusCode); + + undoDisbursement(loanId); + + getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId); + assertNotNull(getLoansLoanIdResponse); + assertNotNull(getLoansLoanIdResponse.getFraud()); + assertEquals(Boolean.TRUE, getLoansLoanIdResponse.getFraud()); + statusCode = getLoansLoanIdResponse.getStatus().getCode(); + log.info("Loan with Id {} is with Status {}", getLoansLoanIdResponse.getId(), statusCode); + }); } - - private Integer createAccounts(final Integer daysToSubtract, final Integer numberOfRepayments) { - // Client and Loan account creation - final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2012"); - final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProduct(loanTransactionHelper, null); - - // Older date to have more than one overdue installment - final LocalDate transactionDate = this.todaysDate.minusDays(daysToSubtract + (30 * (numberOfRepayments - 1))); - String operationDate = Utils.dateFormatter.format(transactionDate); - - return createLoanAccount(loanTransactionHelper, clientId.toString(), getLoanProductsProductResponse.getId().toString(), - operationDate, amountVal, numberOfRepayments.toString()); - } - - private GetLoanProductsProductIdResponse createLoanProduct(final LoanTransactionHelper loanTransactionHelper, - final Integer delinquencyBucketId) { - final HashMap loanProductMap = new LoanProductTestBuilder().build(null, delinquencyBucketId); - final Integer loanProductId = loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap)); - return loanTransactionHelper.getLoanProduct(loanProductId); - } - - private Integer createLoanAccount(final LoanTransactionHelper loanTransactionHelper, final String clientId, final String loanProductId, - final String operationDate, final String principalAmount, final String numberOfRepayments) { - final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal(principalAmount) - .withLoanTermFrequency(numberOfRepayments).withLoanTermFrequencyAsMonths().withNumberOfRepayments(numberOfRepayments) - .withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths() // - .withInterestRatePerPeriod("0") // - .withExpectedDisbursementDate(operationDate) // - .withInterestTypeAsDecliningBalance() // - .withSubmittedOnDate(operationDate) // - .build(clientId, loanProductId, null); - return loanTransactionHelper.getLoanId(loanApplicationJSON); - } - }