From 573b4bb998aeebd547daae81b18edf4a1ef5ab5a Mon Sep 17 00:00:00 2001 From: "abraham.menyhart" Date: Wed, 21 Jun 2023 14:50:42 +0200 Subject: [PATCH] FINERACT-1724: Loan product creation - duplicate short name fix --- ...WritePlatformServiceJpaRepositoryImpl.java | 11 ++- .../LoanProductShortNameValidationTest.java | 73 +++++++++++++++++++ .../common/loans/LoanProductTestBuilder.java | 7 +- 3 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductShortNameValidationTest.java diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java index fdc7547f8..cff6227ba 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java @@ -328,7 +328,8 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro final String name = command.stringValueOfParameterNamed("name"); throw new PlatformDataIntegrityException("error.msg.product.loan.duplicate.name", "Loan product with name `" + name + "` already exists", "name", name, realCause); - } else if (realCause.getMessage().contains("'unq_short_name'")) { + } else if (realCause.getMessage().contains("'unq_short_name'") || containsDuplicateShortnameErrorForPostgreSQL(realCause) + || containsDuplicateShortnameErrorForMySQL(realCause)) { final String shortName = command.stringValueOfParameterNamed("shortName"); throw new PlatformDataIntegrityException("error.msg.product.loan.duplicate.short.name", @@ -343,6 +344,14 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro "Unknown data integrity issue with resource.", realCause); } + private static boolean containsDuplicateShortnameErrorForPostgreSQL(Throwable realCause) { + return realCause.getMessage().contains("m_product_loan_short_name_key"); + } + + private static boolean containsDuplicateShortnameErrorForMySQL(Throwable realCause) { + return (realCause.getMessage().contains("short_name") && realCause.getMessage().toLowerCase().contains("duplicate")); + } + private void validateInputDates(final JsonCommand command) { final LocalDate startDate = command.localDateValueOfParameterNamed("startDate"); final LocalDate closeDate = command.localDateValueOfParameterNamed("closeDate"); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductShortNameValidationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductShortNameValidationTest.java new file mode 100644 index 000000000..7f8e21b96 --- /dev/null +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductShortNameValidationTest.java @@ -0,0 +1,73 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.fineract.integrationtests; + +import static io.restassured.http.ContentType.JSON; +import static org.apache.fineract.integrationtests.common.Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey; +import static org.apache.fineract.integrationtests.common.Utils.uniqueRandomStringGenerator; +import static org.hamcrest.Matchers.equalTo; + +import io.restassured.builder.RequestSpecBuilder; +import io.restassured.builder.ResponseSpecBuilder; +import io.restassured.specification.RequestSpecification; +import io.restassured.specification.ResponseSpecification; +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; + +@ExtendWith(LoanTestLifecycleExtension.class) +public class LoanProductShortNameValidationTest { + + private RequestSpecification requestSpec; + + @BeforeEach + public void setup() { + requestSpec = new RequestSpecBuilder().setContentType(JSON) + .addHeader("Authorization", "Basic " + loginIntoServerAndGetBase64EncodedAuthenticationKey()).build(); + } + + @Test + public void createLoanProductsWithSameShortName() { + String shortName = uniqueRandomStringGenerator("", 4); + createLoanProduct(shortName, successResponseSpec()); + createLoanProduct(shortName, validationFailedResponseSpec()); + } + + private ResponseSpecification successResponseSpec() { + return new ResponseSpecBuilder().expectStatusCode(200).build(); + } + + private ResponseSpecification validationFailedResponseSpec() { + return new ResponseSpecBuilder().expectBody("userMessageGlobalisationCode", equalTo("error.msg.product.loan.duplicate.short.name")) + .expectStatusCode(403).build(); + } + + private void createLoanProduct(String shortName, ResponseSpecification responseSpec) { + LoanTransactionHelper loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec); + + final String loanProductJSON = new LoanProductTestBuilder().withPrincipal("10000").withRepaymentAfterEvery("1") + .withShortName(shortName).withRepaymentTypeAsMonth().withInterestRateFrequencyTypeAsMonths().build(null); + + loanTransactionHelper.getLoanProductId(loanProductJSON); + } +} diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java index 180a74f67..d06dbd24d 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java @@ -75,7 +75,7 @@ public class LoanProductTestBuilder { private String inMultiplesOf = "0"; private String nameOfLoanProduct = Utils.uniqueRandomStringGenerator("LOAN_PRODUCT_", 6); - private final String shortName = Utils.uniqueRandomStringGenerator("", 4); + private String shortName = Utils.uniqueRandomStringGenerator("", 4); private String principal = "10000.00"; private String numberOfRepayments = "5"; private String repaymentFrequency = MONTHS; @@ -311,6 +311,11 @@ public class LoanProductTestBuilder { return this; } + public LoanProductTestBuilder withShortName(final String shortName) { + this.shortName = shortName; + return this; + } + public LoanProductTestBuilder withNumberOfRepayments(final String numberOfRepayment) { this.numberOfRepayments = numberOfRepayment; return this;