This is an automated email from the ASF dual-hosted git repository. adamsaghy pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/fineract.git
commit 2f79e971c88607bf3d1abcdd19bde73df9e9ae7e Author: MarianaDmytrivBinariks <[email protected]> AuthorDate: Tue Mar 17 18:44:05 2026 +0200 FINERACT-2455: added e2e test scenarios for Working Capital Delinquency Buckets --- .../data/delinquency/DelinquencyBucketType.java | 37 +++ .../data/delinquency/DelinquencyFrequencyType.java | 41 +++ .../delinquency/DelinquencyMinimumPayment.java | 36 +++ .../test/factory/WorkingCapitalRequestFactory.java | 17 + .../fineract/test/helper/ErrorMessageHelper.java | 12 + .../WorkingCapitalDelinquencyConfigStepDef.java | 350 +++++++++++++++++++++ .../test/stepdef/loan/WorkingCapitalStepDef.java | 63 ---- .../fineract/test/support/TestContextKey.java | 7 + .../global/DelinquencyGlobalInitializerStep.java | 33 ++ .../WorkingCapitalDelinquencyConfiguration.feature | 72 ++++- .../DelinquencyWritePlatformServiceImpl.java | 5 + 11 files changed, 604 insertions(+), 69 deletions(-) diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/delinquency/DelinquencyBucketType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/delinquency/DelinquencyBucketType.java new file mode 100644 index 0000000000..9a581aab82 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/delinquency/DelinquencyBucketType.java @@ -0,0 +1,37 @@ +/** + * 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.test.data.delinquency; + +import lombok.Getter; + +public enum DelinquencyBucketType { + + REGULAR(1L, "bucketType.regular"), WORKING_CAPITAL(2L, "bucketType.workingCapital"); + + @Getter + public final Long value; + + @Getter + public final String code; + + DelinquencyBucketType(Long value, String code) { + this.value = value; + this.code = code; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/delinquency/DelinquencyFrequencyType.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/delinquency/DelinquencyFrequencyType.java new file mode 100644 index 0000000000..1599e0b059 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/delinquency/DelinquencyFrequencyType.java @@ -0,0 +1,41 @@ +/** + * 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.test.data.delinquency; + +import lombok.Getter; + +public enum DelinquencyFrequencyType { + + DAYS(0, "delinquencyFrequencyType.days"), // + WEEKS(1, "delinquencyFrequencyType.weeks"), // + MONTHS(2, "delinquencyFrequencyType.months"), // + YEARS(3, "delinquencyFrequencyType.years"); + + @Getter + private final Integer value; + @Getter + private final String code; + + DelinquencyFrequencyType(final Integer value, final String code) { + this.value = value; + this.code = code; + } + +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/delinquency/DelinquencyMinimumPayment.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/delinquency/DelinquencyMinimumPayment.java new file mode 100644 index 0000000000..64bf6ca974 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/delinquency/DelinquencyMinimumPayment.java @@ -0,0 +1,36 @@ +/** + * 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.test.data.delinquency; + +import lombok.Getter; + +public enum DelinquencyMinimumPayment { + + PERCENTAGE(1L, "delinquencyMinimumPayment.percentage"), FLAT(2L, "delinquencyMinimumPayment.flat"); + + @Getter + private final Long value; + @Getter + private final String code; + + DelinquencyMinimumPayment(Long value, String code) { + this.value = value; + this.code = code; + } +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/WorkingCapitalRequestFactory.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/WorkingCapitalRequestFactory.java index cf859ff45c..b54d8f1647 100644 --- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/WorkingCapitalRequestFactory.java +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/factory/WorkingCapitalRequestFactory.java @@ -32,11 +32,16 @@ import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import lombok.RequiredArgsConstructor; +import org.apache.fineract.client.models.DelinquencyBucketRequest; +import org.apache.fineract.client.models.MinimumPaymentPeriodAndRule; import org.apache.fineract.client.models.PaymentAllocationOrder; import org.apache.fineract.client.models.PostAllowAttributeOverrides; import org.apache.fineract.client.models.PostPaymentAllocation; import org.apache.fineract.client.models.PostWorkingCapitalLoanProductsRequest; import org.apache.fineract.client.models.PutWorkingCapitalLoanProductsProductIdRequest; +import org.apache.fineract.test.data.delinquency.DelinquencyBucketType; +import org.apache.fineract.test.data.delinquency.DelinquencyFrequencyType; +import org.apache.fineract.test.data.delinquency.DelinquencyMinimumPayment; import org.apache.fineract.test.helper.Utils; import org.springframework.stereotype.Component; @@ -156,4 +161,16 @@ public class WorkingCapitalRequestFactory { return paymentAllocationData; } + public DelinquencyBucketRequest defaultWorkingCapitalDelinquencyBucketRequest() { + return new DelinquencyBucketRequest() // + .name("DB-WCL-" + Utils.randomStringGenerator(8)) // + .bucketType(DelinquencyBucketType.WORKING_CAPITAL.getValue().toString())// + .ranges(List.of(1L)) // + .minimumPaymentPeriodAndRule(new MinimumPaymentPeriodAndRule() // + .frequency(1L) // + .minimumPaymentType(DelinquencyMinimumPayment.PERCENTAGE.getValue()) // + .frequencyType(DelinquencyFrequencyType.WEEKS.getValue()) // + .minimumPayment(BigDecimal.valueOf(1.23D))); + } + } diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorMessageHelper.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorMessageHelper.java index 387d57bcff..5d34b506dc 100644 --- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorMessageHelper.java +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorMessageHelper.java @@ -1044,4 +1044,16 @@ public final class ErrorMessageHelper { public static String workingCapitalLoanProductIdentifiedDoesNotExistFailure(String identifierId) { return String.format("Working Capital Loan Product with identifier %s does not exist", identifierId); } + + public static String workingCapitalDelinquencyBucketCreateDuplicateNameFailure(Long identifierId) { + return String.format("Data integrity issue with resource: %d", identifierId); + } + + public static String workingCapitalDelinquencyBucketNotFoundFailure(Long id) { + return String.format("Delinquency bucket with id `%d` is not found.", id); + } + + public static String workingCapitalDelinquencyBucketDoesntExistFailure(Long id) { + return String.format("Delinquency bucket with id `%d` does not exist.", id); + } } diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/WorkingCapitalDelinquencyConfigStepDef.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/WorkingCapitalDelinquencyConfigStepDef.java new file mode 100644 index 0000000000..1f67100af0 --- /dev/null +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/WorkingCapitalDelinquencyConfigStepDef.java @@ -0,0 +1,350 @@ +/** + * 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.test.stepdef.loan; + +import static org.apache.fineract.client.feign.util.FeignCalls.fail; +import static org.apache.fineract.client.feign.util.FeignCalls.ok; +import static org.assertj.core.api.Assertions.assertThat; + +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.fineract.client.feign.FineractFeignClient; +import org.apache.fineract.client.feign.util.CallFailedRuntimeException; +import org.apache.fineract.client.models.DelinquencyBucketData; +import org.apache.fineract.client.models.DelinquencyBucketRequest; +import org.apache.fineract.client.models.DelinquencyMinimumPaymentPeriodAndRuleData; +import org.apache.fineract.client.models.DelinquencyRangeData; +import org.apache.fineract.client.models.MinimumPaymentPeriodAndRule; +import org.apache.fineract.client.models.PostDelinquencyBucketResponse; +import org.apache.fineract.test.data.delinquency.DelinquencyBucketType; +import org.apache.fineract.test.data.delinquency.DelinquencyFrequencyType; +import org.apache.fineract.test.data.delinquency.DelinquencyMinimumPayment; +import org.apache.fineract.test.factory.WorkingCapitalRequestFactory; +import org.apache.fineract.test.helper.ErrorMessageHelper; +import org.apache.fineract.test.helper.Utils; +import org.apache.fineract.test.stepdef.AbstractStepDef; +import org.apache.fineract.test.support.TestContext; +import org.apache.fineract.test.support.TestContextKey; +import org.assertj.core.api.SoftAssertions; +import org.springframework.beans.factory.annotation.Autowired; + +@Slf4j +@RequiredArgsConstructor +public class WorkingCapitalDelinquencyConfigStepDef extends AbstractStepDef { + + @Autowired + private WorkingCapitalRequestFactory workingCapitalRequestFactory; + + private final FineractFeignClient fineractFeignClient; + + @When("Admin Calls Delinquency Template") + public void adminCallsDelinquencyTemplate() { + DelinquencyBucketData template = ok(() -> fineractFeignClient.delinquencyRangeAndBucketsManagement().getTemplate3()); + assertThat(template).isNotNull(); + log.info("Template DelinquencyBucketData: {}", template); + } + + @Then("Get Delinquency Bucket With Template has the following values") + public void getDelinquencyBucketWithTemplateHasTheFollowingValues() { + Long id = TestContext.GLOBAL.get(TestContextKey.DELINQUENCY_BUCKET_ID); + DelinquencyBucketData delinquencyBucketData = ok(() -> fineractFeignClient.delinquencyRangeAndBucketsManagement() + .getDelinquencyBucketUniversal(id, Map.of("template", "true"))); + log.info("Get Template for Delinquency Bucket Data: {}", delinquencyBucketData); + } + + @When("Admin creates WC Delinquency Bucket With Values") + public void adminCreatesWCDelinquencyBucketWithValues() { + DelinquencyBucketRequest delinquencyBucketRequest = new DelinquencyBucketRequest() // + .name("DB-WCL-" + Utils.randomStringGenerator(12)) // + .bucketType(DelinquencyBucketType.WORKING_CAPITAL.getValue().toString())// + .ranges(List.of(1L)) // + .minimumPaymentPeriodAndRule(new MinimumPaymentPeriodAndRule() // + .frequency(1L) // + .minimumPaymentType(DelinquencyMinimumPayment.PERCENTAGE.getValue()) // + .frequencyType(DelinquencyFrequencyType.WEEKS.getValue()) // + .minimumPayment(BigDecimal.valueOf(1.23D))); // + PostDelinquencyBucketResponse ok = ok( + () -> fineractFeignClient.delinquencyRangeAndBucketsManagement().createDelinquencyBucket(delinquencyBucketRequest)); + assertThat(ok).isNotNull(); + assertThat(ok.getResourceId()).isNotNull(); + TestContext.GLOBAL.set(TestContextKey.DELINQUENCY_BUCKET_ID, ok.getResourceId()); + TestContext.GLOBAL.set(TestContextKey.DELINQUENCY_BUCKET_CREATE_REQUEST, delinquencyBucketRequest); + } + + @When("Admin creates WC Delinquency Bucket With Values for update") + public void adminCreatesWCDelinquencyBucketWithValuesForUpdate() { + DelinquencyBucketRequest delinquencyBucketRequest = workingCapitalRequestFactory.defaultWorkingCapitalDelinquencyBucketRequest() + .name("DB-WCL-" + Utils.randomStringGenerator(12)); // + PostDelinquencyBucketResponse ok = ok( + () -> fineractFeignClient.delinquencyRangeAndBucketsManagement().createDelinquencyBucket(delinquencyBucketRequest)); + assertThat(ok).isNotNull(); + assertThat(ok.getResourceId()).isNotNull(); + TestContext.GLOBAL.set(TestContextKey.DELINQUENCY_BUCKET_ID_FOR_UPDATE, ok.getResourceId()); + TestContext.GLOBAL.set(TestContextKey.DELINQUENCY_BUCKET_CREATE_REQUEST_FOR_UPDATE, delinquencyBucketRequest); + } + + @When("Admin failed to create WC Delinquency Bucket With duplicated name") + public void adminCreateWCDelinquencyBucketWithDuplicateNameFailure() { + Long delinquencyBucketIdForUpdate = TestContext.GLOBAL.get(TestContextKey.DELINQUENCY_BUCKET_ID_FOR_UPDATE); + DelinquencyBucketRequest delinquencyBucketRequestForUpdate = TestContext.GLOBAL + .get(TestContextKey.DELINQUENCY_BUCKET_CREATE_REQUEST_FOR_UPDATE); + String name = delinquencyBucketRequestForUpdate.getName(); + DelinquencyBucketRequest delinquencyBucketRequest = workingCapitalRequestFactory.defaultWorkingCapitalDelinquencyBucketRequest() + .name(name); // + String errorMessage = ErrorMessageHelper.workingCapitalDelinquencyBucketCreateDuplicateNameFailure(delinquencyBucketIdForUpdate); + checkCreateWCDelinquencyBucketWithInvalidDataFailure(delinquencyBucketRequest, errorMessage, 403); + } + + @Then("Admin failed to create a new WC Delinquency Bucket for field {string} with invalid data {string} results with an error {}") + public void createWCDelinquencyBucketWithInvalidDataFailed(String fieldName, String value, String errorMessage) { + final String workingCapitalDelinquencyBucketName = "DB-WCL-" + Utils.randomStringGenerator(12); // + final DelinquencyBucketRequest defaultWCDelinquencyBucketCreateRequest = workingCapitalRequestFactory + .defaultWorkingCapitalDelinquencyBucketRequest() // + .name(workingCapitalDelinquencyBucketName); // + + final DelinquencyBucketRequest wcDelinquencyBucketCreateRequestUpdated = setWCDelinquencyBucketCreateFieldValue( + defaultWCDelinquencyBucketCreateRequest, fieldName, value); + checkCreateWCDelinquencyBucketWithInvalidDataFailure(wcDelinquencyBucketCreateRequestUpdated, errorMessage, 400); + } + + @When("Admin modifies WC Delinquency Bucket With Values") + public void adminModifiesWCDelinquencyBucketWithValues() { + Long id = TestContext.GLOBAL.get(TestContextKey.DELINQUENCY_BUCKET_ID); + DelinquencyBucketData delinquencyBucketData = ok( + () -> fineractFeignClient.delinquencyRangeAndBucketsManagement().getDelinquencyBucket(id)); + DelinquencyBucketRequest delinquencyBucketRequest = new DelinquencyBucketRequest() // + .ranges(delinquencyBucketData.getRanges().stream().map(DelinquencyRangeData::getId).toList()) // + .name(delinquencyBucketData.getName()) // + .bucketType(DelinquencyBucketType.WORKING_CAPITAL.getValue().toString())// + .minimumPaymentPeriodAndRule(new MinimumPaymentPeriodAndRule() // + .minimumPayment(BigDecimal.valueOf(7.89D)) // + .minimumPaymentType(DelinquencyMinimumPayment.FLAT.getValue()) // + .frequencyType(DelinquencyFrequencyType.YEARS.getValue()) // + .frequency(4L) // + ); + ok(() -> fineractFeignClient.delinquencyRangeAndBucketsManagement().updateDelinquencyBucket(id, delinquencyBucketRequest)); + TestContext.GLOBAL.set(TestContextKey.DELINQUENCY_BUCKET_UPDATE_REQUEST, delinquencyBucketRequest); + } + + @Then("Admin failed to update WC Delinquency Bucket for field {string} with invalid data {string} results with an error {}") + public void updateWCDelinquencyBucketWithInvalidDataFailed(String fieldName, String value, String errorMessage) { + + Long delinquencyBucketIdForUpdate = TestContext.GLOBAL.get(TestContextKey.DELINQUENCY_BUCKET_ID_FOR_UPDATE); + DelinquencyBucketRequest delinquencyBucketRequestForUpdate = TestContext.GLOBAL + .get(TestContextKey.DELINQUENCY_BUCKET_CREATE_REQUEST_FOR_UPDATE); + String delinquencyBucketNameForUpdate = delinquencyBucketRequestForUpdate.getName(); + final DelinquencyBucketRequest defaultWCDelinquencyBucketCreateRequest = workingCapitalRequestFactory + .defaultWorkingCapitalDelinquencyBucketRequest().name(delinquencyBucketNameForUpdate); // + + final DelinquencyBucketRequest wcDelinquencyBucketCreateRequestUpdated = setWCDelinquencyBucketCreateFieldValue( + defaultWCDelinquencyBucketCreateRequest, fieldName, value); + checkUpdateWCDelinquencyBucketWithInvalidDataFailure(delinquencyBucketIdForUpdate, wcDelinquencyBucketCreateRequestUpdated, + errorMessage, 400); + } + + @When("Admin failed to update WC Delinquency Bucket With duplicated name") + public void adminUpdateWCDelinquencyBucketWithDuplicateNameFailure() { + Long delinquencyBucketIdForUpdate = TestContext.GLOBAL.get(TestContextKey.DELINQUENCY_BUCKET_ID_FOR_UPDATE); + Long delinquencyBucketId = TestContext.GLOBAL.get(TestContextKey.DELINQUENCY_BUCKET_ID); + DelinquencyBucketRequest delinquencyBucketRequestForUpdate = TestContext.GLOBAL + .get(TestContextKey.DELINQUENCY_BUCKET_CREATE_REQUEST); + String name = delinquencyBucketRequestForUpdate.getName(); + DelinquencyBucketRequest delinquencyBucketRequest = workingCapitalRequestFactory.defaultWorkingCapitalDelinquencyBucketRequest() // + .name(name); // + String errorMessage = ErrorMessageHelper.workingCapitalDelinquencyBucketCreateDuplicateNameFailure(delinquencyBucketId); + checkUpdateWCDelinquencyBucketWithInvalidDataFailure(delinquencyBucketIdForUpdate, delinquencyBucketRequest, errorMessage, 403); + } + + @Then("Check created Delinquency Bucket has the following values") + public void checkCreatedDelinquencyBucketHasTheFollowingValues() { + Long id = TestContext.GLOBAL.get(TestContextKey.DELINQUENCY_BUCKET_ID); + DelinquencyBucketData delinquencyBucketData = ok( + () -> fineractFeignClient.delinquencyRangeAndBucketsManagement().getDelinquencyBucket(id)); + DelinquencyBucketRequest delinquencyBucketRequest = TestContext.GLOBAL.get(TestContextKey.DELINQUENCY_BUCKET_CREATE_REQUEST); + checkDelinquencyBucketData(delinquencyBucketRequest, delinquencyBucketData); + log.info("Get DelinquencyBucketData : {} matches with create request data: {}", delinquencyBucketData, delinquencyBucketRequest); + } + + @Then("Check updated Delinquency Bucket has the following values") + public void checkUpdatedDelinquencyBucketHasTheFollowingValues() { + Long id = TestContext.GLOBAL.get(TestContextKey.DELINQUENCY_BUCKET_ID); + DelinquencyBucketData delinquencyBucketData = ok( + () -> fineractFeignClient.delinquencyRangeAndBucketsManagement().getDelinquencyBucket(id)); + DelinquencyBucketRequest delinquencyBucketRequest = TestContext.GLOBAL.get(TestContextKey.DELINQUENCY_BUCKET_UPDATE_REQUEST); + checkDelinquencyBucketData(delinquencyBucketRequest, delinquencyBucketData); + log.info("Get DelinquencyBucketData : {} matches with update request data: {}", delinquencyBucketData, delinquencyBucketRequest); + } + + @Then("Admin failed to retrieve WC Delinquency Bucket with id {int} that is not found") + public void adminRetrieveWCDelinquencyBucketAlreadyDeletedFailure(Integer id) { + checkRetrieveWCDelinquencyBucketNotFoundFailure(Long.valueOf(id)); + } + + @When("Admin deletes WC Delinquency Bucket With Values") + public void adminDeletesWCDelinquencyBucketWithValues() { + Long id = TestContext.GLOBAL.get(TestContextKey.DELINQUENCY_BUCKET_ID); + ok(() -> fineractFeignClient.delinquencyRangeAndBucketsManagement().deleteDelinquencyBucket(id)); + } + + @When("Admin deletes WC Delinquency Bucket With Values for update") + public void adminDeletesWCDelinquencyBucketWithValuesForUpdate() { + Long id = TestContext.GLOBAL.get(TestContextKey.DELINQUENCY_BUCKET_ID_FOR_UPDATE); + ok(() -> fineractFeignClient.delinquencyRangeAndBucketsManagement().deleteDelinquencyBucket(id)); + } + + @Then("Admin failed to delete WC Delinquency Bucket that is already deleted") + public void adminDeleteWCDelinquencyBucketAlreadyDeletedFailure() { + Long id = TestContext.GLOBAL.get(TestContextKey.DELINQUENCY_BUCKET_ID_FOR_UPDATE); + checkDeleteWCDelinquencyBucketDoesntExistFailure(id); + } + + @Then("Admin failed to delete WC Delinquency Bucket with id {int} that doesn't exist") + public void adminDeleteWCDelinquencyBucketAlreadyDeletedFailure(Integer id) { + checkDeleteWCDelinquencyBucketDoesntExistFailure(Long.valueOf(id)); + } + + @Then("Admin failed to retrieve WC Delinquency Bucket that is already deleted") + public void adminRetrieveWCDelinquencyBucketAlreadyDeletedFailure() { + Long id = TestContext.GLOBAL.get(TestContextKey.DELINQUENCY_BUCKET_ID_FOR_UPDATE); + checkRetrieveWCDelinquencyBucketNotFoundFailure(id); + } + + public void checkRetrieveWCDelinquencyBucketNotFoundFailure(Long id) { + CallFailedRuntimeException exception = fail( + () -> fineractFeignClient.delinquencyRangeAndBucketsManagement().getDelinquencyBucket(id)); + String errorMessage = ErrorMessageHelper.workingCapitalDelinquencyBucketNotFoundFailure(id); + assertThat(exception.getStatus()).as(errorMessage).isEqualTo(404); + assertThat(exception.getDeveloperMessage()).contains(errorMessage); + } + + public void checkCreateWCDelinquencyBucketWithInvalidDataFailure(DelinquencyBucketRequest defaultWCDelinquencyBucketCreateRequest, + String errorMessage, int errorCode) { + CallFailedRuntimeException exception = fail(() -> fineractFeignClient.delinquencyRangeAndBucketsManagement() + .createDelinquencyBucket(defaultWCDelinquencyBucketCreateRequest)); + assertThat(exception.getStatus()).as(ErrorMessageHelper.incorrectExpectedValueInResponse()).isEqualTo(errorCode); + assertThat(exception.getDeveloperMessage()).contains(errorMessage); + } + + public DelinquencyBucketRequest setWCDelinquencyBucketCreateFieldValue(DelinquencyBucketRequest delinquencyBucketRequest, + String fieldName, String fieldValue) { + if (fieldValue.equals("null")) { + fieldValue = null; + } + Long valueLong = null; + BigDecimal valueBigDecimal = null; + if (fieldName.equalsIgnoreCase("frequency") || fieldName.equalsIgnoreCase("minimumPaymentType")) { + valueLong = fieldValue != null ? Long.valueOf(fieldValue) : null; + } + if (fieldName.equalsIgnoreCase("minimumPayment")) { + valueBigDecimal = fieldValue != null ? new BigDecimal(fieldValue) : null; + } + List<Long> valueArrayList = new ArrayList<>(); + if (fieldName.equalsIgnoreCase("ranges")) { + assert fieldValue != null; + valueArrayList = fieldValue.equalsIgnoreCase("[]") ? new ArrayList<>() : new ArrayList<>(List.of(Long.valueOf(fieldValue))); + } + MinimumPaymentPeriodAndRule minimumPaymentPeriodAndRuleRequest = delinquencyBucketRequest.getMinimumPaymentPeriodAndRule(); + assert minimumPaymentPeriodAndRuleRequest != null; + + switch (fieldName) { + case "name": + delinquencyBucketRequest.setName(fieldValue); + break; + case "ranges": + delinquencyBucketRequest.setRanges(valueArrayList); + break; + case "bucketType": + delinquencyBucketRequest.setBucketType(fieldValue); + break; + case "minimumPaymentPeriodAndRule": + delinquencyBucketRequest.setMinimumPaymentPeriodAndRule(fieldValue == null ? null : minimumPaymentPeriodAndRuleRequest); + break; + case "frequency": + minimumPaymentPeriodAndRuleRequest.setFrequency(valueLong); + break; + case "frequencyType": + minimumPaymentPeriodAndRuleRequest.setFrequencyType(fieldValue == null ? null : Integer.valueOf(fieldValue)); + break; + case "minimumPayment": + minimumPaymentPeriodAndRuleRequest.setMinimumPayment(valueBigDecimal); + break; + case "minimumPaymentType": + minimumPaymentPeriodAndRuleRequest.setMinimumPaymentType(valueLong); + break; + default: + break; + } + return delinquencyBucketRequest; + } + + public void checkDelinquencyBucketData(DelinquencyBucketRequest delinquencyBucketRequest, DelinquencyBucketData delinquencyBucketData) { + SoftAssertions assertions = new SoftAssertions(); + assertions.assertThat(delinquencyBucketRequest.getName()).isEqualTo(delinquencyBucketData.getName()); + assert delinquencyBucketRequest.getBucketType() != null; + assertions.assertThat(Long.valueOf(delinquencyBucketRequest.getBucketType())).isEqualTo(delinquencyBucketData.getBucketType()); + + // minimum payment period and rule + MinimumPaymentPeriodAndRule minimumPaymentPeriodAndRuleRequest = delinquencyBucketRequest.getMinimumPaymentPeriodAndRule(); + DelinquencyMinimumPaymentPeriodAndRuleData minimumPaymentPeriodAndRuleResponse = delinquencyBucketData + .getMinimumPaymentPeriodAndRule(); + assert minimumPaymentPeriodAndRuleRequest != null; + assert minimumPaymentPeriodAndRuleResponse != null; + assertions.assertThat( + minimumPaymentPeriodAndRuleRequest.getMinimumPayment().compareTo(minimumPaymentPeriodAndRuleResponse.getMinimumPayment())) + .isEqualTo(0); + assert minimumPaymentPeriodAndRuleResponse.getMinimumPaymentType() != null; + assertions.assertThat(Long.valueOf(minimumPaymentPeriodAndRuleRequest.getMinimumPaymentType())) + .isEqualTo(minimumPaymentPeriodAndRuleResponse.getMinimumPaymentType().getId()); + assertions.assertThat(minimumPaymentPeriodAndRuleRequest.getFrequency()) + .isEqualTo(minimumPaymentPeriodAndRuleResponse.getFrequency()); + assert minimumPaymentPeriodAndRuleResponse.getFrequencyType() != null; + assertions.assertThat(Long.valueOf(minimumPaymentPeriodAndRuleRequest.getFrequencyType())) + .isEqualTo(minimumPaymentPeriodAndRuleResponse.getFrequencyType().getId()); + + // ranges + assert delinquencyBucketData.getRanges() != null; + assertions.assertThat(delinquencyBucketRequest.getRanges()) + .containsAll(delinquencyBucketData.getRanges().stream().map(DelinquencyRangeData::getId).toList()); + + assertions.assertAll(); + } + + public void checkUpdateWCDelinquencyBucketWithInvalidDataFailure(Long id, DelinquencyBucketRequest defaultWCDelinquencyBucketRequest, + String errorMessage, int errorCode) { + CallFailedRuntimeException exception = fail(() -> fineractFeignClient.delinquencyRangeAndBucketsManagement() + .updateDelinquencyBucket(id, defaultWCDelinquencyBucketRequest)); + assertThat(exception.getStatus()).as(ErrorMessageHelper.incorrectExpectedValueInResponse()).isEqualTo(errorCode); + assertThat(exception.getDeveloperMessage()).contains(errorMessage); + } + + public void checkDeleteWCDelinquencyBucketDoesntExistFailure(Long id) { + CallFailedRuntimeException exception = fail( + () -> fineractFeignClient.delinquencyRangeAndBucketsManagement().deleteDelinquencyBucket(id)); + String errorMessage = ErrorMessageHelper.workingCapitalDelinquencyBucketDoesntExistFailure(id); + assertThat(exception.getStatus()).as(errorMessage).isEqualTo(404); + assertThat(exception.getDeveloperMessage()).contains(errorMessage); + } + +} diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/WorkingCapitalStepDef.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/WorkingCapitalStepDef.java index 759c11404d..d2fc04ce2c 100644 --- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/WorkingCapitalStepDef.java +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/WorkingCapitalStepDef.java @@ -25,7 +25,6 @@ import static org.assertj.core.api.Assertions.assertThat; import io.cucumber.java.en.Then; import io.cucumber.java.en.When; import java.math.BigDecimal; -import java.util.List; import java.util.Map; import java.util.UUID; import lombok.RequiredArgsConstructor; @@ -34,15 +33,10 @@ import org.apache.fineract.client.feign.FineractFeignClient; import org.apache.fineract.client.feign.services.WorkingCapitalLoanProductsApi; import org.apache.fineract.client.feign.util.CallFailedRuntimeException; import org.apache.fineract.client.models.DeleteWorkingCapitalLoanProductsProductIdResponse; -import org.apache.fineract.client.models.DelinquencyBucketData; -import org.apache.fineract.client.models.DelinquencyBucketRequest; -import org.apache.fineract.client.models.DelinquencyRangeData; import org.apache.fineract.client.models.GetConfigurableAttributes; import org.apache.fineract.client.models.GetPaymentAllocation; import org.apache.fineract.client.models.GetWorkingCapitalLoanProductsProductIdResponse; -import org.apache.fineract.client.models.MinimumPaymentPeriodAndRule; import org.apache.fineract.client.models.PostAllowAttributeOverrides; -import org.apache.fineract.client.models.PostDelinquencyBucketResponse; import org.apache.fineract.client.models.PostWorkingCapitalLoanProductsRequest; import org.apache.fineract.client.models.PostWorkingCapitalLoanProductsResponse; import org.apache.fineract.client.models.PutWorkingCapitalLoanProductsProductIdRequest; @@ -807,61 +801,4 @@ public class WorkingCapitalStepDef extends AbstractStepDef { .contains(ErrorMessageHelper.workingCapitalLoanProductIdentifiedDoesNotExistFailure(String.valueOf(productId))); } - @When("Admin Calls Delinquency Template") - public void adminCallsDelinquencyTemplate() { - DelinquencyBucketData template = ok(() -> fineractFeignClient.delinquencyRangeAndBucketsManagement().getTemplate3()); - log.info("Template DelinquencyBucketData: {}", template); - } - - @When("Admin creates WC Delinquency Bucket With Values") - public void adminCreatesWCDelinquencyBucketWithValues() { - DelinquencyBucketRequest delinquencyBucketRequest = new DelinquencyBucketRequest() // - .name("DB-" + System.currentTimeMillis()) // - .bucketType("2").ranges(List.of(1L)).minimumPaymentPeriodAndRule(new MinimumPaymentPeriodAndRule().frequency(1L) - .frequencyType(1).minimumPayment(BigDecimal.valueOf(1.23D)).minimumPaymentType(1L)); - PostDelinquencyBucketResponse ok = ok( - () -> fineractFeignClient.delinquencyRangeAndBucketsManagement().createDelinquencyBucket(delinquencyBucketRequest)); - assertThat(ok).isNotNull(); - assertThat(ok.getResourceId()).isNotNull(); - testContext().get().put("DELINQUENCY_BUCKET_ID", ok.getResourceId()); - } - - @Then("Get Delinquency Bucket has the following values") - public void getDelinquencyBucketHasTheFollowingValues() { - Long id = (Long) testContext().get().get("DELINQUENCY_BUCKET_ID"); - DelinquencyBucketData delinquencyBucketData = ok( - () -> fineractFeignClient.delinquencyRangeAndBucketsManagement().getDelinquencyBucket(id)); - log.info("Get DelinquencyBucketData: {}", delinquencyBucketData); - } - - @Then("Get Delinquency Bucket With Template has the following values") - public void getDelinquencyBucketWithTemplateHasTheFollowingValues() { - Long id = (Long) testContext().get().get("DELINQUENCY_BUCKET_ID"); - DelinquencyBucketData delinquencyBucketData = ok(() -> fineractFeignClient.delinquencyRangeAndBucketsManagement() - .getDelinquencyBucketUniversal(id, Map.of("template", "true"))); - log.info("Get With Template DelinquencyBucketData: {}", delinquencyBucketData); - } - - @When("Admin modifies WC Delinquency Bucket With Values") - public void adminModifiesWCDelinquencyBucketWithValues() { - Long id = (Long) testContext().get().get("DELINQUENCY_BUCKET_ID"); - DelinquencyBucketData delinquencyBucketData = ok( - () -> fineractFeignClient.delinquencyRangeAndBucketsManagement().getDelinquencyBucket(id)); - DelinquencyBucketRequest request = new DelinquencyBucketRequest() // - .ranges(delinquencyBucketData.getRanges().stream().map(DelinquencyRangeData::getId).toList()) - // 1 Regular - // 2 Working Capital - .name(delinquencyBucketData.getName()).bucketType("2").minimumPaymentPeriodAndRule(new MinimumPaymentPeriodAndRule() // - .minimumPayment(BigDecimal.valueOf(7.89D)).minimumPaymentType(2L) // - .frequencyType(3) // - .frequency(4L) // - ); - ok(() -> fineractFeignClient.delinquencyRangeAndBucketsManagement().updateDelinquencyBucket(id, request)); - } - - @When("Admin deletes WC Delinquency Bucket With Values") - public void adminDeletesWCDelinquencyBucketWithValues() { - Long id = (Long) testContext().get().get("DELINQUENCY_BUCKET_ID"); - ok(() -> fineractFeignClient.delinquencyRangeAndBucketsManagement().deleteDelinquencyBucket(id)); - } } diff --git a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java index 2b3f9be13e..d9ec674020 100644 --- a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java +++ b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java @@ -325,4 +325,11 @@ public abstract class TestContextKey { public static final String WORKING_CAPITAL_LOAN_PRODUCT_CREATE_RESPONSE = "workingCapitalLoanProductCreateResponse"; public static final String WORKING_CAPITAL_LOAN_PRODUCT_UPDATE_REQUEST = "workingCapitalLoanProductUpdateRequest"; public static final String WORKING_CAPITAL_LOAN_PRODUCT_UPDATE_RESPONSE = "workingCapitalLoanProductUpdateResponse"; + public static final String DELINQUENCY_BUCKET_ID = "delinquencyBucketId"; + public static final String DELINQUENCY_BUCKET_CREATE_REQUEST = "delinquencyBucketCreateRequest"; + public static final String DELINQUENCY_BUCKET_UPDATE_REQUEST = "delinquencyBucketUpdateRequest"; + + public static final String DELINQUENCY_BUCKET_ID_FOR_UPDATE = "delinquencyBucketIdForUpdate"; + public static final String DELINQUENCY_BUCKET_CREATE_REQUEST_FOR_UPDATE = "delinquencyBucketCreateRequestForUpdate"; + public static final String DELINQUENCY_BUCKET_CREATE_RESPONSE_FOR_UPDATE_DUPLICATE = "delinquencyBucketUpdateRequestForUpdateDuplicate"; } diff --git a/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/initializer/global/DelinquencyGlobalInitializerStep.java b/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/initializer/global/DelinquencyGlobalInitializerStep.java index f022a26a94..ff9ef82c21 100644 --- a/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/initializer/global/DelinquencyGlobalInitializerStep.java +++ b/fineract-e2e-tests-runner/src/test/java/org/apache/fineract/test/initializer/global/DelinquencyGlobalInitializerStep.java @@ -21,6 +21,7 @@ package org.apache.fineract.test.initializer.global; import static org.apache.fineract.client.feign.util.FeignCalls.executeVoid; import static org.apache.fineract.client.feign.util.FeignCalls.ok; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -32,7 +33,11 @@ import org.apache.fineract.client.models.DelinquencyBucketData; import org.apache.fineract.client.models.DelinquencyBucketRequest; import org.apache.fineract.client.models.DelinquencyRangeData; import org.apache.fineract.client.models.DelinquencyRangeRequest; +import org.apache.fineract.client.models.MinimumPaymentPeriodAndRule; import org.apache.fineract.client.models.PostDelinquencyRangeResponse; +import org.apache.fineract.test.data.delinquency.DelinquencyBucketType; +import org.apache.fineract.test.data.delinquency.DelinquencyFrequencyType; +import org.apache.fineract.test.data.delinquency.DelinquencyMinimumPayment; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @@ -46,6 +51,7 @@ public class DelinquencyGlobalInitializerStep implements FineractGlobalInitializ public static final String DEFAULT_LOCALE = "en"; public static final List<Integer> DEFAULT_DELINQUENCY_RANGES = Arrays.asList(1, 3, 30, 60, 90, 120, 150, 180, 240); public static final String DEFAULT_DELINQUENCY_BUCKET_NAME = "Default delinquency bucket"; + public static final String DEFAULT_WC_DELINQUENCY_BUCKET_NAME = "Default Working Capital delinquency bucket"; private final FineractFeignClient fineractClient; @@ -55,6 +61,7 @@ public class DelinquencyGlobalInitializerStep implements FineractGlobalInitializ public void initialize() { setDefaultDelinquencyRanges(); setDefaultDelinquencyBucket(); + setDefaultWCDelinquencyBucket(); } public void setDefaultDelinquencyRanges() { @@ -133,4 +140,30 @@ public class DelinquencyGlobalInitializerStep implements FineractGlobalInitializ executeVoid(() -> fineractClient.delinquencyRangeAndBucketsManagement().createDelinquencyBucket(postDelinquencyBucketRequest, Map.of())); } + + public void setDefaultWCDelinquencyBucket() { + try { + List<DelinquencyBucketData> existingBuckets = fineractClient.delinquencyRangeAndBucketsManagement() + .getDelinquencyBuckets(Map.of()); + boolean bucketExists = existingBuckets.stream().anyMatch(b -> DEFAULT_WC_DELINQUENCY_BUCKET_NAME.equals(b.getName())); + + if (bucketExists) { + return; + } + } catch (Exception e) { + log.debug("Could not retrieve existing working capital delinquency buckets, will create default bucket", e); + } + + DelinquencyBucketRequest postDelinquencyBucketWCRequest = new DelinquencyBucketRequest().name(DEFAULT_WC_DELINQUENCY_BUCKET_NAME) + .bucketType(DelinquencyBucketType.WORKING_CAPITAL.getValue().toString())// + .ranges(List.of(1L)) // + .minimumPaymentPeriodAndRule(new MinimumPaymentPeriodAndRule() // + .frequency(1L) // + .minimumPaymentType(DelinquencyMinimumPayment.PERCENTAGE.getValue()) // + .frequencyType(DelinquencyFrequencyType.MONTHS.getValue()) // + .minimumPayment(BigDecimal.valueOf(1.23))); // + + executeVoid(() -> fineractClient.delinquencyRangeAndBucketsManagement().createDelinquencyBucket(postDelinquencyBucketWCRequest, + Map.of())); + } } diff --git a/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquencyConfiguration.feature b/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquencyConfiguration.feature index c619212217..81b935ce4e 100644 --- a/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquencyConfiguration.feature +++ b/fineract-e2e-tests-runner/src/test/resources/features/WorkingCapitalDelinquencyConfiguration.feature @@ -1,12 +1,72 @@ -@WCDelinquencyCFeature @WC +@WorkingCapitalDelinquencyManagementFeature Feature: Working Capital Delinquency Configuration - @TestRailId:CXXXX - Scenario: Verify Working Capital Delinquency Configuration CRUD + @TestRailId:C72329 + Scenario: Verify Working Capital Delinquency Configuration CRUD - UC1 When Admin Calls Delinquency Template When Admin creates WC Delinquency Bucket With Values - Then Get Delinquency Bucket has the following values + Then Check created Delinquency Bucket has the following values Then Get Delinquency Bucket With Template has the following values When Admin modifies WC Delinquency Bucket With Values - Then Get Delinquency Bucket has the following values - When Admin deletes WC Delinquency Bucket With Values \ No newline at end of file + Then Check updated Delinquency Bucket has the following values + When Admin deletes WC Delinquency Bucket With Values + + @TestRailId:C72330 + Scenario Outline: Verify Working Capital Delinquency Configuration create with invalid data shall outcome with error - UC2 + Then Admin failed to create a new WC Delinquency Bucket for field "<wc_db_field_name_invalid>" with invalid data <wc_db_field_value_invalid> results with an error <wc_db_error_message> + + Examples: + | wc_db_field_name_invalid | wc_db_field_value_invalid | wc_db_error_message | + | name | "null" | The parameter `name` is mandatory. | + | name | "" | The parameter `name` is mandatory. | + | ranges | "[]" | The parameter `ranges` cannot be empty. You must select at least one. | + | bucketType | "0" | The parameter `bucketType` must be one of [ 1, 2 ] . | + | minimumPayment | "-1" | The parameter `minimumPayment` must be greater than or equal to 0. | + | minimumPaymentType | "9" | The parameter `minimumPaymentType` must be between 1 and 2. | + | frequencyType | "5" | The parameter `frequencyType` must be between 0 and 3. | + | minimumPaymentPeriodAndRule | "null" | The parameter `minimumPaymentPeriodAndRule` is mandatory. | + + @TestRailId:C72331 + Scenario: Verify Working Capital Delinquency Configuration create validation with existing name outcomes with error - UC3 + When Admin creates WC Delinquency Bucket With Values for update + Then Admin failed to create WC Delinquency Bucket With duplicated name + + @TestRailId:C72332 + Scenario Outline: Verify Working Capital Delinquency Configuration update with invalid data shall outcome with error - UC4 + Then Admin failed to update WC Delinquency Bucket for field "<wc_db_field_name_invalid>" with invalid data <wc_db_field_value_invalid> results with an error <wc_db_error_message> + + Examples: + | wc_db_field_name_invalid | wc_db_field_value_invalid | wc_db_error_message | + | ranges | "[]" | The parameter `ranges` cannot be empty. You must select at least one. | + | bucketType | "9" | The parameter `bucketType` must be one of [ 1, 2 ] . | + | minimumPayment | "-1" | The parameter `minimumPayment` must be greater than or equal to 0. | + | minimumPaymentType | "0" | The parameter `minimumPaymentType` must be between 1 and 2. | + | frequencyType | "8" | The parameter `frequencyType` must be between 0 and 3. | + + @TestRailId:C72333 + Scenario: Verify Working Capital Delinquency Configuration update validation with existing name outcomes with error - UC5 + When Admin creates WC Delinquency Bucket With Values + Then Admin failed to update WC Delinquency Bucket With duplicated name + When Admin deletes WC Delinquency Bucket With Values + + @TestRailId:C72334 + Scenario: Verify deleting Working Capital Delinquency Configuration that is already deleted failure - UC6 + When Admin deletes WC Delinquency Bucket With Values for update + Then Admin failed to delete WC Delinquency Bucket that is already deleted + Then Admin failed to retrieve WC Delinquency Bucket that is already deleted + + @TestRailId:C72335 + Scenario Outline: Verify Working capital Delinquency Bucket delete with invalid data shall outcome with error - validation check with id - UC7 + Then Admin failed to delete WC Delinquency Bucket with id <wcp_field_name_incorrect_value> that doesn't exist + Examples: + | wcp_field_name_incorrect_value | + | 103284 | + | 0 | + + @TestRailId:C72336 + Scenario Outline: Verify Working capital Delinquency Bucket retrieve with invalid data shall outcome with error - validation check with id - UC8 + Then Admin failed to retrieve WC Delinquency Bucket with id <wcp_field_name_incorrect_value> that is not found + Examples: + | wcp_field_name_incorrect_value | + | 565465 | + | 0 | diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java index 91c15e332a..235aa9ebce 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java @@ -375,6 +375,11 @@ public class DelinquencyWritePlatformServiceImpl implements DelinquencyWritePlat private DelinquencyBucket updateDelinquencyBucket(DelinquencyBucket delinquencyBucket, DelinquencyBucketData data, Map<String, Object> changes) { if (!data.getName().equalsIgnoreCase(delinquencyBucket.getName())) { + Optional<DelinquencyBucket> existingEntityByName = repositoryBucket.findByName(data.getName()); + if (existingEntityByName.isPresent()) { + throw new PlatformDataIntegrityException("error.msg.data.integrity.issue.entity.duplicated", + "Data integrity issue with resource: " + existingEntityByName.get().getId()); + } delinquencyBucket.setName(data.getName()); changes.put(DelinquencyApiConstants.NAME_PARAM_NAME, data.getName()); }
